aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-01-07 11:42:54 +0100
committerHarald Welte <laforge@gnumonks.org>2010-01-07 11:42:54 +0100
commit7ea3caeb81b9db57b5e56ad714a4a704d242bb1b (patch)
tree8e87652980d2920334d0679e4f925fbc02fff55a
parent766f0422badf1a0484635c3a3cee15cef1780edb (diff)
parentef24dff2a22c907f08a24b19773dde5ce20ba5d6 (diff)
Merge remote branch 'origin/master' into gprs
Conflicts: openbsc/include/openbsc/debug.h openbsc/src/Makefile.am openbsc/src/gsm_04_08.c openbsc/src/input/ipaccess.c openbsc/src/ipaccess-config.c
-rw-r--r--openbsc/.gitignore6
-rw-r--r--openbsc/include/openbsc/Makefile.am2
-rw-r--r--openbsc/include/openbsc/abis_nm.h8
-rw-r--r--openbsc/include/openbsc/chan_alloc.h14
-rw-r--r--openbsc/include/openbsc/comp128.h22
-rw-r--r--openbsc/include/openbsc/db.h15
-rw-r--r--openbsc/include/openbsc/debug.h135
-rw-r--r--openbsc/include/openbsc/gsm_04_08.h2
-rw-r--r--openbsc/include/openbsc/gsm_data.h87
-rw-r--r--openbsc/include/openbsc/gsm_subscriber.h2
-rw-r--r--openbsc/include/openbsc/gsm_utils.h7
-rw-r--r--openbsc/include/openbsc/ipaccess.h54
-rw-r--r--openbsc/include/openbsc/meas_rep.h1
-rw-r--r--openbsc/include/openbsc/signal.h11
-rw-r--r--openbsc/include/openbsc/silent_call.h5
-rw-r--r--openbsc/include/openbsc/statistics.h31
-rw-r--r--openbsc/include/openbsc/telnet_interface.h3
-rw-r--r--openbsc/include/vty/command.h2
-rw-r--r--openbsc/include/vty/vector.h2
-rw-r--r--openbsc/src/Makefile.am24
-rw-r--r--openbsc/src/abis_nm.c220
-rw-r--r--openbsc/src/abis_rsl.c185
-rw-r--r--openbsc/src/bs11_config.c13
-rw-r--r--openbsc/src/bsc_hack.c43
-rw-r--r--openbsc/src/bsc_init.c25
-rw-r--r--openbsc/src/bsc_mgcp.c7
-rw-r--r--openbsc/src/chan_alloc.c91
-rw-r--r--openbsc/src/comp128.c230
-rw-r--r--openbsc/src/db.c464
-rw-r--r--openbsc/src/debug.c354
-rw-r--r--openbsc/src/e1_input.c12
-rw-r--r--openbsc/src/gsm_04_08.c126
-rw-r--r--openbsc/src/gsm_04_08_utils.c97
-rw-r--r--openbsc/src/gsm_04_11.c127
-rw-r--r--openbsc/src/gsm_data.c98
-rw-r--r--openbsc/src/gsm_subscriber.c11
-rw-r--r--openbsc/src/gsm_subscriber_base.c4
-rw-r--r--openbsc/src/handover_logic.c20
-rw-r--r--openbsc/src/input/ipaccess.c53
-rw-r--r--openbsc/src/ipaccess/ipaccess-config.c (renamed from openbsc/src/ipaccess-config.c)316
-rw-r--r--openbsc/src/ipaccess/ipaccess-find.c (renamed from openbsc/src/ipaccess-find.c)0
-rw-r--r--openbsc/src/ipaccess/ipaccess-firmware.c123
-rw-r--r--openbsc/src/ipaccess/ipaccess-proxy.c1127
-rw-r--r--openbsc/src/msgb.c7
-rw-r--r--openbsc/src/paging.c14
-rw-r--r--openbsc/src/rrlp.c8
-rw-r--r--openbsc/src/rtp_proxy.c3
-rw-r--r--openbsc/src/silent_call.c54
-rw-r--r--openbsc/src/statistics.c70
-rw-r--r--openbsc/src/system_information.c24
-rw-r--r--openbsc/src/talloc_ctx.c4
-rw-r--r--openbsc/src/telnet_interface.c10
-rw-r--r--openbsc/src/token_auth.c4
-rw-r--r--openbsc/src/transaction.c11
-rw-r--r--openbsc/src/vty/command.c44
-rw-r--r--openbsc/src/vty/vector.c12
-rw-r--r--openbsc/src/vty/vty.c2
-rw-r--r--openbsc/src/vty_interface.c415
-rw-r--r--openbsc/src/vty_interface_layer3.c198
-rw-r--r--openbsc/tests/channel/Makefile.am3
-rw-r--r--openbsc/tests/debug/Makefile.am2
-rw-r--r--openbsc/tests/debug/debug_test.c21
-rw-r--r--openbsc/tests/sccp/sccp_test.c2
-rwxr-xr-xopenbsc/tools/hlrstat.pl25
-rw-r--r--rrlp-ephemeris/.gitignore4
-rw-r--r--rrlp-ephemeris/COPYING2
-rw-r--r--rrlp-ephemeris/Makefile44
-rw-r--r--rrlp-ephemeris/asn1/MAP-BS-Code.asn131
-rw-r--r--rrlp-ephemeris/asn1/MAP-CommonDataTypes.asn633
-rw-r--r--rrlp-ephemeris/asn1/MAP-ER-DataTypes.asn415
-rw-r--r--rrlp-ephemeris/asn1/MAP-ExtensionDataTypes.asn74
-rw-r--r--rrlp-ephemeris/asn1/MAP-LCS-DataTypes.asn657
-rw-r--r--rrlp-ephemeris/asn1/MAP-MS-DataTypes.asn2780
-rw-r--r--rrlp-ephemeris/asn1/MAP-OM-DataTypes.asn216
-rw-r--r--rrlp-ephemeris/asn1/MAP-SM-DataTypes.asn270
-rw-r--r--rrlp-ephemeris/asn1/MAP-SS-Code.asn190
-rw-r--r--rrlp-ephemeris/asn1/MAP-SS-DataTypes.asn342
-rw-r--r--rrlp-ephemeris/asn1/MAP-TS-Code.asn92
-rw-r--r--rrlp-ephemeris/asn1/RRLP-Components.asn1488
-rw-r--r--rrlp-ephemeris/asn1/RRLP-Messages.asn38
-rw-r--r--rrlp-ephemeris/asn1/patch-rrlp-components.diff36
-rw-r--r--rrlp-ephemeris/asn1c_patches/00_add_enumerated_verbose.diff56
-rw-r--r--rrlp-ephemeris/asn1c_patches/01_fix_per_encoding_dieter.diff17
-rw-r--r--rrlp-ephemeris/data.ubxbin0 -> 2872 bytes
-rwxr-xr-xrrlp-ephemeris/get-test-data.sh17
-rw-r--r--rrlp-ephemeris/gpl-2.0.txt339
-rw-r--r--rrlp-ephemeris/gpl-3.0.txt674
-rw-r--r--rrlp-ephemeris/gps.c126
-rw-r--r--rrlp-ephemeris/gps.h190
-rw-r--r--rrlp-ephemeris/main.c99
-rw-r--r--rrlp-ephemeris/rrlp.c648
-rw-r--r--rrlp-ephemeris/rrlp.h64
-rw-r--r--rrlp-ephemeris/ubx-parse.c177
-rw-r--r--rrlp-ephemeris/ubx-parse.h45
-rw-r--r--rrlp-ephemeris/ubx.c81
-rw-r--r--rrlp-ephemeris/ubx.h232
-rw-r--r--wireshark/abis_oml.patch27
97 files changed, 14720 insertions, 596 deletions
diff --git a/openbsc/.gitignore b/openbsc/.gitignore
index 7b7b11a1e..267c906ec 100644
--- a/openbsc/.gitignore
+++ b/openbsc/.gitignore
@@ -3,8 +3,12 @@
.deps
Makefile
Makefile.in
+bscconfig.h
+bscconfig.h.in
+openbsc.pc
bsc_hack
bsc_msc_ip
+bsc_mgcp
*.*~
*.sw?
@@ -26,6 +30,8 @@ hlr.sqlite3
bs11_config
ipaccess-config
ipaccess-find
+ipaccess-firmware
+ipaccess-proxy
isdnsync
#tests
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index 27c88b770..b4760252e 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -5,4 +5,4 @@ noinst_HEADERS = abis_nm.h abis_rsl.h debug.h db.h gsm_04_08.h gsm_data.h \
gsm_utils.h ipaccess.h rs232.h openbscdefines.h rtp_proxy.h \
bsc_rll.h mncc.h talloc.h transaction.h ussd.h gsm_04_80.h \
silent_call.h mgcp.h meas_rep.h bitvec.h rest_octets.h \
- system_information.h handover.h
+ system_information.h handover.h statistics.h
diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h
index 462403c85..5e10e7993 100644
--- a/openbsc/include/openbsc/abis_nm.h
+++ b/openbsc/include/openbsc/abis_nm.h
@@ -211,6 +211,7 @@ enum abis_nm_msgtype_bs11 {
enum abis_nm_msgtype_ipacc {
NM_MT_IPACC_RESTART = 0x87,
NM_MT_IPACC_RESTART_ACK,
+ NM_MT_IPACC_RESTART_NACK,
NM_MT_IPACC_RSL_CONNECT = 0xe0,
NM_MT_IPACC_RSL_CONNECT_ACK,
NM_MT_IPACC_RSL_CONNECT_NACK,
@@ -485,6 +486,12 @@ enum abis_nm_avail_state {
NM_AVSTATE_OK = 0xff,
};
+enum abis_nm_op_state {
+ NM_OPSTATE_DISABLED = 1,
+ NM_OPSTATE_ENABLED = 2,
+ NM_OPSTATE_NULL = 0xff,
+};
+
/* Section 9.4.13: Channel Combination */
enum abis_nm_chan_comb {
NM_CHANC_TCHFull = 0x00, /* TCH/F + TCH/H + SACCH/TF */
@@ -820,4 +827,5 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
const char *nm_opstate_name(u_int8_t os);
const char *nm_avail_name(u_int8_t avail);
+int nm_is_running(struct gsm_nm_state *s);
#endif /* _NM_H */
diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h
index 38855d1ee..f564e9e4d 100644
--- a/openbsc/include/openbsc/chan_alloc.h
+++ b/openbsc/include/openbsc/chan_alloc.h
@@ -49,4 +49,18 @@ void lchan_free(struct gsm_lchan *lchan);
/* Consider releasing the channel */
int lchan_auto_release(struct gsm_lchan *lchan);
+struct load_counter {
+ unsigned int total;
+ unsigned int used;
+};
+
+struct pchan_load {
+ struct load_counter pchan[GSM_PCHAN_UNKNOWN];
+};
+
+void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts);
+void network_chan_load(struct pchan_load *pl, struct gsm_network *net);
+
+int trx_is_usable(struct gsm_bts_trx *trx);
+
#endif /* _CHAN_ALLOC_H */
diff --git a/openbsc/include/openbsc/comp128.h b/openbsc/include/openbsc/comp128.h
new file mode 100644
index 000000000..691ade54b
--- /dev/null
+++ b/openbsc/include/openbsc/comp128.h
@@ -0,0 +1,22 @@
+/*
+ * COMP128 header
+ *
+ * See comp128.c for details
+ */
+
+#ifndef __COMP128_H__
+#define __COMP128_H__
+
+#include <sys/types.h>
+
+/*
+ * Performs the COMP128 algorithm (used as A3/A8)
+ * ki : u_int8_t [16]
+ * srand : u_int8_t [16]
+ * sres : u_int8_t [4]
+ * kc : u_int8_t [8]
+ */
+void comp128(u_int8_t *ki, u_int8_t *srand, u_int8_t *sres, u_int8_t *kc);
+
+#endif /* __COMP128_H__ */
+
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h
index 07135937b..df664dbc1 100644
--- a/openbsc/include/openbsc/db.h
+++ b/openbsc/include/openbsc/db.h
@@ -43,9 +43,20 @@ int db_subscriber_alloc_token(struct gsm_subscriber* subscriber, u_int32_t* toke
int db_subscriber_assoc_imei(struct gsm_subscriber* subscriber, char *imei);
int db_sync_equipment(struct gsm_equipment *equip);
+/* auth info */
+int get_authinfo_by_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr);
+int set_authinfo_for_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr);
+int get_authtuple_by_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr);
+int set_authtuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr);
+
/* SMS store-and-forward */
int db_sms_store(struct gsm_sms *sms);
struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id);
+struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, int min_subscr_id);
struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr);
int db_sms_mark_sent(struct gsm_sms *sms);
@@ -53,4 +64,8 @@ int db_sms_mark_sent(struct gsm_sms *sms);
int db_apdu_blob_store(struct gsm_subscriber *subscr,
u_int8_t apdu_id_flags, u_int8_t len,
u_int8_t *apdu);
+
+/* Statistics counter storage */
+int db_store_counter(struct counter *ctr);
+
#endif /* _DB_H */
diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h
index 95f27c7e0..276ab87c9 100644
--- a/openbsc/include/openbsc/debug.h
+++ b/openbsc/include/openbsc/debug.h
@@ -1,53 +1,54 @@
#ifndef _DEBUG_H
#define _DEBUG_H
-#define DEBUG
-
-#define DRLL 0x0001
-#define DCC 0x0002
-#define DMM 0x0004
-#define DRR 0x0008
-#define DRSL 0x0010
-#define DNM 0x0020
-
-#define DMNCC 0x0080
-#define DSMS 0x0100
-#define DPAG 0x0200
-#define DMEAS 0x0400
-#define DGPRS 0x0800
+#include <stdio.h>
+#include "linuxlist.h"
-#define DMI 0x1000
-#define DMIB 0x2000
-#define DMUX 0x4000
-#define DINP 0x8000
-
-#define DSCCP 0x10000
-#define DMSC 0x20000
-
-#define DMGCP 0x40000
+#define DEBUG
-#define DHO 0x80000
+/* Debug Areas of the code */
+enum {
+ DRLL,
+ DCC,
+ DMM,
+ DRR,
+ DRSL,
+ DNM,
+ DMNCC,
+ DSMS,
+ DPAG,
+ DMEAS,
+ DMI,
+ DMIB,
+ DMUX,
+ DINP,
+ DSCCP,
+ DMSC,
+ DMGCP,
+ DHO,
+ DDB,
+ DREF,
+ DGPRS,
+ Debug_LastEntry,
+};
#ifdef DEBUG
#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args)
#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args)
#else
-#define DEBUGP(xss, fmt, args...)
+#define DEBUGP(xss, fmt, args...)
#define DEBUGPC(ss, fmt, args...)
#endif
+
#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
char *hexdump(const unsigned char *buf, int len);
void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
-void debug_parse_category_mask(const char* mask);
-void debug_use_color(int use_color);
-void debug_timestamp(int enable);
-extern unsigned int debug_mask;
/* new logging interface */
-#define LOGP(ss, level, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ##args)
-#define LOGPC(ss, level, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ##args)
+#define LOGP(ss, level, fmt, args...) debugp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args)
+#define LOGPC(ss, level, fmt, args...) debugp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args)
/* different levels */
#define LOGL_DEBUG 1 /* debugging information */
@@ -56,4 +57,76 @@ extern unsigned int debug_mask;
#define LOGL_ERROR 7 /* error condition, requires user action */
#define LOGL_FATAL 8 /* fatal, program aborted */
+/* context */
+#define BSC_CTX_LCHAN 0
+#define BSC_CTX_SUBSCR 1
+#define BSC_CTX_BTS 2
+#define BSC_CTX_SCCP 3
+
+/* target */
+
+enum {
+ DEBUG_FILTER_IMSI = 1 << 0,
+ DEBUG_FILTER_ALL = 1 << 1,
+};
+
+struct debug_category {
+ int enabled;
+ int loglevel;
+};
+
+struct debug_target {
+ int filter_map;
+ char *imsi_filter;
+
+
+ struct debug_category categories[Debug_LastEntry];
+ int use_color;
+ int print_timestamp;
+ int loglevel;
+
+ union {
+ struct {
+ FILE *out;
+ } tgt_stdout;
+
+ struct {
+ int priority;
+ } tgt_syslog;
+
+ struct {
+ void *vty;
+ } tgt_vty;
+ };
+
+ void (*output) (struct debug_target *target, const char *string);
+
+ struct llist_head entry;
+};
+
+/* use the above macros */
+void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 6, 7)));
+void debug_init(void);
+
+/* context management */
+void debug_reset_context(void);
+void debug_set_context(int ctx, void *value);
+
+/* filter on the targets */
+void debug_set_imsi_filter(struct debug_target *target, const char *imsi);
+void debug_set_all_filter(struct debug_target *target, int);
+void debug_set_use_color(struct debug_target *target, int);
+void debug_set_print_timestamp(struct debug_target *target, int);
+void debug_set_log_level(struct debug_target *target, int log_level);
+void debug_parse_category_mask(struct debug_target *target, const char* mask);
+int debug_parse_level(const char *lvl);
+int debug_parse_category(const char *category);
+void debug_set_category_filter(struct debug_target *target, int category, int enable, int level);
+
+
+/* management of the targets */
+struct debug_target *debug_target_create(void);
+struct debug_target *debug_target_create_stderr(void);
+void debug_add_target(struct debug_target *target);
+void debug_del_target(struct debug_target *target);
#endif /* _DEBUG_H */
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index 23dffd76b..f21f35a47 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -754,7 +754,7 @@ enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
int gsm48_tx_mm_info(struct gsm_lchan *lchan);
-int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand);
+int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand, int key_seq);
int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan);
struct msgb *gsm48_msgb_alloc(void);
int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans);
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 4464f6340..50e92d8bf 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -9,6 +9,7 @@ struct value_string {
};
const char *get_value_string(const struct value_string *vs, u_int32_t val);
+int get_string_value(const struct value_string *vs, const char *str);
enum gsm_band {
GSM_BAND_400,
@@ -61,6 +62,7 @@ enum gsm_chreq_reason_t {
#include <openbsc/mncc.h>
#include <openbsc/tlv.h>
#include <openbsc/bitvec.h>
+#include <openbsc/statistics.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -100,14 +102,14 @@ typedef int gsm_cbfn(unsigned int hooknum,
#define LCHAN_RELEASE_TIMEOUT 20, 0
#define use_lchan(lchan) \
do { lchan->use_count++; \
- DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \
+ DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
lchan->nr, lchan->use_count); \
bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0);
#define put_lchan(lchan) \
do { lchan->use_count--; \
- DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \
+ DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
lchan->nr, lchan->use_count); \
} while(0);
@@ -118,6 +120,28 @@ struct gsm_bts_link {
struct gsm_bts *bts;
};
+/* Real authentication information containing Ki */
+enum gsm_auth_algo {
+ AUTH_ALGO_NONE,
+ AUTH_ALGO_XOR,
+ AUTH_ALGO_COMP128v1,
+};
+
+struct gsm_auth_info {
+ enum gsm_auth_algo auth_algo;
+ unsigned int a3a8_ki_len;
+ u_int8_t a3a8_ki[16];
+};
+
+struct gsm_auth_tuple {
+ int use_count;
+ int key_seq;
+ u_int8_t rand[16];
+ u_int8_t sres[4];
+ u_int8_t kc[8];
+};
+
+
struct gsm_lchan;
struct gsm_subscriber;
struct gsm_mncc;
@@ -168,7 +192,9 @@ struct neigh_meas_proc {
/* state of a logical channel */
enum gsm_lchan_state {
LCHAN_S_NONE, /* channel is not active */
+ LCHAN_S_ACT_REQ, /* channel activatin requested */
LCHAN_S_ACTIVE, /* channel is active and operational */
+ LCHAN_S_REL_REQ, /* channel release has been requested */
LCHAN_S_INACTIVE, /* channel is set inactive */
};
@@ -194,6 +220,8 @@ struct gsm_lchan {
u_int8_t key_len;
u_int8_t key[MAX_A5_KEY_LEN];
} encr;
+ /* Are we part of a special "silent" call */
+ int silent_call;
/* AMR bits */
struct gsm48_multi_rate_conf mr_conf;
@@ -299,9 +327,6 @@ struct gsm_bts_trx {
} bs11;
};
struct gsm_bts_trx_ts ts[TRX_NR_TS];
-
- /* NM state */
- int rf_locked;
};
enum gsm_bts_type {
@@ -460,6 +485,49 @@ struct gsm_bts {
struct llist_head trx_list;
};
+/* Some statistics of our network */
+struct gsmnet_stats {
+ struct {
+ struct counter *total;
+ struct counter *no_channel;
+ } chreq;
+ struct {
+ struct counter *attempted;
+ struct counter *no_channel; /* no channel available */
+ struct counter *timeout; /* T3103 timeout */
+ struct counter *completed; /* HO COMPL received */
+ struct counter *failed; /* HO FAIL received */
+ } handover;
+ struct {
+ struct counter *attach;
+ struct counter *normal;
+ struct counter *periodic;
+ struct counter *detach;
+ } loc_upd_type;
+ struct {
+ struct counter *reject;
+ struct counter *accept;
+ } loc_upd_resp;
+ struct {
+ struct counter *attempted;
+ struct counter *detached;
+ struct counter *completed;
+ struct counter *expired;
+ } paging;
+ struct {
+ struct counter *submitted; /* MO SMS submissions */
+ struct counter *no_receiver;
+ struct counter *delivered; /* MT SMS deliveries */
+ struct counter *rp_err_mem;
+ struct counter *rp_err_other;
+ } sms;
+ struct {
+ struct counter *dialled; /* total number of dialled calls */
+ struct counter *alerted; /* we alerted the other end */
+ struct counter *connected;/* how many calls were accepted */
+ } call;
+};
+
enum gsm_auth_policy {
GSM_AUTH_POLICY_CLOSED, /* only subscribers authorized in DB */
GSM_AUTH_POLICY_ACCEPT_ALL, /* accept everyone, even if not authorized in DB */
@@ -497,6 +565,8 @@ struct gsm_network {
unsigned int max_distance; /* TA values */
} handover;
+ struct gsmnet_stats stats;
+
/* layer 4 */
int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg);
struct llist_head upqueue;
@@ -546,11 +616,13 @@ struct gsm_sms {
char text[SMS_TEXT_SIZE];
};
+
struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code,
int (*mncc_recv)(struct gsm_network *, int, void *));
struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
u_int8_t tsc, u_int8_t bsic);
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
+void gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
@@ -562,9 +634,12 @@ struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num);
const char *gsm_pchan_name(enum gsm_phys_chan_config c);
enum gsm_phys_chan_config gsm_pchan_parse(const char *name);
-const char *gsm_lchan_name(enum gsm_chan_t c);
+const char *gsm_lchant_name(enum gsm_chan_t c);
const char *gsm_chreq_name(enum gsm_chreq_reason_t c);
+char *gsm_trx_name(struct gsm_bts_trx *trx);
char *gsm_ts_name(struct gsm_bts_trx_ts *ts);
+char *gsm_lchan_name(struct gsm_lchan *lchan);
+const char *gsm_lchans_name(enum gsm_lchan_state s);
enum gsm_e1_event {
EVT_E1_NONE,
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 553c87559..e3c86dab3 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -85,6 +85,8 @@ void subscr_put_channel(struct gsm_lchan *lchan);
void subscr_get_channel(struct gsm_subscriber *subscr,
int type, gsm_cbfn *cbfn, void *param);
+char *subscr_name(struct gsm_subscriber *subscr);
+
/* internal */
struct gsm_subscriber *subscr_alloc(void);
extern struct llist_head active_subscribers;
diff --git a/openbsc/include/openbsc/gsm_utils.h b/openbsc/include/openbsc/gsm_utils.h
index 5809221a3..56a4120a5 100644
--- a/openbsc/include/openbsc/gsm_utils.h
+++ b/openbsc/include/openbsc/gsm_utils.h
@@ -37,5 +37,12 @@ int ms_pwr_dbm(enum gsm_band band, u_int8_t lvl);
int rxlev2dbm(u_int8_t rxlev);
u_int8_t dbm2rxlev(int dbm);
+/* According to GSM 04.08 Chapter 10.5.2.29 */
+static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; }
+static inline int rach_max_trans_raw2val(int raw) {
+ const int tbl[4] = { 1, 2, 4, 7 };
+ return tbl[raw & 3];
+}
+
void generate_backtrace();
#endif
diff --git a/openbsc/include/openbsc/ipaccess.h b/openbsc/include/openbsc/ipaccess.h
index 395687764..8c12e59cc 100644
--- a/openbsc/include/openbsc/ipaccess.h
+++ b/openbsc/include/openbsc/ipaccess.h
@@ -2,6 +2,10 @@
#define _IPACCESS_H
#include "e1_input.h"
+#include "linuxlist.h"
+
+#define IPA_TCP_PORT_OML 3002
+#define IPA_TCP_PORT_RSL 3003
struct ipaccess_head {
u_int16_t len; /* network byte order */
@@ -45,4 +49,54 @@ int ipaccess_rcvmsg_base(struct msgb *msg, struct bsc_fd *bfd);
struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error);
void ipaccess_prepend_header(struct msgb *msg, int proto);
+/*
+ * Firmware specific header
+ */
+struct sdp_firmware {
+ char magic[4];
+ char more_magic[2];
+ u_int16_t more_more_magic;
+ u_int32_t header_length;
+ u_int32_t file_length;
+ char sw_part[20];
+ char text1[64];
+ char time[12];
+ char date[14];
+ char text2[10];
+ char version[20];
+ u_int8_t dummy[2];
+ u_int16_t part_length;
+ /* stuff i don't know */
+} __attribute__((packed));
+
+struct sdp_header_entry {
+ u_int16_t something1;
+ char text1[64];
+ char time[12];
+ char date[14];
+ char text2[10];
+ char version[20];
+ u_int32_t length;
+ u_int32_t addr1;
+ u_int32_t addr2;
+ u_int32_t start;
+} __attribute__((packed));
+
+struct sdp_header_item {
+ struct sdp_header_entry header_entry;
+ struct llist_head entry;
+};
+
+struct sdp_header {
+ struct sdp_firmware firmware_info;
+
+ /* for more_magic a list of sdp_header_entry_list */
+ struct llist_head header_list;
+
+ /* the entry of the sdp_header */
+ struct llist_head entry;
+};
+
+int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned base_offset, struct llist_head *list);
+
#endif /* _IPACCESS_H */
diff --git a/openbsc/include/openbsc/meas_rep.h b/openbsc/include/openbsc/meas_rep.h
index fd5fced43..3c2c8d1c1 100644
--- a/openbsc/include/openbsc/meas_rep.h
+++ b/openbsc/include/openbsc/meas_rep.h
@@ -7,6 +7,7 @@
struct gsm_meas_rep_cell {
u_int8_t rxlev;
u_int8_t bsic;
+ u_int8_t neigh_idx;
u_int16_t arfcn;
unsigned int flags;
};
diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h
index 8c815f89e..07b4e393d 100644
--- a/openbsc/include/openbsc/signal.h
+++ b/openbsc/include/openbsc/signal.h
@@ -45,7 +45,8 @@ enum signal_subsystems {
/* SS_PAGING signals */
enum signal_paging {
- S_PAGING_COMPLETED,
+ S_PAGING_SUCCEEDED,
+ S_PAGING_EXPIRED,
};
/* SS_SMS signals */
@@ -69,6 +70,9 @@ enum signal_nm {
S_NM_FAIL_REP, /* GSM 12.21 failure event report */
S_NM_NACK, /* GSM 12.21 various NM_MT_*_NACK happened */
S_NM_IPACC_NACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_NACK happened */
+ S_NM_IPACC_ACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_ACK happened */
+ S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */
+ S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */
S_NM_TEST_REP, /* GSM 12.21 Test Report */
};
@@ -123,6 +127,11 @@ struct scall_signal_data {
void *data;
};
+struct ipacc_ack_signal_data {
+ struct gsm_bts *bts;
+ u_int8_t msg_type;
+};
+
/* Management */
int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
diff --git a/openbsc/include/openbsc/silent_call.h b/openbsc/include/openbsc/silent_call.h
index 53ed4e248..fefc5182d 100644
--- a/openbsc/include/openbsc/silent_call.h
+++ b/openbsc/include/openbsc/silent_call.h
@@ -1,7 +1,10 @@
#ifndef _SILENT_CALL_H
#define _SILENT_CALL_H
-extern int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data);
+extern int gsm_silent_call_start(struct gsm_subscriber *subscr,
+ void *data, int type);
extern int gsm_silent_call_stop(struct gsm_subscriber *subscr);
+extern int silent_call_rx(struct msgb *msg);
+extern int silent_call_reroute(struct msgb *msg);
#endif /* _SILENT_CALL_H */
diff --git a/openbsc/include/openbsc/statistics.h b/openbsc/include/openbsc/statistics.h
new file mode 100644
index 000000000..1d56054ab
--- /dev/null
+++ b/openbsc/include/openbsc/statistics.h
@@ -0,0 +1,31 @@
+#ifndef _STATISTICS_H
+#define _STATISTICS_H
+
+struct counter {
+ struct llist_head list;
+ const char *name;
+ const char *description;
+ unsigned long value;
+};
+
+static inline void counter_inc(struct counter *ctr)
+{
+ ctr->value++;
+}
+
+static inline unsigned long counter_get(struct counter *ctr)
+{
+ return ctr->value;
+}
+
+static inline void counter_reset(struct counter *ctr)
+{
+ ctr->value = 0;
+}
+
+struct counter *counter_alloc(const char *name);
+void counter_free(struct counter *ctr);
+
+int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data);
+
+#endif /* _STATISTICS_H */
diff --git a/openbsc/include/openbsc/telnet_interface.h b/openbsc/include/openbsc/telnet_interface.h
index d3381e0a4..f4e976f77 100644
--- a/openbsc/include/openbsc/telnet_interface.h
+++ b/openbsc/include/openbsc/telnet_interface.h
@@ -22,7 +22,7 @@
#define TELNET_INTERFACE_H
#include "gsm_data.h"
-#include "linuxlist.h"
+#include "debug.h"
#include "select.h"
#include <vty/vty.h>
@@ -35,6 +35,7 @@ struct telnet_connection {
struct gsm_network *network;
struct bsc_fd fd;
struct vty *vty;
+ struct debug_target *dbg;
};
diff --git a/openbsc/include/vty/command.h b/openbsc/include/vty/command.h
index 10a60add5..03b071f70 100644
--- a/openbsc/include/vty/command.h
+++ b/openbsc/include/vty/command.h
@@ -356,4 +356,6 @@ void host_config_set(const char *);
void print_version(const char *);
+extern void *tall_vty_cmd_ctx;
+
#endif /* _ZEBRA_COMMAND_H */
diff --git a/openbsc/include/vty/vector.h b/openbsc/include/vty/vector.h
index 00f0079f3..22a184d61 100644
--- a/openbsc/include/vty/vector.h
+++ b/openbsc/include/vty/vector.h
@@ -59,4 +59,6 @@ vector vector_copy(vector v);
void *vector_lookup(vector, unsigned int);
void *vector_lookup_ensure(vector, unsigned int);
+extern void *tall_vty_vec_ctx;
+
#endif /* _ZEBRA_VECTOR_H */
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 6e1d25afd..c89bee06c 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -2,40 +2,44 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS=-Wall
sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config \
- isdnsync bsc_mgcp
-noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a
+ isdnsync bsc_mgcp ipaccess-proxy
+noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a libsgsn.a
noinst_HEADERS = vty/cardshell.h
libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \
- msgb.c select.c chan_alloc.c timer.c debug.c handover_logic.c \
+ msgb.c select.c chan_alloc.c timer.c debug.c \
gsm_subscriber_base.c subchan_demux.c bsc_rll.c transaction.c \
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \
input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c \
talloc_ctx.c system_information.c bitvec.c rest_octets.c \
- handover_decision.c meas_rep.c \
- gprs_ns.c gprs_bssgp.c gprs_llc.c gsm_04_08_gprs.c \
+ rtp_proxy.c statistics.c
+
+libsgsn_a_SOURCES = gprs_ns.c gprs_bssgp.c gprs_llc.c gsm_04_08_gprs.c \
crc24.c gprs_sgsn.c
libmsc_a_SOURCES = gsm_subscriber.c db.c telnet_interface.c \
- mncc.c rtp_proxy.c gsm_04_08.c gsm_04_11.c transaction.c \
- token_auth.c rrlp.c gsm_04_80.c ussd.c silent_call.c
+ mncc.c gsm_04_08.c gsm_04_11.c transaction.c \
+ token_auth.c rrlp.c gsm_04_80.c ussd.c silent_call.c \
+ handover_logic.c handover_decision.c meas_rep.c comp128.c
libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
libsccp_a_SOURCES = sccp/sccp.c
bsc_hack_SOURCES = bsc_hack.c bsc_init.c vty_interface.c vty_interface_layer3.c
-bsc_hack_LDADD = libmsc.a libbsc.a libmsc.a libvty.a -ldl -ldbi $(LIBCRYPT)
+bsc_hack_LDADD = libmsc.a libbsc.a libmsc.a libsgsn.a libvty.a -ldl -ldbi $(LIBCRYPT)
bs11_config_SOURCES = bs11_config.c abis_nm.c gsm_data.c msgb.c debug.c \
select.c timer.c rs232.c tlv_parser.c signal.c talloc.c
-ipaccess_find_SOURCES = ipaccess-find.c select.c timer.c
+ipaccess_find_SOURCES = ipaccess/ipaccess-find.c select.c timer.c
-ipaccess_config_SOURCES = ipaccess-config.c
+ipaccess_config_SOURCES = ipaccess/ipaccess-config.c ipaccess/ipaccess-firmware.c
ipaccess_config_LDADD = libbsc.a libmsc.a libbsc.a libvty.a -ldl -ldbi $(LIBCRYPT)
isdnsync_SOURCES = isdnsync.c
bsc_mgcp_SOURCES = bsc_mgcp.c msgb.c talloc.c debug.c select.c timer.c telnet_interface.c
bsc_mgcp_LDADD = libvty.a
+
+ipaccess_proxy_SOURCES = ipaccess/ipaccess-proxy.c msgb.c select.c talloc.c debug.c timer.c
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index 2dadbb255..2426360ed 100644
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -48,6 +48,7 @@
#define OM_ALLOC_SIZE 1024
#define OM_HEADROOM_SIZE 128
+#define IPACC_SEGMENT_SIZE 245
/* unidirectional messages from BTS to BSC */
static const enum abis_nm_msgtype reports[] = {
@@ -541,11 +542,11 @@ static const char *obj_class_name(u_int8_t oc)
const char *nm_opstate_name(u_int8_t os)
{
switch (os) {
- case 1:
+ case NM_OPSTATE_DISABLED:
return "Disabled";
- case 2:
+ case NM_OPSTATE_ENABLED:
return "Enabled";
- case 0xff:
+ case NM_OPSTATE_NULL:
return "NULL";
default:
return "RFU";
@@ -599,6 +600,13 @@ const char *nm_adm_name(u_int8_t adm)
}
}
+int nm_is_running(struct gsm_nm_state *s) {
+ return (s->operational == NM_OPSTATE_ENABLED) && (
+ (s->availability == NM_AVSTATE_OK) ||
+ (s->availability == 0xff)
+ );
+}
+
static void debugp_foh(struct abis_om_fom_hdr *foh)
{
DEBUGP(DNM, "OC=%s(%02x) INST=(%02x,%02x,%02x) ",
@@ -806,19 +814,25 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb)
new_state.availability = *TLVP_VAL(&tp, NM_ATT_AVAIL_STATUS);
DEBUGPC(DNM, "AVAIL=%s(%02x) ", nm_avail_name(new_state.availability),
new_state.availability);
- }
+ } else
+ new_state.availability = 0xff;
if (TLVP_PRESENT(&tp, NM_ATT_ADM_STATE)) {
new_state.administrative = *TLVP_VAL(&tp, NM_ATT_ADM_STATE);
DEBUGPC(DNM, "ADM=%2s ", nm_adm_name(new_state.administrative));
}
DEBUGPC(DNM, "\n");
- if (memcmp(&new_state, nm_state, sizeof(new_state))) {
+ if ((new_state.administrative != 0 && nm_state->administrative == 0) ||
+ new_state.operational != nm_state->operational ||
+ new_state.availability != nm_state->availability) {
/* Update the operational state of a given object in our in-memory data
* structures and send an event to the higher layer */
void *obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst);
rc = nm_state_event(EVT_STATECHG_OPER, foh->obj_class, obj, nm_state, &new_state);
- *nm_state = new_state;
+ nm_state->operational = new_state.operational;
+ nm_state->availability = new_state.availability;
+ if (nm_state->administrative == 0)
+ nm_state->administrative = new_state.administrative;
}
#if 0
if (op_state == 1) {
@@ -1036,13 +1050,11 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
/* check if last message is to be acked */
if (is_ack_nack(nmh->last_msgtype)) {
if (mt == MT_ACK(nmh->last_msgtype)) {
- fprintf(stderr, "received ACK (0x%x)\n",
- foh->msg_type);
+ DEBUGP(DNM, "received ACK (0x%x)\n", foh->msg_type);
/* we got our ACK, continue sending the next msg */
} else if (mt == MT_NACK(nmh->last_msgtype)) {
/* we got a NACK, signal this to the caller */
- fprintf(stderr, "received NACK (0x%x)\n",
- foh->msg_type);
+ DEBUGP(DNM, "received NACK (0x%x)\n", foh->msg_type);
/* FIXME: somehow signal this to the caller */
} else {
/* really strange things happen */
@@ -1064,6 +1076,12 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
case NM_MT_CONN_MDROP_LINK_ACK:
DEBUGP(DNM, "CONN MDROP LINK ACK\n");
break;
+ case NM_MT_IPACC_RESTART_ACK:
+ dispatch_signal(SS_NM, S_NM_IPACC_RESTART_ACK, NULL);
+ break;
+ case NM_MT_IPACC_RESTART_NACK:
+ dispatch_signal(SS_NM, S_NM_IPACC_RESTART_NACK, NULL);
+ break;
}
return 0;
@@ -1209,6 +1227,22 @@ struct abis_nm_sw {
static struct abis_nm_sw g_sw;
+static void sw_add_file_id_and_ver(struct abis_nm_sw *sw, struct msgb *msg)
+{
+ if (sw->bts->type == GSM_BTS_TYPE_NANOBTS) {
+ msgb_v_put(msg, NM_ATT_SW_DESCR);
+ msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
+ msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
+ sw->file_version);
+ } else if (sw->bts->type == GSM_BTS_TYPE_BS11) {
+ msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
+ msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
+ sw->file_version);
+ } else {
+ LOGP(DNM, LOGL_ERROR, "Please implement this for the BTS.\n");
+ }
+}
+
/* 6.2.1 / 8.3.1: Load Data Initiate */
static int sw_load_init(struct abis_nm_sw *sw)
{
@@ -1220,11 +1254,8 @@ static int sw_load_init(struct abis_nm_sw *sw)
fill_om_fom_hdr(oh, len, NM_MT_LOAD_INIT, sw->obj_class,
sw->obj_instance[0], sw->obj_instance[1],
sw->obj_instance[2]);
-
- /* FIXME: this is BS11 specific format */
- msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
- msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
- sw->file_version);
+
+ sw_add_file_id_and_ver(sw, msg);
msgb_tv_put(msg, NM_ATT_WINDOW_SIZE, sw->window_size);
return abis_nm_sendmsg(sw->bts, msg);
@@ -1282,7 +1313,24 @@ static int sw_load_segment(struct abis_nm_sw *sw)
/* we only now know the exact length for the OM hdr */
len = strlen(line_buf)+2;
break;
+ case GSM_BTS_TYPE_NANOBTS: {
+ static_assert(sizeof(seg_buf) >= IPACC_SEGMENT_SIZE, buffer_big_enough);
+ len = read(sw->fd, &seg_buf, IPACC_SEGMENT_SIZE);
+ if (len < 0) {
+ perror("read failed");
+ return -EINVAL;
+ }
+
+ if (len != IPACC_SEGMENT_SIZE)
+ sw->last_seg = 1;
+
+ ++sw->seg_in_window;
+ msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const u_int8_t *) seg_buf);
+ len += 3;
+ break;
+ }
default:
+ LOGP(DNM, LOGL_ERROR, "sw_load_segment needs implementation for the BTS.\n");
/* FIXME: Other BTS types */
return -1;
}
@@ -1306,11 +1354,7 @@ static int sw_load_end(struct abis_nm_sw *sw)
sw->obj_instance[0], sw->obj_instance[1],
sw->obj_instance[2]);
- /* FIXME: this is BS11 specific format */
- msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
- msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
- sw->file_version);
-
+ sw_add_file_id_and_ver(sw, msg);
return abis_nm_sendmsg(sw->bts, msg);
}
@@ -1334,6 +1378,59 @@ static int sw_activate(struct abis_nm_sw *sw)
return abis_nm_sendmsg(sw->bts, msg);
}
+struct sdp_firmware {
+ char magic[4];
+ char more_magic[4];
+ unsigned int header_length;
+ unsigned int file_length;
+} __attribute__ ((packed));
+
+static int parse_sdp_header(struct abis_nm_sw *sw)
+{
+ struct sdp_firmware firmware_header;
+ int rc;
+ struct stat stat;
+
+ rc = read(sw->fd, &firmware_header, sizeof(firmware_header));
+ if (rc != sizeof(firmware_header)) {
+ LOGP(DNM, LOGL_ERROR, "Could not read SDP file header.\n");
+ return -1;
+ }
+
+ if (strncmp(firmware_header.magic, " SDP", 4) != 0) {
+ LOGP(DNM, LOGL_ERROR, "The magic number1 is wrong.\n");
+ return -1;
+ }
+
+ if (firmware_header.more_magic[0] != 0x10 ||
+ firmware_header.more_magic[1] != 0x02 ||
+ firmware_header.more_magic[2] != 0x00 ||
+ firmware_header.more_magic[3] != 0x00) {
+ LOGP(DNM, LOGL_ERROR, "The more magic number is wrong.\n");
+ return -1;
+ }
+
+
+ if (fstat(sw->fd, &stat) == -1) {
+ LOGP(DNM, LOGL_ERROR, "Could not stat the file.\n");
+ return -1;
+ }
+
+ if (ntohl(firmware_header.file_length) != stat.st_size) {
+ LOGP(DNM, LOGL_ERROR, "The filesizes do not match.\n");
+ return -1;
+ }
+
+ /* go back to the start as we checked the whole filesize.. */
+ lseek(sw->fd, 0l, SEEK_SET);
+ LOGP(DNM, LOGL_NOTICE, "The ipaccess SDP header is not fully understood.\n"
+ "There might be checksums in the file that are not\n"
+ "verified and incomplete firmware might be flashed.\n"
+ "There is absolutely no WARRANTY that flashing will\n"
+ "work.\n");
+ return 0;
+}
+
static int sw_open_file(struct abis_nm_sw *sw, const char *fname)
{
char file_id[12+1];
@@ -1365,6 +1462,19 @@ static int sw_open_file(struct abis_nm_sw *sw, const char *fname)
/* rewind to start of file */
rewind(sw->stream);
break;
+ case GSM_BTS_TYPE_NANOBTS:
+ /* TODO: extract that from the filename or content */
+ rc = parse_sdp_header(sw);
+ if (rc < 0) {
+ fprintf(stderr, "Could not parse the ipaccess SDP header\n");
+ return -1;
+ }
+
+ strcpy((char *)sw->file_id, "id");
+ sw->file_id_len = 3;
+ strcpy((char *)sw->file_version, "version");
+ sw->file_version_len = 8;
+ break;
default:
/* We don't know how to treat them yet */
close(sw->fd);
@@ -1463,6 +1573,12 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
rc = sw_load_end(sw);
}
break;
+ case NM_MT_LOAD_ABORT:
+ if (sw->cbfn)
+ sw->cbfn(GSM_HOOK_NM_SWLOAD,
+ NM_MT_LOAD_ABORT, mb,
+ sw->cb_data, NULL);
+ break;
}
break;
case SW_STATE_WAIT_ENDACK:
@@ -1476,6 +1592,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_LOAD_END_ACK, mb,
sw->cb_data, NULL);
+ rc = 0;
break;
case NM_MT_LOAD_END_NACK:
if (sw->forced) {
@@ -1552,10 +1669,26 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
return -EBUSY;
sw->bts = bts;
- sw->obj_class = NM_OC_SITE_MANAGER;
- sw->obj_instance[0] = 0xff;
- sw->obj_instance[1] = 0xff;
- sw->obj_instance[2] = 0xff;
+
+ switch (bts->type) {
+ case GSM_BTS_TYPE_BS11:
+ sw->obj_class = NM_OC_SITE_MANAGER;
+ sw->obj_instance[0] = 0xff;
+ sw->obj_instance[1] = 0xff;
+ sw->obj_instance[2] = 0xff;
+ break;
+ case GSM_BTS_TYPE_NANOBTS:
+ sw->obj_class = NM_OC_BASEB_TRANSC;
+ sw->obj_instance[0] = 0x00;
+ sw->obj_instance[1] = 0x00;
+ sw->obj_instance[2] = 0xff;
+ break;
+ case GSM_BTS_TYPE_UNKNOWN:
+ default:
+ LOGPC(DNM, LOGL_ERROR, "Software Load not properly implemented.\n");
+ return -1;
+ break;
+ }
sw->window_size = win_size;
sw->state = SW_STATE_WAIT_INITACK;
sw->cbfn = cbfn;
@@ -1583,7 +1716,10 @@ int abis_nm_software_load_status(struct gsm_bts *bts)
return rc;
}
- percent = (ftell(sw->stream) * 100) / st.st_size;
+ if (sw->stream)
+ percent = (ftell(sw->stream) * 100) / st.st_size;
+ else
+ percent = (lseek(sw->fd, 0, SEEK_CUR) * 100) / st.st_size;
return percent;
}
@@ -2590,9 +2726,10 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
struct abis_om_fom_hdr *foh;
u_int8_t idstrlen = oh->data[0];
struct tlv_parsed tp;
+ struct ipacc_ack_signal_data signal;
if (strncmp((char *)&oh->data[1], ipaccess_magic, idstrlen)) {
- DEBUGP(DNM, "id string is not com.ipaccess !?!\n");
+ LOGP(DNM, LOGL_ERROR, "id string is not com.ipaccess !?!\n");
return -EINVAL;
}
@@ -2620,7 +2757,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
DEBUGPC(DNM, "\n");
break;
case NM_MT_IPACC_RSL_CONNECT_NACK:
- DEBUGPC(DNM, "RSL CONNECT NACK ");
+ LOGP(DNM, LOGL_ERROR, "RSL CONNECT NACK ");
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
DEBUGPC(DNM, " CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
@@ -2632,35 +2769,35 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
/* FIXME: decode and show the actual attributes */
break;
case NM_MT_IPACC_SET_NVATTR_NACK:
- DEBUGPC(DNM, "SET NVATTR NACK ");
+ LOGP(DNM, LOGL_ERROR, "SET NVATTR NACK ");
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
- DEBUGPC(DNM, " CAUSE=%s\n",
+ LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
else
- DEBUGPC(DNM, "\n");
+ LOGPC(DNM, LOGL_ERROR, "\n");
break;
case NM_MT_IPACC_GET_NVATTR_ACK:
DEBUGPC(DNM, "GET NVATTR ACK\n");
/* FIXME: decode and show the actual attributes */
break;
case NM_MT_IPACC_GET_NVATTR_NACK:
- DEBUGPC(DNM, "GET NVATTR NACK ");
+ LOGPC(DNM, LOGL_ERROR, "GET NVATTR NACK ");
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
- DEBUGPC(DNM, " CAUSE=%s\n",
+ LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
else
- DEBUGPC(DNM, "\n");
+ LOGPC(DNM, LOGL_ERROR, "\n");
break;
case NM_MT_IPACC_SET_ATTR_ACK:
DEBUGPC(DNM, "SET ATTR ACK\n");
break;
case NM_MT_IPACC_SET_ATTR_NACK:
- DEBUGPC(DNM, "SET ATTR NACK ");
+ LOGPC(DNM, LOGL_ERROR, "SET ATTR NACK ");
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
- DEBUGPC(DNM, " CAUSE=%s\n",
+ LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
else
- DEBUGPC(DNM, "\n");
+ LOGPC(DNM, LOGL_ERROR, "\n");
break;
default:
DEBUGPC(DNM, "unknown\n");
@@ -2672,7 +2809,14 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
case NM_MT_IPACC_RSL_CONNECT_NACK:
case NM_MT_IPACC_SET_NVATTR_NACK:
case NM_MT_IPACC_GET_NVATTR_NACK:
- dispatch_signal(SS_NM, S_NM_IPACC_NACK, &foh->msg_type);
+ signal.bts = msg->trx->bts;
+ signal.msg_type = foh->msg_type;
+ dispatch_signal(SS_NM, S_NM_IPACC_NACK, &signal);
+ break;
+ case NM_MT_IPACC_SET_NVATTR_ACK:
+ signal.bts = msg->trx->bts;
+ signal.msg_type = foh->msg_type;
+ dispatch_signal(SS_NM, S_NM_IPACC_ACK, &signal);
break;
default:
break;
@@ -2782,7 +2926,7 @@ void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked)
{
int new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;
- trx->rf_locked = locked;
+ trx->nm_state.administrative = new_state;
if (!trx->bts || !trx->bts->oml_link)
return;
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 72ae9dbb6..11a4355a7 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -237,6 +237,8 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr)
}
lchan = &ts->lchan[lch_idx];
+ debug_set_context(BSC_CTX_LCHAN, lchan);
+ debug_set_context(BSC_CTX_SUBSCR, lchan->subscr);
return lchan;
}
@@ -368,6 +370,24 @@ static const char *rsl_err_vals[0xff] = {
[RSL_ERR_INTERWORKING] = "Interworking error, unspecified",
};
+static const struct value_string rlm_cause_strs[] = {
+ { RLL_CAUSE_T200_EXPIRED, "Timer T200 expired (N200+1) times" },
+ { RLL_CAUSE_REEST_REQ, "Re-establishment request" },
+ { RLL_CAUSE_UNSOL_UA_RESP, "Unsolicited UA response" },
+ { RLL_CAUSE_UNSOL_DM_RESP, "Unsolicited DM response" },
+ { RLL_CAUSE_UNSOL_DM_RESP_MF, "Unsolicited DM response, multiple frame" },
+ { RLL_CAUSE_UNSOL_SPRV_RESP, "Unsolicited supervisory response" },
+ { RLL_CAUSE_SEQ_ERR, "Sequence Error" },
+ { RLL_CAUSE_UFRM_INC_PARAM, "U-Frame with incorrect parameters" },
+ { RLL_CAUSE_SFRM_INC_PARAM, "S-Frame with incorrect parameters" },
+ { RLL_CAUSE_IFRM_INC_MBITS, "I-Frame with incorrect use of M bit" },
+ { RLL_CAUSE_IFRM_INC_LEN, "I-Frame with incorrect length" },
+ { RLL_CAUSE_FRM_UNIMPL, "Fraeme not implemented" },
+ { RLL_CAUSE_SABM_MF, "SABM command, multiple frame established state" },
+ { RLL_CAUSE_SABM_INFO_NOTALL, "SABM frame with information not allowed in this state" },
+ { 0, NULL },
+};
+
static const char *rsl_err_name(u_int8_t err)
{
if (rsl_err_vals[err])
@@ -376,14 +396,14 @@ static const char *rsl_err_name(u_int8_t err)
return "unknown";
}
-static void print_rsl_cause(const u_int8_t *cause_v, u_int8_t cause_len)
+static void print_rsl_cause(int lvl, const u_int8_t *cause_v, u_int8_t cause_len)
{
int i;
- DEBUGPC(DRSL, "CAUSE=0x%02x(%s) ",
+ LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ",
cause_v[0], rsl_err_name(cause_v[0]));
for (i = 1; i < cause_len-1; i++)
- DEBUGPC(DRSL, "%02x ", cause_v[i]);
+ LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
}
/* Send a BCCH_INFO message as per Chapter 8.5.1 */
@@ -719,8 +739,7 @@ int rsl_deact_sacch(struct gsm_lchan *lchan)
msg->lchan = lchan;
msg->trx = lchan->ts->trx;
- DEBUGP(DRSL, "DEACTivate SACCH CMD channel=%s chan_nr=0x%02x\n",
- gsm_ts_name(lchan->ts), dh->chan_nr);
+ DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan));
return abis_rsl_sendmsg(msg);
}
@@ -738,8 +757,7 @@ int rsl_rf_chan_release(struct gsm_lchan *lchan)
msg->lchan = lchan;
msg->trx = lchan->ts->trx;
- DEBUGP(DRSL, "RF Channel Release CMD channel=%s chan_nr=0x%02x\n",
- gsm_ts_name(lchan->ts), dh->chan_nr);
+ DEBUGP(DRSL, "%s RF Channel Release CMD\n", gsm_lchan_name(lchan));
/* BTS will respond by RF CHAN REL ACK */
return abis_rsl_sendmsg(msg);
@@ -832,8 +850,8 @@ int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci)
dh->chan_nr = lchan2chan_nr(lchan);
msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(u_int8_t *)mrpci);
- DEBUGP(DRSL, "channel=%s chan_nr=0x%02x TX Siemens MRPCI 0x%02x\n",
- gsm_ts_name(lchan->ts), dh->chan_nr, *(u_int8_t *)mrpci);
+ DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n",
+ gsm_lchan_name(lchan), *(u_int8_t *)mrpci);
msg->trx = lchan->ts->trx;
@@ -903,6 +921,9 @@ int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id)
rh->link_id = link_id;
msgb_tv_put(msg, RSL_IE_RELEASE_MODE, 0); /* normal release */
+ lchan->state = LCHAN_S_REL_REQ;
+ /* FIXME: start some timer in case we don't receive a REL ACK ? */
+
msg->trx = lchan->ts->trx;
return abis_rsl_sendmsg(msg);
@@ -918,6 +939,10 @@ static int rsl_rx_chan_act_ack(struct msgb *msg)
if (rslh->ie_chan != RSL_IE_CHAN_NR)
return -EINVAL;
+ if (msg->lchan->state != LCHAN_S_ACT_REQ)
+ LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
+ gsm_lchan_name(msg->lchan),
+ gsm_lchans_name(msg->lchan->state));
msg->lchan->state = LCHAN_S_ACTIVE;
dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_ACK, msg->lchan);
@@ -931,16 +956,24 @@ static int rsl_rx_chan_act_nack(struct msgb *msg)
struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
struct tlv_parsed tp;
+ LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK",
+ gsm_lchan_name(msg->lchan));
+
/* BTS has rejected channel activation ?!? */
if (dh->ie_chan != RSL_IE_CHAN_NR)
return -EINVAL;
rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
- if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
- print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
+ if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) {
+ const u_int8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE);
+ print_rsl_cause(LOGL_ERROR, cause,
TLVP_LEN(&tp, RSL_IE_CAUSE));
-
- msg->lchan->state = LCHAN_S_NONE;
+ if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
+ msg->lchan->state = LCHAN_S_NONE;
+ } else
+ msg->lchan->state = LCHAN_S_NONE;
+
+ LOGPC(DRSL, LOGL_ERROR, "\n");
dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_NACK, msg->lchan);
@@ -955,14 +988,16 @@ static int rsl_rx_conn_fail(struct msgb *msg)
struct tlv_parsed tp;
/* FIXME: print which channel */
- LOGP(DRSL, LOGL_NOTICE, "CONNECTION FAIL: RELEASING\n");
+ LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ",
+ gsm_lchan_name(msg->lchan));
rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
- print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
+ print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE),
TLVP_LEN(&tp, RSL_IE_CAUSE));
+ LOGPC(DRSL, LOGL_NOTICE, "\n");
/* FIXME: only free it after channel release ACK */
return rsl_rf_chan_release(msg->lchan);
}
@@ -1012,8 +1047,8 @@ static void print_meas_rep(struct gsm_meas_rep *mr)
return;
for (i = 0; i < mr->num_cell; i++) {
struct gsm_meas_rep_cell *mrc = &mr->cell[i];
- DEBUGP(DMEAS, "ARFCN=%u BSIC=%u => %d dBm\n", mrc->arfcn, mrc->bsic,
- rxlev2dbm(mrc->rxlev));
+ DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n",
+ mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev));
}
}
@@ -1028,8 +1063,11 @@ static int rsl_rx_meas_res(struct msgb *msg)
/* check if this channel is actually active */
/* FIXME: maybe this check should be way more generic/centralized */
- if (msg->lchan->state != LCHAN_S_ACTIVE)
+ if (msg->lchan->state != LCHAN_S_ACTIVE) {
+ LOGP(DRSL, LOGL_NOTICE, "%s: MEAS RES for inactive channel\n",
+ gsm_lchan_name(msg->lchan));
return 0;
+ }
memset(mr, 0, sizeof(*mr));
mr->lchan = msg->lchan;
@@ -1090,7 +1128,7 @@ static int rsl_rx_hando_det(struct msgb *msg)
struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
struct tlv_parsed tp;
- DEBUGP(DRSL, "HANDOVER DETECT ");
+ DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan));
rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
@@ -1112,18 +1150,14 @@ static int abis_rsl_rx_dchan(struct msgb *msg)
char *ts_name;
msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr);
- ts_name = gsm_ts_name(msg->lchan->ts);
-
- if (rslh->c.msg_type != RSL_MT_MEAS_RES)
- DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ", ts_name, rslh->chan_nr);
+ ts_name = gsm_lchan_name(msg->lchan);
switch (rslh->c.msg_type) {
case RSL_MT_CHAN_ACTIV_ACK:
- DEBUGPC(DRSL, "CHANNEL ACTIVATE ACK\n");
+ DEBUGP(DRSL, "%s CHANNEL ACTIVATE ACK\n", ts_name);
rc = rsl_rx_chan_act_ack(msg);
break;
case RSL_MT_CHAN_ACTIV_NACK:
- DEBUGPC(DRSL, "CHANNEL ACTIVATE NACK\n");
rc = rsl_rx_chan_act_nack(msg);
break;
case RSL_MT_CONN_FAIL:
@@ -1136,27 +1170,31 @@ static int abis_rsl_rx_dchan(struct msgb *msg)
rc = rsl_rx_hando_det(msg);
break;
case RSL_MT_RF_CHAN_REL_ACK:
- DEBUGPC(DRSL, "RF CHANNEL RELEASE ACK\n");
+ DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", ts_name);
+ if (msg->lchan->state != LCHAN_S_REL_REQ)
+ LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
+ gsm_lchan_name(msg->lchan),
+ gsm_lchans_name(msg->lchan->state));
msg->lchan->state = LCHAN_S_NONE;
lchan_free(msg->lchan);
break;
case RSL_MT_MODE_MODIFY_ACK:
- DEBUGPC(DRSL, "CHANNEL MODE MODIFY ACK\n");
+ DEBUGP(DRSL, "%s CHANNEL MODE MODIFY ACK\n", ts_name);
break;
case RSL_MT_MODE_MODIFY_NACK:
- DEBUGPC(DRSL, "CHANNEL MODE MODIFY NACK\n");
+ LOGP(DRSL, LOGL_ERROR, "%s CHANNEL MODE MODIFY NACK\n", ts_name);
break;
case RSL_MT_IPAC_PDCH_ACT_ACK:
- DEBUGPC(DRSL, "IPAC PDCH ACT ACK\n");
+ DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name);
break;
case RSL_MT_IPAC_PDCH_ACT_NACK:
- DEBUGPC(DRSL, "IPAC PDCH ACT NACK\n");
+ LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name);
break;
case RSL_MT_IPAC_PDCH_DEACT_ACK:
- DEBUGPC(DRSL, "IPAC PDCH DEACT ACK\n");
+ DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name);
break;
case RSL_MT_IPAC_PDCH_DEACT_NACK:
- DEBUGPC(DRSL, "IPAC PDCH DEACT NACK\n");
+ LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name);
break;
case RSL_MT_PHY_CONTEXT_CONF:
case RSL_MT_PREPROC_MEAS_RES:
@@ -1166,12 +1204,12 @@ static int abis_rsl_rx_dchan(struct msgb *msg)
case RSL_MT_MR_CODEC_MOD_ACK:
case RSL_MT_MR_CODEC_MOD_NACK:
case RSL_MT_MR_CODEC_MOD_PER:
- DEBUGPC(DRSL, "Unimplemented Abis RSL DChan msg 0x%02x\n",
- rslh->c.msg_type);
+ LOGP(DRSL, LOGL_NOTICE, "%s Unimplemented Abis RSL DChan "
+ "msg 0x%02x\n", ts_name, rslh->c.msg_type);
break;
default:
- DEBUGPC(DRSL, "unknown Abis RSL DChan msg 0x%02x\n",
- rslh->c.msg_type);
+ LOGP(DRSL, LOGL_NOTICE, "%s unknown Abis RSL DChan msg 0x%02x\n",
+ ts_name, rslh->c.msg_type);
return -EINVAL;
}
@@ -1183,12 +1221,12 @@ static int rsl_rx_error_rep(struct msgb *msg)
struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
struct tlv_parsed tp;
- LOGP(DRSL, LOGL_ERROR, "ERROR REPORT ");
+ LOGP(DRSL, LOGL_ERROR, "%s ERROR REPORT ", gsm_trx_name(msg->trx));
rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
- print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
+ print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE),
TLVP_LEN(&tp, RSL_IE_CAUSE));
LOGPC(DRSL, LOGL_ERROR, "\n");
@@ -1207,15 +1245,16 @@ static int abis_rsl_rx_trx(struct msgb *msg)
break;
case RSL_MT_RF_RES_IND:
/* interference on idle channels of TRX */
- //DEBUGP(DRSL, "TRX: RF Interference Indication\n");
+ //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(msg->trx));
break;
case RSL_MT_OVERLOAD:
/* indicate CCCH / ACCH / processor overload */
- LOGP(DRSL, LOGL_ERROR, "TRX: CCCH/ACCH/CPU Overload\n");
+ LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
+ gsm_trx_name(msg->trx));
break;
default:
- DEBUGP(DRSL, "Unknown Abis RSL TRX message type 0x%02x\n",
- rslh->msg_type);
+ LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
+ "type 0x%02x\n", gsm_trx_name(msg->trx), rslh->msg_type);
return -EINVAL;
}
return rc;
@@ -1261,15 +1300,24 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
lctype = get_ctype_by_chreq(bts, rqd_ref->ra, bts->network->neci);
chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra, bts->network->neci);
+ counter_inc(bts->network->stats.chreq.total);
+
/* check availability / allocate channel */
lchan = lchan_alloc(bts, lctype);
if (!lchan) {
- DEBUGP(DRSL, "CHAN RQD: no resources for %s 0x%x\n",
- gsm_lchan_name(lctype), rqd_ref->ra);
+ LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
+ msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
+ counter_inc(bts->network->stats.chreq.no_channel);
/* FIXME: send some kind of reject ?!? */
return -ENOMEM;
}
+ if (lchan->state != LCHAN_S_NONE)
+ LOGP(DRSL, LOGL_NOTICE, "%s lchan_alloc() returned channel "
+ "in state %s\n", gsm_lchan_name(lchan),
+ gsm_lchans_name(lchan->state));
+ lchan->state = LCHAN_S_ACT_REQ;
+
ts_number = lchan->ts->nr;
arfcn = lchan->ts->trx->arfcn;
subch = lchan->nr;
@@ -1297,10 +1345,9 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
ia.timing_advance = rqd_ta;
ia.mob_alloc_len = 0;
- DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %s "
- "chan_nr=0x%02x r=%s ra=0x%02x\n",
- arfcn, ts_number, subch, gsm_lchan_name(lchan->type),
- ia.chan_desc.chan_nr, gsm_chreq_name(chreq_reason),
+ DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
+ "r=%s ra=0x%02x\n", gsm_lchan_name(lchan), arfcn, subch,
+ gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason),
rqd_ref->ra);
/* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */
@@ -1379,10 +1426,12 @@ static int rsl_rx_rll_err_ind(struct msgb *msg)
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
u_int8_t *rlm_cause = rllh->data;
- LOGP(DRLL, LOGL_ERROR, "ERROR INDICATION cause=0x%02x\n", rlm_cause[1]);
+ LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n",
+ gsm_lchan_name(msg->lchan),
+ get_value_string(rlm_cause_strs, rlm_cause[1]));
rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND);
-
+
if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED)
return rsl_rf_chan_release(msg->lchan);
@@ -1403,9 +1452,8 @@ static int abis_rsl_rx_rll(struct msgb *msg)
u_int8_t sapi = rllh->link_id & 7;
msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
- ts_name = gsm_ts_name(msg->lchan->ts);
- DEBUGP(DRLL, "channel=%s chan_nr=0x%02x sapi=%u ", ts_name,
- rllh->chan_nr, sapi);
+ ts_name = gsm_lchan_name(msg->lchan);
+ DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi);
switch (rllh->c.msg_type) {
case RSL_MT_DATA_IND:
@@ -1575,9 +1623,8 @@ int rsl_ipacc_crcx(struct gsm_lchan *lchan)
lchan->abis_ip.speech_mode = 0x10 | ipa_smod_s_for_lchan(lchan);
msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode);
- DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND "
- "speech_mode=0x%02x\n", gsm_ts_name(lchan->ts),
- dh->chan_nr, lchan->abis_ip.speech_mode);
+ DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x\n",
+ gsm_lchan_name(lchan), lchan->abis_ip.speech_mode);
msg->trx = lchan->ts->trx;
@@ -1606,9 +1653,8 @@ int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
lchan->abis_ip.speech_mode = 0x00 | ipa_smod_s_for_lchan(lchan);
ia.s_addr = htonl(ip);
- DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_MDCX "
- "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d speech_mode=0x%02x\n",
- gsm_ts_name(lchan->ts), dh->chan_nr, inet_ntoa(ia), port,
+ DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d "
+ "speech_mode=0x%02x\n", gsm_lchan_name(lchan), inet_ntoa(ia), port,
rtp_payload2, lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode);
msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id);
@@ -1649,8 +1695,7 @@ int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan)
dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
dh->chan_nr = lchan2chan_nr(lchan);
- DEBUGP(DRSL, "channel=%s chan_nr=0x%02x IPAC_PDCH_ACT\n",
- gsm_ts_name(lchan->ts), dh->chan_nr);
+ DEBUGP(DRSL, "%s IPAC_PDCH_ACT\n", gsm_lchan_name(lchan));
msg->trx = lchan->ts->trx;
@@ -1731,7 +1776,7 @@ static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
- print_rsl_cause(TLVP_VAL(&tv, RSL_IE_CAUSE),
+ print_rsl_cause(LOGL_DEBUG, TLVP_VAL(&tv, RSL_IE_CAUSE),
TLVP_LEN(&tv, RSL_IE_CAUSE));
/* the BTS tells us a RTP stream has been disconnected */
@@ -1748,38 +1793,38 @@ static int abis_rsl_rx_ipacc_dlcx_ind(struct msgb *msg)
static int abis_rsl_rx_ipacc(struct msgb *msg)
{
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
+ char *ts_name;
int rc = 0;
msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr);
- DEBUGP(DRSL, "channel=%s chan_nr=0x%02x ",
- gsm_ts_name(msg->lchan->ts), rllh->chan_nr);
+ ts_name = gsm_lchan_name(msg->lchan);
switch (rllh->c.msg_type) {
case RSL_MT_IPAC_CRCX_ACK:
- DEBUGPC(DRSL, "IPAC_CRCX_ACK ");
+ DEBUGP(DRSL, "%s IPAC_CRCX_ACK ", ts_name);
rc = abis_rsl_rx_ipacc_crcx_ack(msg);
break;
case RSL_MT_IPAC_CRCX_NACK:
/* somehow the BTS was unable to bind the lchan to its local
* port?!? */
- DEBUGPC(DRSL, "IPAC_CRCX_NACK ");
+ LOGP(DRSL, LOGL_ERROR, "%s IPAC_CRCX_NACK\n", ts_name);
break;
case RSL_MT_IPAC_MDCX_ACK:
/* the BTS tells us that a connect operation was successful */
- DEBUGPC(DRSL, "IPAC_MDCX_ACK ");
+ DEBUGP(DRSL, "%s IPAC_MDCX_ACK ", ts_name);
rc = abis_rsl_rx_ipacc_mdcx_ack(msg);
break;
case RSL_MT_IPAC_MDCX_NACK:
/* somehow the BTS was unable to connect the lchan to a remote
* port */
- DEBUGPC(DRSL, "IPAC_MDCX_NACK ");
+ LOGP(DRSL, LOGL_ERROR, "%s IPAC_MDCX_NACK\n", ts_name);
break;
case RSL_MT_IPAC_DLCX_IND:
- DEBUGPC(DRSL, "IPAC_DLCX_IND ");
+ DEBUGP(DRSL, "%s IPAC_DLCX_IND ", ts_name);
rc = abis_rsl_rx_ipacc_dlcx_ind(msg);
break;
default:
- LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x",
+ LOGP(DRSL, LOGL_NOTICE, "Unknown ip.access msg_type 0x%02x\n",
rllh->c.msg_type);
break;
}
diff --git a/openbsc/src/bs11_config.c b/openbsc/src/bs11_config.c
index 3e8bf88a3..b2470a9fc 100644
--- a/openbsc/src/bs11_config.c
+++ b/openbsc/src/bs11_config.c
@@ -71,6 +71,13 @@ static const char *trx1_password = "1111111111";
static const u_int8_t too_fast[] = { 0x12, 0x80, 0x00, 0x00, 0x02, 0x02 };
+static struct debug_target *stderr_target;
+
+/* dummy function to keep gsm_data.c happy */
+struct counter *counter_alloc(const char *name)
+{
+ return NULL;
+}
int handle_serial_msg(struct msgb *rx_msg);
@@ -754,7 +761,7 @@ static void handle_options(int argc, char **argv)
serial_port = optarg;
break;
case 'b':
- debug_parse_category_mask(optarg);
+ debug_parse_category_mask(stderr_target, optarg);
break;
case 's':
fname_software = optarg;
@@ -807,6 +814,10 @@ int main(int argc, char **argv)
struct gsm_network *gsmnet;
int rc;
+ debug_init();
+ stderr_target = debug_target_create_stderr();
+ debug_add_target(stderr_target);
+ debug_set_all_filter(stderr_target, 1);
handle_options(argc, argv);
gsmnet = gsm_network_init(1, 1, NULL);
diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c
index a9a5d372f..3122fae9c 100644
--- a/openbsc/src/bsc_hack.c
+++ b/openbsc/src/bsc_hack.c
@@ -38,10 +38,16 @@
#include <openbsc/signal.h>
/* MCC and MNC for the Location Area Identifier */
+static struct debug_target *stderr_target;
struct gsm_network *bsc_gsmnet = 0;
static const char *database_name = "hlr.sqlite3";
static const char *config_file = "openbsc.cfg";
+
+/* timer to store statistics */
+#define DB_SYNC_INTERVAL 60, 0
+static struct timer_list db_sync_timer;
+
extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
const char *cfg_file);
extern int bsc_shutdown_net(struct gsm_network *net);
@@ -105,10 +111,10 @@ static void handle_options(int argc, char** argv)
print_help();
exit(0);
case 's':
- debug_use_color(0);
+ debug_set_use_color(stderr_target, 0);
break;
case 'd':
- debug_parse_category_mask(optarg);
+ debug_parse_category_mask(stderr_target, optarg);
break;
case 'l':
database_name = strdup(optarg);
@@ -120,7 +126,7 @@ static void handle_options(int argc, char** argv)
create_pcap_file(optarg);
break;
case 'T':
- debug_timestamp(1);
+ debug_set_print_timestamp(stderr_target, 1);
break;
case 'P':
ipacc_rtp_direct = 0;
@@ -132,6 +138,7 @@ static void handle_options(int argc, char** argv)
}
}
+extern void *tall_vty_ctx;
static void signal_handler(int signal)
{
fprintf(stdout, "signal %u received\n", signal);
@@ -147,22 +154,45 @@ static void signal_handler(int signal)
/* in case of abort, we want to obtain a talloc report
* and then return to the caller, who will abort the process */
case SIGUSR1:
+ talloc_report(tall_vty_ctx, stderr);
talloc_report_full(tall_bsc_ctx, stderr);
break;
+ case SIGUSR2:
+ talloc_report_full(tall_vty_ctx, stderr);
+ break;
default:
break;
}
}
+/* timer handling */
+static int _db_store_counter(struct counter *counter, void *data)
+{
+ return db_store_counter(counter);
+}
+
+static void db_sync_timer_cb(void *data)
+{
+ /* store counters to database and re-schedule */
+ counters_for_each(_db_store_counter, NULL);
+ bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
+}
+
int main(int argc, char **argv)
{
int rc;
+ debug_init();
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
talloc_ctx_init();
on_dso_load_token();
on_dso_load_rrlp();
on_dso_load_ho_dec();
+ stderr_target = debug_target_create_stderr();
+ debug_add_target(stderr_target);
+
+ /* enable filters */
+ debug_set_all_filter(stderr_target, 1);
/* parse options */
handle_options(argc, argv);
@@ -182,6 +212,11 @@ int main(int argc, char **argv)
}
printf("DB: Database prepared.\n");
+ /* setup the timer */
+ db_sync_timer.cb = db_sync_timer_cb;
+ db_sync_timer.data = NULL;
+ bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
+
rc = bsc_bootstrap_network(mncc_recv, config_file);
if (rc < 0)
exit(1);
@@ -189,10 +224,12 @@ int main(int argc, char **argv)
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
+ signal(SIGUSR2, &signal_handler);
signal(SIGPIPE, SIG_IGN);
while (1) {
bsc_upqueue(bsc_gsmnet);
+ debug_reset_context();
bsc_select_main(0);
}
}
diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c
index 7fbac0a10..2f8b6a226 100644
--- a/openbsc/src/bsc_init.c
+++ b/openbsc/src/bsc_init.c
@@ -420,8 +420,10 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
switch (obj_class) {
case NM_OC_SITE_MANAGER:
bts = container_of(obj, struct gsm_bts, site_mgr);
- if (new_state->operational == 2 &&
- new_state->availability == NM_AVSTATE_OK)
+ if ((new_state->operational == 2 &&
+ new_state->availability == NM_AVSTATE_OK) ||
+ (new_state->operational == 1 &&
+ new_state->availability == NM_AVSTATE_OFF_LINE))
abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
break;
case NM_OC_BTS:
@@ -516,6 +518,8 @@ static int sw_activ_rep(struct msgb *mb)
struct gsm_bts *bts = mb->trx->bts;
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
+ if (!trx)
+ return -EINVAL;
switch (foh->obj_class) {
case NM_OC_BASEB_TRANSC:
@@ -537,8 +541,7 @@ static int sw_activ_rep(struct msgb *mb)
* This code is here to make sure that on start
* a TRX remains locked.
*/
- int rc_state = trx->rf_locked ?
- NM_STATE_LOCKED : NM_STATE_UNLOCKED;
+ int rc_state = trx->nm_state.administrative;
/* Patch ARFCN into radio attribute */
nanobts_attr_radio[5] &= 0xf0;
nanobts_attr_radio[5] |= trx->arfcn >> 8;
@@ -881,9 +884,10 @@ static void patch_nm_tables(struct gsm_bts *bts)
static void bootstrap_rsl(struct gsm_bts_trx *trx)
{
LOGP(DRSL, LOGL_NOTICE, "bootstrapping RSL for BTS/TRX (%u/%u) "
- "using MCC=%u MNC=%u BSIC=%u TSC=%u\n",
- trx->bts->nr, trx->nr, bsc_gsmnet->country_code,
- bsc_gsmnet->network_code, trx->bts->bsic, trx->bts->tsc);
+ "on ARFCN %u using MCC=%u MNC=%u LAC=%u CID=%u BSIC=%u TSC=%u\n",
+ trx->bts->nr, trx->nr, trx->arfcn, bsc_gsmnet->country_code,
+ bsc_gsmnet->network_code, trx->bts->location_area_code,
+ trx->bts->cell_identity, trx->bts->bsic, trx->bts->tsc);
set_system_infos(trx);
}
@@ -939,7 +943,7 @@ static int bootstrap_bts(struct gsm_bts *bts)
if (bts->network->auth_policy == GSM_AUTH_POLICY_ACCEPT_ALL &&
!bts->si_common.rach_control.cell_bar)
- LOGP(DNM, LOG_ERROR, "\nWARNING: You are running an 'accept-all' "
+ LOGP(DNM, LOGL_ERROR, "\nWARNING: You are running an 'accept-all' "
"network on a BTS that is not barred. This "
"configuration is likely to interfere with production "
"GSM networks and should only be used in a RF "
@@ -952,11 +956,6 @@ static int bootstrap_bts(struct gsm_bts *bts)
/* T3212 is set from vty/config */
/* some defaults for our system information */
- bts->si_common.rach_control.re = 1; /* no re-establishment */
- bts->si_common.rach_control.tx_integer = 5; /* 8 slots spread */
- bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
- bts->si_common.rach_control.t2 = 4; /* no emergency calls */
-
bts->si_common.cell_options.radio_link_timeout = 2; /* 12 */
bts->si_common.cell_options.dtx = 2; /* MS shall not use upplink DTX */
bts->si_common.cell_options.pwrc = 0; /* PWRC not set */
diff --git a/openbsc/src/bsc_mgcp.c b/openbsc/src/bsc_mgcp.c
index 6d5e6b154..fff6d6039 100644
--- a/openbsc/src/bsc_mgcp.c
+++ b/openbsc/src/bsc_mgcp.c
@@ -1084,8 +1084,15 @@ int main(int argc, char** argv)
struct gsm_network dummy_network;
struct sockaddr_in addr;
int on = 1, i, rc;
+ struct debug_target *stderr_target;
tall_bsc_ctx = talloc_named_const(NULL, 1, "mgcp-callagent");
+
+ debug_init();
+ stderr_target = debug_target_create_stderr();
+ debug_add_target(stderr_target);
+ debug_set_all_filter(stderr_target, 1);
+
handle_options(argc, argv);
telnet_init(&dummy_network, 4243);
diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c
index c42b60b46..2e885241c 100644
--- a/openbsc/src/chan_alloc.c
+++ b/openbsc/src/chan_alloc.c
@@ -35,6 +35,29 @@
static void auto_release_channel(void *_lchan);
+static int ts_is_usable(struct gsm_bts_trx_ts *ts)
+{
+ /* FIXME: How does this behave for BS-11 ? */
+ if (is_ipaccess_bts(ts->trx->bts)) {
+ if (!nm_is_running(&ts->nm_state))
+ return 0;
+ }
+
+ return 1;
+}
+
+int trx_is_usable(struct gsm_bts_trx *trx)
+{
+ /* FIXME: How does this behave for BS-11 ? */
+ if (is_ipaccess_bts(trx->bts)) {
+ if (!nm_is_running(&trx->nm_state) ||
+ !nm_is_running(&trx->bb_transc.nm_state))
+ return 0;
+ }
+
+ return 1;
+}
+
struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
enum gsm_phys_chan_config pchan)
{
@@ -63,6 +86,9 @@ struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
llist_for_each_entry(trx, &bts->trx_list, list) {
int from, to;
+ if (!trx_is_usable(trx))
+ continue;
+
/* the following constraints are pure policy,
* no requirement to put this restriction in place */
if (trx == bts->c0) {
@@ -97,6 +123,10 @@ struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
for (j = from; j <= to; j++) {
struct gsm_bts_trx_ts *ts = &trx->ts[j];
+
+ if (!ts_is_usable(ts))
+ continue;
+
if (ts->pchan == GSM_PCHAN_NONE) {
ts->pchan = pchan;
/* set channel attribute on OML */
@@ -121,6 +151,7 @@ static const u_int8_t subslots_per_pchan[] = {
[GSM_PCHAN_TCH_F] = 1,
[GSM_PCHAN_TCH_H] = 2,
[GSM_PCHAN_SDCCH8_SACCH8C] = 8,
+ /* FIXME: what about dynamic TCH_F_TCH_H ? */
};
static struct gsm_lchan *
@@ -129,14 +160,20 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan)
struct gsm_bts_trx_ts *ts;
int j, ss;
+ if (!trx_is_usable(trx))
+ return NULL;
+
for (j = 0; j < 8; j++) {
ts = &trx->ts[j];
+ if (!ts_is_usable(ts))
+ continue;
if (ts->pchan != pchan)
continue;
/* check if all sub-slots are allocated yet */
for (ss = 0; ss < subslots_per_pchan[pchan]; ss++) {
struct gsm_lchan *lc = &ts->lchan[ss];
- if (lc->type == GSM_LCHAN_NONE)
+ if (lc->type == GSM_LCHAN_NONE &&
+ lc->state == LCHAN_S_NONE)
return lc;
}
}
@@ -262,6 +299,8 @@ void lchan_free(struct gsm_lchan *lchan)
for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++)
lchan->neigh_meas[i].arfcn = 0;
+ lchan->silent_call = 0;
+
/* FIXME: ts_free() the timeslot, if we're the last logical
* channel using it */
}
@@ -283,7 +322,7 @@ int lchan_auto_release(struct gsm_lchan *lchan)
LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n",
lchan->use_count);
- DEBUGP(DRLL, "Recycling the channel with: %d (%x)\n", lchan->nr, lchan->nr);
+ DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan));
rsl_release_request(lchan, 0);
return 1;
}
@@ -329,3 +368,51 @@ struct gsm_lchan *lchan_for_subscr(struct gsm_subscriber *subscr)
return NULL;
}
+
+void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts)
+{
+ struct gsm_bts_trx *trx;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ int i;
+
+ /* skip administratively deactivated tranxsceivers */
+ if (!nm_is_running(&trx->nm_state) ||
+ !nm_is_running(&trx->bb_transc.nm_state))
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ struct load_counter *pl = &cl->pchan[ts->pchan];
+ int j;
+
+ /* skip administratively deactivated timeslots */
+ if (!nm_is_running(&ts->nm_state))
+ continue;
+
+ for (j = 0; j < subslots_per_pchan[ts->pchan]; j++) {
+ struct gsm_lchan *lchan = &ts->lchan[j];
+
+ pl->total++;
+
+ switch (lchan->state) {
+ case LCHAN_S_NONE:
+ break;
+ default:
+ pl->used++;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void network_chan_load(struct pchan_load *pl, struct gsm_network *net)
+{
+ struct gsm_bts *bts;
+
+ memset(pl, 0, sizeof(*pl));
+
+ llist_for_each_entry(bts, &net->bts_list, list)
+ bts_chan_load(pl, bts);
+}
diff --git a/openbsc/src/comp128.c b/openbsc/src/comp128.c
new file mode 100644
index 000000000..9df545256
--- /dev/null
+++ b/openbsc/src/comp128.c
@@ -0,0 +1,230 @@
+/*
+ * COMP128 implementation
+ *
+ *
+ * This code is inspired by original code from :
+ * Marc Briceno <marc@scard.org>, Ian Goldberg <iang@cs.berkeley.edu>,
+ * and David Wagner <daw@cs.berkeley.edu>
+ *
+ * But it has been fully rewritten from various PDFs found online describing
+ * the algorithm because the licence of the code referenced above was unclear.
+ * A comment snippet from the original code is included below, it describes
+ * where the doc came from and how the algorithm was reverse engineered.
+ *
+ *
+ * (C) 2009 by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+/*
+ * --- SNIP ---
+ *
+ * This code derived from a leaked document from the GSM standards.
+ * Some missing pieces were filled in by reverse-engineering a working SIM.
+ * We have verified that this is the correct COMP128 algorithm.
+ *
+ * The first page of the document identifies it as
+ * _Technical Information: GSM System Security Study_.
+ * 10-1617-01, 10th June 1988.
+ * The bottom of the title page is marked
+ * Racal Research Ltd.
+ * Worton Drive, Worton Grange Industrial Estate,
+ * Reading, Berks. RG2 0SB, England.
+ * Telephone: Reading (0734) 868601 Telex: 847152
+ * The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy!
+ *
+ * Note: There are three typos in the spec (discovered by
+ * reverse-engineering).
+ * First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read
+ * "z = (2 * x[m] + x[n]) mod 2^(9-j)".
+ * Second, the "k" loop in the "Form bits from bytes" section is severely
+ * botched: the k index should run only from 0 to 3, and clearly the range
+ * on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8,
+ * to be consistent with the subsequent section).
+ * Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as
+ * claimed in the document. (And the document doesn't specify how Kc is
+ * derived, but that was also easily discovered with reverse engineering.)
+ * All of these typos have been corrected in the following code.
+ *
+ * --- /SNIP ---
+ */
+
+#include <string.h>
+#include <sys/types.h>
+
+/* The compression tables (just copied ...) */
+static const u_int8_t table_0[512] = {
+ 102, 177, 186, 162, 2, 156, 112, 75, 55, 25, 8, 12, 251, 193, 246, 188,
+ 109, 213, 151, 53, 42, 79, 191, 115, 233, 242, 164, 223, 209, 148, 108, 161,
+ 252, 37, 244, 47, 64, 211, 6, 237, 185, 160, 139, 113, 76, 138, 59, 70,
+ 67, 26, 13, 157, 63, 179, 221, 30, 214, 36, 166, 69, 152, 124, 207, 116,
+ 247, 194, 41, 84, 71, 1, 49, 14, 95, 35, 169, 21, 96, 78, 215, 225,
+ 182, 243, 28, 92, 201, 118, 4, 74, 248, 128, 17, 11, 146, 132, 245, 48,
+ 149, 90, 120, 39, 87, 230, 106, 232, 175, 19, 126, 190, 202, 141, 137, 176,
+ 250, 27, 101, 40, 219, 227, 58, 20, 51, 178, 98, 216, 140, 22, 32, 121,
+ 61, 103, 203, 72, 29, 110, 85, 212, 180, 204, 150, 183, 15, 66, 172, 196,
+ 56, 197, 158, 0, 100, 45, 153, 7, 144, 222, 163, 167, 60, 135, 210, 231,
+ 174, 165, 38, 249, 224, 34, 220, 229, 217, 208, 241, 68, 206, 189, 125, 255,
+ 239, 54, 168, 89, 123, 122, 73, 145, 117, 234, 143, 99, 129, 200, 192, 82,
+ 104, 170, 136, 235, 93, 81, 205, 173, 236, 94, 105, 52, 46, 228, 198, 5,
+ 57, 254, 97, 155, 142, 133, 199, 171, 187, 50, 65, 181, 127, 107, 147, 226,
+ 184, 218, 131, 33, 77, 86, 31, 44, 88, 62, 238, 18, 24, 43, 154, 23,
+ 80, 159, 134, 111, 9, 114, 3, 91, 16, 130, 83, 10, 195, 240, 253, 119,
+ 177, 102, 162, 186, 156, 2, 75, 112, 25, 55, 12, 8, 193, 251, 188, 246,
+ 213, 109, 53, 151, 79, 42, 115, 191, 242, 233, 223, 164, 148, 209, 161, 108,
+ 37, 252, 47, 244, 211, 64, 237, 6, 160, 185, 113, 139, 138, 76, 70, 59,
+ 26, 67, 157, 13, 179, 63, 30, 221, 36, 214, 69, 166, 124, 152, 116, 207,
+ 194, 247, 84, 41, 1, 71, 14, 49, 35, 95, 21, 169, 78, 96, 225, 215,
+ 243, 182, 92, 28, 118, 201, 74, 4, 128, 248, 11, 17, 132, 146, 48, 245,
+ 90, 149, 39, 120, 230, 87, 232, 106, 19, 175, 190, 126, 141, 202, 176, 137,
+ 27, 250, 40, 101, 227, 219, 20, 58, 178, 51, 216, 98, 22, 140, 121, 32,
+ 103, 61, 72, 203, 110, 29, 212, 85, 204, 180, 183, 150, 66, 15, 196, 172,
+ 197, 56, 0, 158, 45, 100, 7, 153, 222, 144, 167, 163, 135, 60, 231, 210,
+ 165, 174, 249, 38, 34, 224, 229, 220, 208, 217, 68, 241, 189, 206, 255, 125,
+ 54, 239, 89, 168, 122, 123, 145, 73, 234, 117, 99, 143, 200, 129, 82, 192,
+ 170, 104, 235, 136, 81, 93, 173, 205, 94, 236, 52, 105, 228, 46, 5, 198,
+ 254, 57, 155, 97, 133, 142, 171, 199, 50, 187, 181, 65, 107, 127, 226, 147,
+ 218, 184, 33, 131, 86, 77, 44, 31, 62, 88, 18, 238, 43, 24, 23, 154,
+ 159, 80, 111, 134, 114, 9, 91, 3, 130, 16, 10, 83, 240, 195, 119, 253,
+}, table_1[256] = {
+ 19, 11, 80, 114, 43, 1, 69, 94, 39, 18, 127, 117, 97, 3, 85, 43,
+ 27, 124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5,
+ 35, 107, 103, 68, 21, 86, 36, 91, 85, 126, 32, 50, 109, 94, 120, 6,
+ 53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55, 110, 125, 105, 20,
+ 90, 80, 76, 96, 23, 60, 89, 64, 121, 56, 14, 74, 101, 8, 19, 78,
+ 76, 66, 104, 46, 111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51,
+ 57, 65, 119, 116, 22, 109, 7, 86, 59, 93, 62, 110, 78, 99, 77, 67,
+ 12, 113, 87, 98, 102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75,
+ 95, 63, 28, 49, 123, 120, 20, 112, 44, 30, 15, 98, 106, 2, 103, 29,
+ 82, 107, 42, 124, 24, 30, 41, 16, 108, 100, 117, 40, 73, 40, 7, 114,
+ 82, 115, 36, 112, 12, 102, 100, 84, 92, 48, 72, 97, 9, 54, 55, 74,
+ 113, 123, 17, 26, 53, 58, 4, 9, 69, 122, 21, 118, 42, 60, 27, 73,
+ 118, 125, 34, 15, 65, 115, 84, 64, 62, 81, 70, 1, 24, 111, 121, 83,
+ 104, 81, 49, 127, 48, 105, 31, 10, 6, 91, 87, 37, 16, 54, 116, 126,
+ 31, 38, 13, 0, 72, 106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52,
+ 101, 17, 44, 108, 71, 52, 66, 57, 33, 51, 25, 90, 2, 119, 122, 35,
+}, table_2[128] = {
+ 52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43,
+ 37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18,
+ 55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59,
+ 62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56,
+ 48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61,
+ 29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0,
+ 20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27,
+ 31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7,
+}, table_3[64] = {
+ 1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31,
+ 28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9,
+ 20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10,
+ 17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19,
+}, table_4[32] = {
+ 15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8,
+ 10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12,
+};
+
+static const u_int8_t *_comp128_table[5] = { table_0, table_1, table_2, table_3, table_4 };
+
+
+static inline void
+_comp128_compression_round(u_int8_t *x, int n, const u_int8_t *tbl)
+{
+ int i, j, m, a, b, y, z;
+ m = 4 - n;
+ for (i=0; i<(1<<n); i++)
+ for (j=0; j<(1<<m); j++) {
+ a = j + i * (2<<m);
+ b = a + (1<<m);
+ y = (x[a] + (x[b]<<1)) & ((32<<m)-1);
+ z = ((x[a]<<1) + x[b]) & ((32<<m)-1);
+ x[a] = tbl[y];
+ x[b] = tbl[z];
+ }
+}
+
+static inline void
+_comp128_compression(u_int8_t *x)
+{
+ int n;
+ for (n=0; n<5; n++)
+ _comp128_compression_round(x, n, _comp128_table[n]);
+}
+
+static inline void
+_comp128_bitsfrombytes(u_int8_t *x, u_int8_t *bits)
+{
+ int i;
+ memset(bits, 0x00, 128);
+ for (i=0; i<128; i++)
+ if (x[i>>2] & (1<<(3-(i&3))))
+ bits[i] = 1;
+}
+
+static inline void
+_comp128_permutation(u_int8_t *x, u_int8_t *bits)
+{
+ int i;
+ memset(&x[16], 0x00, 16);
+ for (i=0; i<128; i++)
+ x[(i>>3)+16] |= bits[(i*17) & 127] << (7-(i&7));
+}
+
+void
+comp128(u_int8_t *ki, u_int8_t *rand, u_int8_t *sres, u_int8_t *kc)
+{
+ int i;
+ u_int8_t x[32], bits[128];
+
+ /* x[16-31] = RAND */
+ memcpy(&x[16], rand, 16);
+
+ /* Round 1-7 */
+ for (i=0; i<7; i++) {
+ /* x[0-15] = Ki */
+ memcpy(x, ki, 16);
+
+ /* Compression */
+ _comp128_compression(x);
+
+ /* FormBitFromBytes */
+ _comp128_bitsfrombytes(x, bits);
+
+ /* Permutation */
+ _comp128_permutation(x, bits);
+ }
+
+ /* Round 8 (final) */
+ /* x[0-15] = Ki */
+ memcpy(x, ki, 16);
+
+ /* Compression */
+ _comp128_compression(x);
+
+ /* Output stage */
+ for (i=0; i<8; i+=2)
+ sres[i>>1] = x[i]<<4 | x[i+1];
+
+ for (i=0; i<12; i+=2)
+ kc[i>>1] = (x[i + 18] << 6) |
+ (x[i + 19] << 2) |
+ (x[i + 20] >> 2);
+
+ kc[6] = (x[30]<<6) | (x[31]<<2);
+ kc[7] = 0;
+}
+
diff --git a/openbsc/src/db.c b/openbsc/src/db.c
index d85386548..5be47ff64 100644
--- a/openbsc/src/db.c
+++ b/openbsc/src/db.c
@@ -25,6 +25,7 @@
#include <openbsc/db.h>
#include <openbsc/talloc.h>
#include <openbsc/debug.h>
+#include <openbsc/statistics.h>
#include <libgen.h>
#include <stdio.h>
@@ -117,12 +118,35 @@ static char *create_stmts[] = {
"subscriber_id INTEGER NOT NULL, "
"apdu BLOB "
")",
+ "CREATE TABLE IF NOT EXISTS Counters ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "timestamp TIMESTAMP NOT NULL, "
+ "value INTEGER NOT NULL, "
+ "name TEXT NOT NULL "
+ ")",
+ "CREATE TABLE IF NOT EXISTS AuthKeys ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "subscriber_id INTEGER UNIQUE NOT NULL, "
+ "algorithm_id INTEGER NOT NULL, "
+ "a3a8_ki BLOB "
+ ")",
+ "CREATE TABLE IF NOT EXISTS AuthTuples ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "subscriber_id NUMERIC UNIQUE NOT NULL, "
+ "issued TIMESTAMP NOT NULL, "
+ "use_count INTEGER NOT NULL DEFAULT 0, "
+ "key_seq INTEGER NOT NULL, "
+ "rand BLOB NOT NULL, "
+ "sres BLOB NOT NULL, "
+ "kc BLOB NOT NULL "
+ ")",
};
-void db_error_func(dbi_conn conn, void* data) {
- const char* msg;
+void db_error_func(dbi_conn conn, void *data)
+{
+ const char *msg;
dbi_conn_error(conn, &msg);
- printf("DBI: %s\n", msg);
+ LOGP(DDB, LOGL_ERROR, "DBI: %s\n", msg);
}
static int check_db_revision(void)
@@ -149,11 +173,13 @@ static int check_db_revision(void)
return 0;
}
-int db_init(const char *name) {
+int db_init(const char *name)
+{
dbi_initialize(NULL);
+
conn = dbi_conn_new("sqlite3");
- if (conn==NULL) {
- printf("DB: Failed to create connection.\n");
+ if (conn == NULL) {
+ LOGP(DDB, LOGL_FATAL, "Failed to create connection.\n");
return 1;
}
@@ -186,21 +212,23 @@ out_err:
}
-int db_prepare() {
+int db_prepare()
+{
dbi_result result;
int i;
for (i = 0; i < ARRAY_SIZE(create_stmts); i++) {
result = dbi_conn_query(conn, create_stmts[i]);
- if (result==NULL) {
- printf("DB: Failed to create some table.\n");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to create some table.\n");
return 1;
}
dbi_result_free(result);
}
if (check_db_revision() < 0) {
- fprintf(stderr, "Database schema revision invalid, "
+ LOGP(DDB, LOGL_FATAL, "Database schema revision invalid, "
"please update your database schema\n");
return -1;
}
@@ -208,7 +236,8 @@ int db_prepare() {
return 0;
}
-int db_fini() {
+int db_fini()
+{
dbi_conn_close(conn);
dbi_shutdown();
@@ -219,10 +248,10 @@ int db_fini() {
return 0;
}
-struct gsm_subscriber* db_create_subscriber(struct gsm_network *net, char *imsi)
+struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi)
{
dbi_result result;
- struct gsm_subscriber* subscr;
+ struct gsm_subscriber *subscr;
/* Is this subscriber known in the db? */
subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi);
@@ -230,11 +259,10 @@ struct gsm_subscriber* db_create_subscriber(struct gsm_network *net, char *imsi)
result = dbi_conn_queryf(conn,
"UPDATE Subscriber set updated = datetime('now') "
"WHERE imsi = %s " , imsi);
- if (result==NULL) {
- printf("DB: failed to update timestamp\n");
- } else {
+ if (!result)
+ LOGP(DDB, LOGL_ERROR, "failed to update timestamp\n");
+ else
dbi_result_free(result);
- }
return subscr;
}
@@ -249,14 +277,13 @@ struct gsm_subscriber* db_create_subscriber(struct gsm_network *net, char *imsi)
"(%s, datetime('now'), datetime('now')) ",
imsi
);
- if (result==NULL) {
- printf("DB: Failed to create Subscriber by IMSI.\n");
- }
+ if (!result)
+ LOGP(DDB, LOGL_ERROR, "Failed to create Subscriber by IMSI.\n");
subscr->net = net;
subscr->id = dbi_conn_sequence_last(conn, NULL);
strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1);
dbi_result_free(result);
- printf("DB: New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi);
+ LOGP(DDB, LOGL_INFO, "New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi);
db_subscriber_alloc_exten(subscr);
return subscr;
}
@@ -288,7 +315,9 @@ static int get_equipment_by_subscr(struct gsm_subscriber *subscr)
if (string)
strncpy(equip->imei, string, sizeof(equip->imei));
- cm1 = dbi_result_get_uint(result, "classmark1") & 0xff;
+ string = dbi_result_get_string(result, "classmark1");
+ if (string)
+ cm1 = atoi(string) & 0xff;
equip->classmark1 = *((struct gsm48_classmark1 *) &cm1);
equip->classmark2_len = dbi_result_get_field_length(result, "classmark2");
@@ -307,6 +336,214 @@ static int get_equipment_by_subscr(struct gsm_subscriber *subscr)
return 0;
}
+
+int get_authinfo_by_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr)
+{
+ dbi_result result;
+ const unsigned char *a3a8_ki;
+
+ result = dbi_conn_queryf(conn,
+ "SELECT * FROM AuthKeys WHERE subscriber_id=%u",
+ subscr->id);
+ if (!result)
+ return -EIO;
+
+ if (!dbi_result_next_row(result)) {
+ dbi_result_free(result);
+ return -ENOENT;
+ }
+
+ ainfo->auth_algo = dbi_result_get_ulonglong(result, "algorithm_id");
+ ainfo->a3a8_ki_len = dbi_result_get_field_length(result, "a3a8_ki");
+ a3a8_ki = dbi_result_get_binary(result, "a3a8_ki");
+ if (ainfo->a3a8_ki_len > sizeof(ainfo->a3a8_ki))
+ ainfo->a3a8_ki_len = sizeof(ainfo->a3a8_ki_len);
+ memcpy(ainfo->a3a8_ki, a3a8_ki, ainfo->a3a8_ki_len);
+
+ dbi_result_free(result);
+
+ return 0;
+}
+
+int set_authinfo_for_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr)
+{
+ dbi_result result;
+ struct gsm_auth_info ainfo_old;
+ int rc, upd;
+ unsigned char *ki_str;
+
+ /* Deletion ? */
+ if (ainfo == NULL) {
+ result = dbi_conn_queryf(conn,
+ "DELETE FROM AuthKeys WHERE subscriber_id=%u",
+ subscr->id);
+
+ if (!result)
+ return -EIO;
+
+ dbi_result_free(result);
+
+ return 0;
+ }
+
+ /* Check if already existing */
+ rc = get_authinfo_by_subscr(&ainfo_old, subscr);
+ if (rc && rc != -ENOENT)
+ return rc;
+ upd = rc ? 0 : 1;
+
+ /* Update / Insert */
+ dbi_conn_quote_binary_copy(conn,
+ ainfo->a3a8_ki, ainfo->a3a8_ki_len, &ki_str);
+
+ if (!upd) {
+ result = dbi_conn_queryf(conn,
+ "INSERT INTO AuthKeys "
+ "(subscriber_id, algorithm_id, a3a8_ki) "
+ "VALUES (%u, %u, %s)",
+ subscr->id, ainfo->auth_algo, ki_str);
+ } else {
+ result = dbi_conn_queryf(conn,
+ "UPDATE AuthKeys "
+ "SET algorithm_id=%u, a3a8_ki=%s "
+ "WHERE subscriber_id=%u",
+ ainfo->auth_algo, ki_str, subscr->id);
+ }
+
+ free(ki_str);
+
+ if (!result)
+ return -EIO;
+
+ dbi_result_free(result);
+
+ return 0;
+}
+
+int get_authtuple_by_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr)
+{
+ dbi_result result;
+ int len;
+ const unsigned char *blob;
+
+ result = dbi_conn_queryf(conn,
+ "SELECT * FROM AuthTuples WHERE subscriber_id=%u",
+ subscr->id);
+ if (!result)
+ return -EIO;
+
+ if (!dbi_result_next_row(result)) {
+ dbi_result_free(result);
+ return -ENOENT;
+ }
+
+ memset(atuple, 0, sizeof(atuple));
+
+ atuple->use_count = dbi_result_get_ulonglong(result, "use_count");
+ atuple->key_seq = dbi_result_get_ulonglong(result, "key_seq");
+
+ len = dbi_result_get_field_length(result, "rand");
+ if (len != sizeof(atuple->rand))
+ goto err_size;
+
+ blob = dbi_result_get_binary(result, "rand");
+ memcpy(atuple->rand, blob, len);
+
+ len = dbi_result_get_field_length(result, "sres");
+ if (len != sizeof(atuple->sres))
+ goto err_size;
+
+ blob = dbi_result_get_binary(result, "sres");
+ memcpy(atuple->sres, blob, len);
+
+ len = dbi_result_get_field_length(result, "kc");
+ if (len != sizeof(atuple->kc))
+ goto err_size;
+
+ blob = dbi_result_get_binary(result, "kc");
+ memcpy(atuple->kc, blob, len);
+
+ dbi_result_free(result);
+
+ return 0;
+
+err_size:
+ dbi_result_free(result);
+ return -EIO;
+}
+
+int set_authtuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr)
+{
+ dbi_result result;
+ int rc, upd;
+ struct gsm_auth_tuple atuple_old;
+ unsigned char *rand_str, *sres_str, *kc_str;
+
+ /* Deletion ? */
+ if (atuple == NULL) {
+ result = dbi_conn_queryf(conn,
+ "DELETE FROM AuthTuples WHERE subscriber_id=%u",
+ subscr->id);
+
+ if (!result)
+ return -EIO;
+
+ dbi_result_free(result);
+
+ return 0;
+ }
+
+ /* Check if already existing */
+ rc = get_authtuple_by_subscr(&atuple_old, subscr);
+ if (rc && rc != -ENOENT)
+ return rc;
+ upd = rc ? 0 : 1;
+
+ /* Update / Insert */
+ dbi_conn_quote_binary_copy(conn,
+ atuple->rand, sizeof(atuple->rand), &rand_str);
+ dbi_conn_quote_binary_copy(conn,
+ atuple->sres, sizeof(atuple->sres), &sres_str);
+ dbi_conn_quote_binary_copy(conn,
+ atuple->kc, sizeof(atuple->kc), &kc_str);
+
+ if (!upd) {
+ result = dbi_conn_queryf(conn,
+ "INSERT INTO AuthTuples "
+ "(subscriber_id, issued, use_count, "
+ "key_seq, rand, sres, kc) "
+ "VALUES (%u, datetime('now'), %u, "
+ "%u, %s, %s, %s ) ",
+ subscr->id, atuple->use_count, atuple->key_seq,
+ rand_str, sres_str, kc_str);
+ } else {
+ char *issued = atuple->key_seq == atuple_old.key_seq ?
+ "issued" : "datetime('now')";
+ result = dbi_conn_queryf(conn,
+ "UPDATE AuthKeys "
+ "SET issued=%s, use_count=%u, "
+ "key_seq=%u, rand=%s, sres=%s, kc=%s "
+ "WHERE subscriber_id = %u",
+ issued, atuple->use_count, atuple->key_seq,
+ rand_str, sres_str, kc_str, subscr->id);
+ }
+
+ free(rand_str);
+ free(sres_str);
+ free(kc_str);
+
+ if (!result)
+ return -EIO;
+
+ dbi_result_free(result);
+
+ return 0;
+}
+
#define BASE_QUERY "SELECT * FROM Subscriber "
struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
enum gsm_subscriber_field field,
@@ -353,15 +590,15 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
free(quoted);
break;
default:
- printf("DB: Unknown query selector for Subscriber.\n");
+ LOGP(DDB, LOGL_NOTICE, "Unknown query selector for Subscriber.\n");
return NULL;
}
- if (result==NULL) {
- printf("DB: Failed to query Subscriber.\n");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR, "Failed to query Subscriber.\n");
return NULL;
}
if (!dbi_result_next_row(result)) {
- printf("DB: Failed to find the Subscriber. '%u' '%s'\n",
+ DEBUGP(DDB, "Failed to find the Subscriber. '%u' '%s'\n",
field, id);
dbi_result_free(result);
return NULL;
@@ -388,7 +625,7 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
subscr->lac = dbi_result_get_uint(result, "lac");
subscr->authorized = dbi_result_get_uint(result, "authorized");
- printf("DB: Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n",
+ DEBUGP(DDB, "Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n",
subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension,
subscr->lac, subscr->authorized);
dbi_result_free(result);
@@ -398,7 +635,8 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
return subscr;
}
-int db_sync_subscriber(struct gsm_subscriber* subscriber) {
+int db_sync_subscriber(struct gsm_subscriber *subscriber)
+{
dbi_result result;
char tmsi[14];
char *q_tmsi;
@@ -410,6 +648,7 @@ int db_sync_subscriber(struct gsm_subscriber* subscriber) {
&q_tmsi);
} else
q_tmsi = strdup("NULL");
+
result = dbi_conn_queryf(conn,
"UPDATE Subscriber "
"SET updated = datetime('now'), "
@@ -424,14 +663,17 @@ int db_sync_subscriber(struct gsm_subscriber* subscriber) {
subscriber->authorized,
q_tmsi,
subscriber->lac,
- subscriber->imsi
- );
+ subscriber->imsi);
+
free(q_tmsi);
- if (result==NULL) {
- printf("DB: Failed to update Subscriber (by IMSI).\n");
+
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR, "Failed to update Subscriber (by IMSI).\n");
return 1;
}
+
dbi_result_free(result);
+
return 0;
}
@@ -442,15 +684,15 @@ int db_sync_equipment(struct gsm_equipment *equip)
u_int8_t classmark1;
memcpy(&classmark1, &equip->classmark1, sizeof(classmark1));
- printf("DB: Sync Equipment IMEI=%s, classmark1=%02x",
+ DEBUGP(DDB, "Sync Equipment IMEI=%s, classmark1=%02x",
equip->imei, classmark1);
if (equip->classmark2_len)
- printf(", classmark2=%s",
+ DEBUGPC(DDB, ", classmark2=%s",
hexdump(equip->classmark2, equip->classmark2_len));
if (equip->classmark3_len)
- printf(", classmark3=%s",
+ DEBUGPC(DDB, ", classmark3=%s",
hexdump(equip->classmark3, equip->classmark3_len));
- printf("\n");
+ DEBUGPC(DDB, "\n");
dbi_conn_quote_binary_copy(conn, equip->classmark2,
equip->classmark2_len, &cm2);
@@ -470,7 +712,7 @@ int db_sync_equipment(struct gsm_equipment *equip)
free(cm3);
if (!result) {
- printf("DB: Failed to update Equipment\n");
+ LOGP(DDB, LOGL_ERROR, "Failed to update Equipment\n");
return -EIO;
}
@@ -478,10 +720,12 @@ int db_sync_equipment(struct gsm_equipment *equip)
return 0;
}
-int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) {
- dbi_result result=NULL;
+int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber)
+{
+ dbi_result result = NULL;
char tmsi[14];
char* tmsi_quoted;
+
for (;;) {
subscriber->tmsi = rand();
if (subscriber->tmsi == GSM_RESERVED_TMSI)
@@ -492,20 +736,23 @@ int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) {
result = dbi_conn_queryf(conn,
"SELECT * FROM Subscriber "
"WHERE tmsi = %s ",
- tmsi_quoted
- );
+ tmsi_quoted);
+
free(tmsi_quoted);
- if (result==NULL) {
- printf("DB: Failed to query Subscriber while allocating new TMSI.\n");
+
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR, "Failed to query Subscriber "
+ "while allocating new TMSI.\n");
return 1;
}
- if (dbi_result_get_numrows(result)){
+ if (dbi_result_get_numrows(result)) {
dbi_result_free(result);
continue;
}
if (!dbi_result_next_row(result)) {
dbi_result_free(result);
- printf("DB: Allocated TMSI %u for IMSI %s.\n", subscriber->tmsi, subscriber->imsi);
+ DEBUGP(DDB, "Allocated TMSI %u for IMSI %s.\n",
+ subscriber->tmsi, subscriber->imsi);
return db_sync_subscriber(subscriber);
}
dbi_result_free(result);
@@ -513,9 +760,11 @@ int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) {
return 0;
}
-int db_subscriber_alloc_exten(struct gsm_subscriber* subscriber) {
- dbi_result result=NULL;
+int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber)
+{
+ dbi_result result = NULL;
u_int32_t try;
+
for (;;) {
try = (rand()%(GSM_MAX_EXTEN-GSM_MIN_EXTEN+1)+GSM_MIN_EXTEN);
result = dbi_conn_queryf(conn,
@@ -523,8 +772,9 @@ int db_subscriber_alloc_exten(struct gsm_subscriber* subscriber) {
"WHERE extension = %i",
try
);
- if (result==NULL) {
- printf("DB: Failed to query Subscriber while allocating new extension.\n");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR, "Failed to query Subscriber "
+ "while allocating new extension.\n");
return 1;
}
if (dbi_result_get_numrows(result)){
@@ -538,7 +788,7 @@ int db_subscriber_alloc_exten(struct gsm_subscriber* subscriber) {
dbi_result_free(result);
}
sprintf(subscriber->extension, "%i", try);
- printf("DB: Allocated extension %i for IMSI %s.\n", try, subscriber->imsi);
+ DEBUGP(DDB, "Allocated extension %i for IMSI %s.\n", try, subscriber->imsi);
return db_sync_subscriber(subscriber);
}
/*
@@ -547,7 +797,7 @@ int db_subscriber_alloc_exten(struct gsm_subscriber* subscriber) {
* an error.
*/
-int db_subscriber_alloc_token(struct gsm_subscriber* subscriber, u_int32_t* token)
+int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, u_int32_t *token)
{
dbi_result result;
u_int32_t try;
@@ -561,7 +811,8 @@ int db_subscriber_alloc_token(struct gsm_subscriber* subscriber, u_int32_t* toke
"WHERE subscriber_id = %llu OR token = \"%08X\" ",
subscriber->id, try);
if (!result) {
- printf("DB: Failed to query AuthToken while allocating new token.\n");
+ LOGP(DDB, LOGL_ERROR, "Failed to query AuthToken "
+ "while allocating new token.\n");
return 1;
}
if (dbi_result_get_numrows(result)) {
@@ -581,17 +832,19 @@ int db_subscriber_alloc_token(struct gsm_subscriber* subscriber, u_int32_t* toke
"(%llu, datetime('now'), \"%08X\") ",
subscriber->id, try);
if (!result) {
- printf("DB: Failed to create token %08X for IMSI %s.\n", try, subscriber->imsi);
+ LOGP(DDB, LOGL_ERROR, "Failed to create token %08X for "
+ "IMSI %s.\n", try, subscriber->imsi);
return 1;
}
dbi_result_free(result);
*token = try;
- printf("DB: Allocated token %08X for IMSI %s.\n", try, subscriber->imsi);
+ DEBUGP(DDB, "Allocated token %08X for IMSI %s.\n", try, subscriber->imsi);
return 0;
}
-int db_subscriber_assoc_imei(struct gsm_subscriber* subscriber, char imei[GSM_IMEI_LENGTH]) {
+int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM_IMEI_LENGTH])
+{
unsigned long long equipment_id, watch_id;
dbi_result result;
@@ -603,32 +856,32 @@ int db_subscriber_assoc_imei(struct gsm_subscriber* subscriber, char imei[GSM_IM
"(imei, created, updated) "
"VALUES "
"(%s, datetime('now'), datetime('now')) ",
- imei
- );
- if (result==NULL) {
- printf("DB: Failed to create Equipment by IMEI.\n");
+ imei);
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR, "Failed to create Equipment by IMEI.\n");
return 1;
}
+
equipment_id = 0;
if (dbi_result_get_numrows_affected(result)) {
equipment_id = dbi_conn_sequence_last(conn, NULL);
}
dbi_result_free(result);
- if (equipment_id) {
- printf("DB: New Equipment: ID %llu, IMEI %s\n", equipment_id, imei);
- }
+
+ if (equipment_id)
+ DEBUGP(DDB, "New Equipment: ID %llu, IMEI %s\n", equipment_id, imei);
else {
result = dbi_conn_queryf(conn,
"SELECT id FROM Equipment "
"WHERE imei = %s ",
imei
);
- if (result==NULL) {
- printf("DB: Failed to query Equipment by IMEI.\n");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR, "Failed to query Equipment by IMEI.\n");
return 1;
}
if (!dbi_result_next_row(result)) {
- printf("DB: Failed to find the Equipment.\n");
+ LOGP(DDB, LOGL_ERROR, "Failed to find the Equipment.\n");
dbi_result_free(result);
return 1;
}
@@ -641,33 +894,33 @@ int db_subscriber_assoc_imei(struct gsm_subscriber* subscriber, char imei[GSM_IM
"(subscriber_id, equipment_id, created, updated) "
"VALUES "
"(%llu, %llu, datetime('now'), datetime('now')) ",
- subscriber->id, equipment_id
- );
- if (result==NULL) {
- printf("DB: Failed to create EquipmentWatch.\n");
+ subscriber->id, equipment_id);
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR, "Failed to create EquipmentWatch.\n");
return 1;
}
+
watch_id = 0;
- if (dbi_result_get_numrows_affected(result)) {
+ if (dbi_result_get_numrows_affected(result))
watch_id = dbi_conn_sequence_last(conn, NULL);
- }
+
dbi_result_free(result);
- if (watch_id) {
- printf("DB: New EquipmentWatch: ID %llu, IMSI %s, IMEI %s\n", equipment_id, subscriber->imsi, imei);
- }
+ if (watch_id)
+ DEBUGP(DDB, "New EquipmentWatch: ID %llu, IMSI %s, IMEI %s\n",
+ equipment_id, subscriber->imsi, imei);
else {
result = dbi_conn_queryf(conn,
"UPDATE EquipmentWatch "
"SET updated = datetime('now') "
"WHERE subscriber_id = %llu AND equipment_id = %llu ",
- subscriber->id, equipment_id
- );
- if (result==NULL) {
- printf("DB: Failed to update EquipmentWatch.\n");
+ subscriber->id, equipment_id);
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR, "Failed to update EquipmentWatch.\n");
return 1;
}
dbi_result_free(result);
- printf("DB: Updated EquipmentWatch: ID %llu, IMSI %s, IMEI %s\n", equipment_id, subscriber->imsi, imei);
+ DEBUGP(DDB, "Updated EquipmentWatch: ID %llu, IMSI %s, IMEI %s\n",
+ equipment_id, subscriber->imsi, imei);
}
return 0;
@@ -788,6 +1041,33 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id)
return sms;
}
+struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, int min_subscr_id)
+{
+ dbi_result result;
+ struct gsm_sms *sms;
+
+ result = dbi_conn_queryf(conn,
+ "SELECT * FROM SMS,Subscriber "
+ "WHERE sms.receiver_id >= %llu AND sms.sent is NULL "
+ "AND sms.receiver_id = subscriber.id "
+ "AND subscriber.lac > 0 "
+ "ORDER BY sms.receiver_id, id LIMIT 1",
+ min_subscr_id);
+ if (!result)
+ return NULL;
+
+ if (!dbi_result_next_row(result)) {
+ dbi_result_free(result);
+ return NULL;
+ }
+
+ sms = sms_from_result(net, result);
+
+ dbi_result_free(result);
+
+ return sms;
+}
+
/* retrieve the next unsent SMS for a given subscriber */
struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr)
{
@@ -826,7 +1106,7 @@ int db_sms_mark_sent(struct gsm_sms *sms)
"SET sent = datetime('now') "
"WHERE id = %llu", sms->id);
if (!result) {
- printf("DB: Failed to mark SMS %llu as sent.\n", sms->id);
+ LOGP(DDB, LOGL_ERROR, "Failed to mark SMS %llu as sent.\n", sms->id);
return 1;
}
@@ -844,7 +1124,8 @@ int db_sms_inc_deliver_attempts(struct gsm_sms *sms)
"SET deliver_attempts = deliver_attempts + 1 "
"WHERE id = %llu", sms->id);
if (!result) {
- printf("DB: Failed to inc deliver attempts for SMS %llu.\n", sms->id);
+ LOGP(DDB, LOGL_ERROR, "Failed to inc deliver attempts for "
+ "SMS %llu.\n", sms->id);
return 1;
}
@@ -875,3 +1156,24 @@ int db_apdu_blob_store(struct gsm_subscriber *subscr,
dbi_result_free(result);
return 0;
}
+
+int db_store_counter(struct counter *ctr)
+{
+ dbi_result result;
+ char *q_name;
+
+ dbi_conn_quote_string_copy(conn, ctr->name, &q_name);
+
+ result = dbi_conn_queryf(conn,
+ "INSERT INTO Counters "
+ "(timestamp,name,value) VALUES "
+ "(datetime('now'),%s,%lu)", q_name, ctr->value);
+
+ free(q_name);
+
+ if (!result)
+ return -EIO;
+
+ dbi_result_free(result);
+ return 0;
+}
diff --git a/openbsc/src/debug.c b/openbsc/src/debug.c
index 049dc322a..bd06daec7 100644
--- a/openbsc/src/debug.c
+++ b/openbsc/src/debug.c
@@ -25,23 +25,84 @@
#include <string.h>
#include <strings.h>
#include <time.h>
+#include <errno.h>
#include <openbsc/debug.h>
+#include <openbsc/talloc.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
-unsigned int debug_mask = 0xffffffff & ~(DMI|DMIB|DMEAS);
+/* default categories */
+static struct debug_category default_categories[Debug_LastEntry] = {
+ [DRLL] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DCC] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DNM] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DRR] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DRSL] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DMM] = { .enabled = 1, .loglevel = LOGL_INFO },
+ [DMNCC] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DSMS] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DPAG] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DMEAS] = { .enabled = 0, .loglevel = LOGL_NOTICE },
+ [DMI] = { .enabled = 0, .loglevel = LOGL_NOTICE },
+ [DMIB] = { .enabled = 0, .loglevel = LOGL_NOTICE },
+ [DMUX] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DINP] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DSCCP] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DMSC] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DMGCP] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DHO] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DDB] = { .enabled = 1, .loglevel = LOGL_NOTICE },
+ [DREF] = { .enabled = 0, .loglevel = LOGL_NOTICE },
+};
+
+const char *get_value_string(const struct value_string *vs, u_int32_t val)
+{
+ int i;
+
+ for (i = 0;; i++) {
+ if (vs[i].value == 0 && vs[i].str == NULL)
+ break;
+ if (vs[i].value == val)
+ return vs[i].str;
+ }
+ return "unknown";
+}
+
+int get_string_value(const struct value_string *vs, const char *str)
+{
+ int i;
+
+ for (i = 0;; i++) {
+ if (vs[i].value == 0 && vs[i].str == NULL)
+ break;
+ if (!strcasecmp(vs[i].str, str))
+ return vs[i].value;
+ }
+ return -EINVAL;
+}
struct debug_info {
const char *name;
const char *color;
const char *description;
int number;
+ int position;
};
+struct debug_context {
+ struct gsm_lchan *lchan;
+ struct gsm_subscriber *subscr;
+ struct gsm_bts *bts;
+};
+
+static struct debug_context debug_context;
+static void *tall_dbg_ctx = NULL;
+static LLIST_HEAD(target_list);
+
#define DEBUG_CATEGORY(NUMBER, NAME, COLOR, DESCRIPTION) \
{ .name = NAME, .color = COLOR, .description = DESCRIPTION, .number = NUMBER },
-#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
-
static const struct debug_info debug_info[] = {
DEBUG_CATEGORY(DRLL, "DRLL", "\033[1;31m", "")
DEBUG_CATEGORY(DCC, "DCC", "\033[1;32m", "")
@@ -62,52 +123,82 @@ static const struct debug_info debug_info[] = {
DEBUG_CATEGORY(DMSC, "DMSC", "", "")
DEBUG_CATEGORY(DMGCP, "DMGCP", "", "")
DEBUG_CATEGORY(DHO, "DHO", "", "")
+ DEBUG_CATEGORY(DDB, "DDB", "", "")
+ DEBUG_CATEGORY(DDB, "DREF", "", "")
};
-static int use_color = 1;
+static const struct value_string loglevel_strs[] = {
+ { 0, "EVERYTHING" },
+ { 1, "DEBUG" },
+ { 3, "INFO" },
+ { 5, "NOTICE" },
+ { 7, "ERROR" },
+ { 8, "FATAL" },
+ { 0, NULL },
+};
-void debug_use_color(int color)
+int debug_parse_level(const char *lvl)
{
- use_color = color;
+ return get_string_value(loglevel_strs, lvl);
}
-static int print_timestamp = 0;
-
-void debug_timestamp(int enable)
+int debug_parse_category(const char *category)
{
- print_timestamp = enable;
-}
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(debug_info); ++i) {
+ if (!strcasecmp(debug_info[i].name+1, category))
+ return debug_info[i].number;
+ }
+ return -EINVAL;
+}
/*
* Parse the category mask.
- * category1:category2:category3
+ * The format can be this: category1:category2:category3
+ * or category1,2:category2,3:...
*/
-void debug_parse_category_mask(const char *_mask)
+void debug_parse_category_mask(struct debug_target* target, const char *_mask)
{
- unsigned int new_mask = 0;
int i = 0;
char *mask = strdup(_mask);
char *category_token = NULL;
+ /* Disable everything to enable it afterwards */
+ for (i = 0; i < ARRAY_SIZE(target->categories); ++i)
+ target->categories[i].enabled = 0;
+
category_token = strtok(mask, ":");
do {
for (i = 0; i < ARRAY_SIZE(debug_info); ++i) {
- if (strcasecmp(debug_info[i].name, category_token) == 0)
- new_mask |= debug_info[i].number;
+ char* colon = strstr(category_token, ",");
+ int length = strlen(category_token);
+
+ if (colon)
+ length = colon - category_token;
+
+ if (strncasecmp(debug_info[i].name, category_token, length) == 0) {
+ int number = debug_info[i].number;
+ int level = 0;
+
+ if (colon)
+ level = atoi(colon+1);
+
+ target->categories[number].enabled = 1;
+ target->categories[number].loglevel = level;
+ }
}
} while ((category_token = strtok(NULL, ":")));
-
free(mask);
- debug_mask = new_mask;
}
-const char* color(int subsys)
+static const char* color(int subsys)
{
int i = 0;
- for (i = 0; use_color && i < ARRAY_SIZE(debug_info); ++i) {
+ for (i = 0; i < ARRAY_SIZE(debug_info); ++i) {
if (debug_info[i].number == subsys)
return debug_info[i].color;
}
@@ -115,35 +206,111 @@ const char* color(int subsys)
return "";
}
-void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...)
+static void _output(struct debug_target *target, unsigned int subsys, char *file, int line,
+ int cont, const char *format, va_list ap)
{
- va_list ap;
- FILE *outfd = stderr;
-
- if (!(debug_mask & subsys))
- return;
+ char col[30];
+ char sub[30];
+ char tim[30];
+ char buf[4096];
+ char final[4096];
- va_start(ap, format);
+ /* prepare the data */
+ col[0] = '\0';
+ sub[0] = '\0';
+ tim[0] = '\0';
+ buf[0] = '\0';
- fprintf(outfd, "%s", color(subsys));
+ /* are we using color */
+ if (target->use_color) {
+ snprintf(col, sizeof(col), "%s", color(subsys));
+ col[sizeof(col)-1] = '\0';
+ }
+ vsnprintf(buf, sizeof(buf), format, ap);
+ buf[sizeof(buf)-1] = '\0';
if (!cont) {
- if (print_timestamp) {
+ if (target->print_timestamp) {
char *timestr;
time_t tm;
tm = time(NULL);
timestr = ctime(&tm);
timestr[strlen(timestr)-1] = '\0';
- fprintf(outfd, "%s ", timestr);
+ snprintf(tim, sizeof(tim), "%s ", timestr);
+ tim[sizeof(tim)-1] = '\0';
+ }
+ snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line);
+ sub[sizeof(sub)-1] = '\0';
+ }
+
+ snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf);
+ final[sizeof(final)-1] = '\0';
+ target->output(target, final);
+}
+
+
+static void _debugp(unsigned int subsys, int level, char *file, int line,
+ int cont, const char *format, va_list ap)
+{
+ struct debug_target *tar;
+
+ llist_for_each_entry(tar, &target_list, entry) {
+ struct debug_category *category;
+ int output = 0;
+
+ category = &tar->categories[subsys];
+ /* subsystem is not supposed to be debugged */
+ if (!category->enabled)
+ continue;
+
+ /* Check the global log level */
+ if (tar->loglevel != 0 && level < tar->loglevel)
+ continue;
+
+ /* Check the category log level */
+ if (category->loglevel != 0 && level < category->loglevel)
+ continue;
+
+ /*
+ * Apply filters here... if that becomes messy we will need to put
+ * filters in a list and each filter will say stop, continue, output
+ */
+ if ((tar->filter_map & DEBUG_FILTER_ALL) != 0) {
+ output = 1;
+ } else if ((tar->filter_map & DEBUG_FILTER_IMSI) != 0
+ && debug_context.subscr && strcmp(debug_context.subscr->imsi, tar->imsi_filter) == 0) {
+ output = 1;
+ }
+
+ if (output) {
+ /* FIXME: copying the va_list is an ugly workaround against a bug
+ * hidden somewhere in _output. If we do not copy here, the first
+ * call to _output() will corrupt the va_list contents, and any
+ * further _output() calls with the same va_list will segfault */
+ va_list bp;
+ va_copy(bp, ap);
+ _output(tar, subsys, file, line, cont, format, bp);
+ va_end(bp);
}
- fprintf(outfd, "<%4.4x> %s:%d ", subsys, file, line);
}
- vfprintf(outfd, format, ap);
- fprintf(outfd, "\033[0;m");
+}
+
+void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ _debugp(subsys, LOGL_DEBUG, file, line, cont, format, ap);
va_end(ap);
+}
+
+void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...)
+{
+ va_list ap;
- fflush(outfd);
+ va_start(ap, format);
+ _debugp(subsys, level, file, line, cont, format, ap);
+ va_end(ap);
}
static char hexd_buff[4096];
@@ -165,3 +332,122 @@ char *hexdump(const unsigned char *buf, int len)
return hexd_buff;
}
+
+
+void debug_add_target(struct debug_target *target)
+{
+ llist_add_tail(&target->entry, &target_list);
+}
+
+void debug_del_target(struct debug_target *target)
+{
+ llist_del(&target->entry);
+}
+
+void debug_reset_context(void)
+{
+ memset(&debug_context, 0, sizeof(debug_context));
+}
+
+/* currently we are not reffing these */
+void debug_set_context(int ctx, void *value)
+{
+ switch (ctx) {
+ case BSC_CTX_LCHAN:
+ debug_context.lchan = (struct gsm_lchan *) value;
+ break;
+ case BSC_CTX_SUBSCR:
+ debug_context.subscr = (struct gsm_subscriber *) value;
+ break;
+ case BSC_CTX_BTS:
+ debug_context.bts = (struct gsm_bts *) value;
+ break;
+ case BSC_CTX_SCCP:
+ break;
+ default:
+ break;
+ }
+}
+
+void debug_set_imsi_filter(struct debug_target *target, const char *imsi)
+{
+ if (imsi) {
+ target->filter_map |= DEBUG_FILTER_IMSI;
+ target->imsi_filter = talloc_strdup(target, imsi);
+ } else if (target->imsi_filter) {
+ target->filter_map &= ~DEBUG_FILTER_IMSI;
+ talloc_free(target->imsi_filter);
+ target->imsi_filter = NULL;
+ }
+}
+
+void debug_set_all_filter(struct debug_target *target, int all)
+{
+ if (all)
+ target->filter_map |= DEBUG_FILTER_ALL;
+ else
+ target->filter_map &= ~DEBUG_FILTER_ALL;
+}
+
+void debug_set_use_color(struct debug_target *target, int use_color)
+{
+ target->use_color = use_color;
+}
+
+void debug_set_print_timestamp(struct debug_target *target, int print_timestamp)
+{
+ target->print_timestamp = print_timestamp;
+}
+
+void debug_set_log_level(struct debug_target *target, int log_level)
+{
+ target->loglevel = log_level;
+}
+
+void debug_set_category_filter(struct debug_target *target, int category, int enable, int level)
+{
+ if (category >= Debug_LastEntry)
+ return;
+ target->categories[category].enabled = !!enable;
+ target->categories[category].loglevel = level;
+}
+
+static void _stderr_output(struct debug_target *target, const char *log)
+{
+ fprintf(target->tgt_stdout.out, "%s", log);
+ fflush(target->tgt_stdout.out);
+}
+
+struct debug_target *debug_target_create(void)
+{
+ struct debug_target *target;
+
+ target = talloc_zero(tall_dbg_ctx, struct debug_target);
+ if (!target)
+ return NULL;
+
+ INIT_LLIST_HEAD(&target->entry);
+ memcpy(target->categories, default_categories, sizeof(default_categories));
+ target->use_color = 1;
+ target->print_timestamp = 0;
+ target->loglevel = 0;
+ return target;
+}
+
+struct debug_target *debug_target_create_stderr(void)
+{
+ struct debug_target *target;
+
+ target = debug_target_create();
+ if (!target)
+ return NULL;
+
+ target->tgt_stdout.out = stderr;
+ target->output = _stderr_output;
+ return target;
+}
+
+void debug_init(void)
+{
+ tall_dbg_ctx = talloc_named_const(NULL, 1, "debug");
+}
diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c
index 083d8f8de..c894fe40f 100644
--- a/openbsc/src/e1_input.c
+++ b/openbsc/src/e1_input.c
@@ -234,10 +234,16 @@ int abis_rsl_sendmsg(struct msgb *msg)
msg->l2h = msg->data;
- if (!msg->trx || !msg->trx->rsl_link) {
- LOGP(DRSL, LOGL_ERROR, "rsl_sendmsg: msg->trx == NULL\n");
+ if (!msg->trx) {
+ LOGP(DRSL, LOGL_ERROR, "rsl_sendmsg: msg->trx == NULL: %s\n",
+ hexdump(msg->data, msg->len));
talloc_free(msg);
return -EINVAL;
+ } else if (!msg->trx->rsl_link) {
+ LOGP(DRSL, LOGL_ERROR, "rsl_sendmsg: msg->trx->rsl_link == NULL: %s\n",
+ hexdump(msg->data, msg->len));
+ talloc_free(msg);
+ return -EIO;
}
sign_link = msg->trx->rsl_link;
@@ -435,6 +441,8 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
"tei %d, sapi %d\n", tei, sapi);
return -EINVAL;
}
+
+ debug_set_context(BSC_CTX_BTS, link->trx->bts);
switch (link->type) {
case E1INP_SIGN_OML:
msg->trx = link->trx;
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 1fcca349f..61eba2c5a 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -50,6 +50,7 @@
#include <openbsc/talloc.h>
#include <openbsc/transaction.h>
#include <openbsc/ussd.h>
+#include <openbsc/silent_call.h>
#define GSM_MAX_FACILITY 128
#define GSM_MAX_SSVERSION 128
@@ -165,74 +166,6 @@ static const char *rr_cause_name(u_int8_t cause)
return strbuf;
}
-int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
-{
- struct gsm48_hdr *gh = msgb_l3(msg);
- unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
- u_int8_t *data = gh->data;
- struct gsm_bts *bts = msg->lchan->ts->trx->bts;
- struct bitvec *nbv = &bts->si_common.neigh_list;
-
- if (gh->msg_type != GSM48_MT_RR_MEAS_REP)
- return -EINVAL;
-
- if (data[0] & 0x80)
- rep->flags |= MEAS_REP_F_BA1;
- if (data[0] & 0x40)
- rep->flags |= MEAS_REP_F_UL_DTX;
- if ((data[1] & 0x40) == 0x00)
- rep->flags |= MEAS_REP_F_DL_VALID;
-
- rep->dl.full.rx_lev = data[0] & 0x3f;
- rep->dl.sub.rx_lev = data[1] & 0x3f;
- rep->dl.full.rx_qual = (data[3] >> 4) & 0x7;
- rep->dl.sub.rx_qual = (data[3] >> 1) & 0x7;
-
- rep->num_cell = ((data[3] >> 6) & 0x3) | ((data[2] & 0x01) << 2);
- if (rep->num_cell < 1 || rep->num_cell > 6)
- return 0;
-
- /* an encoding nightmare in perfection */
-
- rep->cell[0].rxlev = data[3] & 0x3f;
- rep->cell[0].arfcn = bitvec_get_nth_set_bit(nbv, data[4] >> 2);
- rep->cell[0].bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5);
- if (rep->num_cell < 2)
- return 0;
-
- rep->cell[1].rxlev = ((data[5] & 0x1f) << 1) | (data[6] >> 7);
- rep->cell[1].arfcn = bitvec_get_nth_set_bit(nbv, (data[6] >> 2) & 0x1f);
- rep->cell[1].bsic = ((data[6] & 0x03) << 4) | (data[7] >> 4);
- if (rep->num_cell < 3)
- return 0;
-
- rep->cell[2].rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6);
- rep->cell[2].arfcn = bitvec_get_nth_set_bit(nbv, (data[8] >> 1) & 0x1f);
- rep->cell[2].bsic = ((data[8] & 0x01) << 6) | (data[9] >> 3);
- if (rep->num_cell < 4)
- return 0;
-
- rep->cell[3].rxlev = ((data[9] & 0x07) << 3) | (data[10] >> 5);
- rep->cell[3].arfcn = bitvec_get_nth_set_bit(nbv, data[10] & 0x1f);
- rep->cell[3].bsic = data[11] >> 2;
- if (rep->num_cell < 5)
- return 0;
-
- rep->cell[4].rxlev = ((data[11] & 0x03) << 4) | (data[12] >> 4);
- rep->cell[4].arfcn = bitvec_get_nth_set_bit(nbv,
- ((data[12] & 0xf) << 1) | (data[13] >> 7));
- rep->cell[4].bsic = (data[13] >> 1) & 0x3f;
- if (rep->num_cell < 6)
- return 0;
-
- rep->cell[5].rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3);
- rep->cell[5].arfcn = bitvec_get_nth_set_bit(nbv,
- ((data[14] & 0x07) << 2) | (data[15] >> 6));
- rep->cell[5].bsic = data[15] & 0x3f;
-
- return 0;
-}
-
int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
static int gsm48_tx_simple(struct gsm_lchan *lchan,
u_int8_t pdisc, u_int8_t msg_type);
@@ -886,6 +819,7 @@ static int encode_more(struct msgb *msg)
/* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */
int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
{
+ struct gsm_bts *bts = lchan->ts->trx->bts;
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
@@ -896,7 +830,12 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
gh->data[0] = cause;
- DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
+ LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT "
+ "LAC=%u BTS=%u\n", lchan->subscr ?
+ subscr_name(lchan->subscr) : "unknown",
+ lchan->ts->trx->bts->location_area_code, lchan->ts->trx->bts->nr);
+
+ counter_inc(bts->network->stats.loc_upd_resp.reject);
return gsm48_sendmsg(msg, NULL);
}
@@ -925,6 +864,8 @@ int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
+ counter_inc(bts->network->stats.loc_upd_resp.accept);
+
return gsm48_sendmsg(msg, NULL);
}
@@ -1043,6 +984,18 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
dispatch_signal(SS_SUBSCR, S_SUBSCR_IDENTITY, &lu->mi_len);
+ switch (lu->type) {
+ case GSM48_LUPD_NORMAL:
+ counter_inc(bts->network->stats.loc_upd_type.normal);
+ break;
+ case GSM48_LUPD_IMSI_ATT:
+ counter_inc(bts->network->stats.loc_upd_type.attach);
+ break;
+ case GSM48_LUPD_PERIODIC:
+ counter_inc(bts->network->stats.loc_upd_type.periodic);
+ break;
+ }
+
/*
* Pseudo Spoof detection: Just drop a second/concurrent
* location updating request.
@@ -1222,20 +1175,19 @@ int gsm48_tx_mm_info(struct gsm_lchan *lchan)
}
/* Section 9.2.2 */
-int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand)
+int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand, int key_seq)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
struct gsm48_auth_req *ar = (struct gsm48_auth_req *) msgb_put(msg, sizeof(*ar));
- DEBUGP(DMM, "-> AUTH REQ\n");
+ DEBUGP(DMM, "-> AUTH REQ (rand = %s)\n", hexdump(rand, 16));
msg->lchan = lchan;
gh->proto_discr = GSM48_PDISC_MM;
gh->msg_type = GSM48_MT_MM_AUTH_REQ;
- /* Key Sequence: FIXME fixed to 0 */
- ar->key_seq = 0;
+ ar->key_seq = key_seq;
/* 16 bytes RAND parameters */
if (rand)
@@ -1369,6 +1321,8 @@ static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
DEBUGP(DMM, "IMSI DETACH INDICATION: mi_type=0x%02x MI(%s): ",
mi_type, mi_string);
+ counter_inc(bts->network->stats.loc_upd_type.detach);
+
switch (mi_type) {
case GSM_MI_TYPE_TMSI:
subscr = subscr_get_by_tmsi(bts->network,
@@ -1390,8 +1344,7 @@ static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
if (subscr) {
subscr_update(subscr, msg->trx->bts,
GSM_SUBSCRIBER_UPDATE_DETACHED);
- DEBUGP(DMM, "Subscriber: %s\n",
- subscr->name ? subscr->name : subscr->imsi);
+ DEBUGP(DMM, "Subscriber: %s\n", subscr_name(subscr));
subscr->equipment.classmark1 = idi->classmark1;
db_sync_equipment(&subscr->equipment);
@@ -1441,7 +1394,7 @@ static int gsm0408_rcv_mm(struct msgb *msg)
case GSM48_MT_MM_TMSI_REALL_COMPL:
DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n",
msg->lchan->subscr ?
- msg->lchan->subscr->imsi :
+ subscr_name(msg->lchan->subscr) :
"unknown subscriber");
break;
case GSM48_MT_MM_IMSI_DETACH_IND:
@@ -1454,7 +1407,7 @@ static int gsm0408_rcv_mm(struct msgb *msg)
DEBUGP(DMM, "AUTHENTICATION RESPONSE: Not implemented\n");
break;
default:
- DEBUGP(DMM, "Unknown GSM 04.08 MM msg type 0x%02x\n",
+ LOGP(DMM, LOGL_NOTICE, "Unknown GSM 04.08 MM msg type 0x%02x\n",
gh->msg_type);
break;
}
@@ -1657,8 +1610,8 @@ static int gsm0408_rcv_rr(struct msgb *msg)
rc = gsm48_rx_rr_ho_fail(msg);
break;
default:
- DEBUGP(DMM, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
- gh->msg_type);
+ LOGP(DRR, LOGL_NOTICE, "Unimplemented "
+ "GSM 04.08 RR msg type 0x%02x\n", gh->msg_type);
break;
}
@@ -2197,6 +2150,10 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
new_cc_state(trans, GSM_CSTATE_INITIATED);
+ LOGP(DCC, LOGL_INFO, "Subscriber %s (%s) sends SETUP to %s\n",
+ subscr_name(trans->subscr), trans->subscr->extension,
+ setup.called.number);
+
/* indicate setup to MNCC */
mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
@@ -3543,6 +3500,9 @@ int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t pdisc = gh->proto_discr & 0x0f;
int rc = 0;
+
+ if (silent_call_reroute(msg))
+ return silent_call_rx(msg);
switch (pdisc) {
case GSM48_PDISC_CC:
@@ -3559,15 +3519,15 @@ int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
break;
case GSM48_PDISC_MM_GPRS:
case GSM48_PDISC_SM_GPRS:
- DEBUGP(DMM, "Unimplemented GSM 04.08 discriminator 0x%02x\n",
- pdisc);
+ LOGP(DRLL, LOGL_NOTICE, "Unimplemented "
+ "GSM 04.08 discriminator 0x%02x\n", pdisc);
break;
case GSM48_PDISC_NC_SS:
rc = handle_rcv_ussd(msg);
break;
default:
- DEBUGP(DMM, "Unknown GSM 04.08 discriminator 0x%02x\n",
- pdisc);
+ LOGP(DRLL, LOGL_NOTICE, "Unknown "
+ "GSM 04.08 discriminator 0x%02x\n", pdisc);
break;
}
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index e96a1ca09..d5785f971 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -340,7 +340,7 @@ enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci)
if ((ra & chr->mask) == chr->val)
return ctype_by_chreq[chr->type];
}
- fprintf(stderr, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
+ LOGP(DRR, LOGL_ERROR, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
return GSM_LCHAN_SDCCH;
}
@@ -363,7 +363,7 @@ enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, in
if ((ra & chr->mask) == chr->val)
return reason_by_chreq[chr->type];
}
- fprintf(stderr, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
+ LOGP(DRR, LOGL_ERROR, "Unknown CHANNEL REQUEST REASON 0x%02x\n", ra);
return GSM_CHREQ_REASON_OTHER;
}
@@ -475,7 +475,7 @@ int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr)
if (!msg->lchan->subscr) {
msg->lchan->subscr = subscr;
} else if (msg->lchan->subscr != subscr) {
- DEBUGP(DRR, "<- Channel already owned by someone else?\n");
+ LOGP(DRR, LOGL_ERROR, "<- Channel already owned by someone else?\n");
subscr_put(subscr);
return -EINVAL;
} else {
@@ -488,7 +488,9 @@ int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr)
sig_data.bts = msg->lchan->ts->trx->bts;
sig_data.lchan = msg->lchan;
- dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
+ bts->network->stats.paging.completed++;
+
+ dispatch_signal(SS_PAGING, S_PAGING_SUCCEEDED, &sig_data);
/* Stop paging on the bts we received the paging response */
paging_request_stop(msg->trx->bts, subscr, msg->lchan);
@@ -592,7 +594,8 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command)
/* in case of multi rate we need to attach a config */
if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
if (lchan->mr_conf.ver == 0) {
- DEBUGP(DRR, "BUG: Using multirate codec without multirate config.\n");
+ LOGP(DRR, LOGL_ERROR, "BUG: Using multirate codec "
+ "without multirate config.\n");
} else {
u_int8_t *data = msgb_put(msg, 4);
data[0] = GSM48_IE_MUL_RATE_CFG;
@@ -632,7 +635,8 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
/* in case of multi rate we need to attach a config */
if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
if (lchan->mr_conf.ver == 0) {
- DEBUGP(DRR, "BUG: Using multirate codec without multirate config.\n");
+ LOGP(DRR, LOGL_ERROR, "BUG: Using multirate codec "
+ "without multirate config.\n");
} else {
u_int8_t *data = msgb_put(msg, 4);
data[0] = GSM48_IE_MUL_RATE_CFG;
@@ -665,7 +669,7 @@ int gsm48_rx_rr_modif_ack(struct msgb *msg)
DEBUGP(DRR, "CHANNEL MODE MODIFY ACK\n");
if (mod->mode != msg->lchan->tch_mode) {
- DEBUGP(DRR, "CHANNEL MODE change failed. Wanted: %d Got: %d\n",
+ LOGP(DRR, LOGL_ERROR, "CHANNEL MODE change failed. Wanted: %d Got: %d\n",
msg->lchan->tch_mode, mod->mode);
return -1;
}
@@ -698,3 +702,82 @@ int gsm48_rx_rr_modif_ack(struct msgb *msg)
rsl_ipacc_crcx(msg->lchan);
return rc;
}
+
+int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
+ u_int8_t *data = gh->data;
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
+ struct bitvec *nbv = &bts->si_common.neigh_list;
+ struct gsm_meas_rep_cell *mrc;
+
+ if (gh->msg_type != GSM48_MT_RR_MEAS_REP)
+ return -EINVAL;
+
+ if (data[0] & 0x80)
+ rep->flags |= MEAS_REP_F_BA1;
+ if (data[0] & 0x40)
+ rep->flags |= MEAS_REP_F_UL_DTX;
+ if ((data[1] & 0x40) == 0x00)
+ rep->flags |= MEAS_REP_F_DL_VALID;
+
+ rep->dl.full.rx_lev = data[0] & 0x3f;
+ rep->dl.sub.rx_lev = data[1] & 0x3f;
+ rep->dl.full.rx_qual = (data[3] >> 4) & 0x7;
+ rep->dl.sub.rx_qual = (data[3] >> 1) & 0x7;
+
+ rep->num_cell = ((data[3] >> 6) & 0x3) | ((data[2] & 0x01) << 2);
+ if (rep->num_cell < 1 || rep->num_cell > 6)
+ return 0;
+
+ /* an encoding nightmare in perfection */
+ mrc = &rep->cell[0];
+ mrc->rxlev = data[3] & 0x3f;
+ mrc->neigh_idx = data[4] >> 3;
+ mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
+ mrc->bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5);
+ if (rep->num_cell < 2)
+ return 0;
+
+ mrc = &rep->cell[1];
+ mrc->rxlev = ((data[5] & 0x1f) << 1) | (data[6] >> 7);
+ mrc->neigh_idx = (data[6] >> 2) & 0x1f;
+ mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
+ mrc->bsic = ((data[6] & 0x03) << 4) | (data[7] >> 4);
+ if (rep->num_cell < 3)
+ return 0;
+
+ mrc = &rep->cell[2];
+ mrc->rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6);
+ mrc->neigh_idx = (data[8] >> 1) & 0x1f;
+ mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
+ mrc->bsic = ((data[8] & 0x01) << 5) | (data[9] >> 3);
+ if (rep->num_cell < 4)
+ return 0;
+
+ mrc = &rep->cell[3];
+ mrc->rxlev = ((data[9] & 0x07) << 3) | (data[10] >> 5);
+ mrc->neigh_idx = data[10] & 0x1f;
+ mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
+ mrc->bsic = data[11] >> 2;
+ if (rep->num_cell < 5)
+ return 0;
+
+ mrc = &rep->cell[4];
+ mrc->rxlev = ((data[11] & 0x03) << 4) | (data[12] >> 4);
+ mrc->neigh_idx = ((data[12] & 0xf) << 1) | (data[13] >> 7);
+ mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
+ mrc->bsic = (data[13] >> 1) & 0x3f;
+ if (rep->num_cell < 6)
+ return 0;
+
+ mrc = &rep->cell[5];
+ mrc->rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3);
+ mrc->neigh_idx = ((data[14] & 0x07) << 2) | (data[15] >> 6);
+ mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1);
+ mrc->bsic = data[15] & 0x3f;
+
+ return 0;
+}
+
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 31526e979..7f570b8e5 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -215,7 +215,8 @@ static u_int8_t unbcdify(u_int8_t value)
u_int8_t ret;
if ((value & 0x0F) > 9 || (value >> 4) > 9)
- DEBUGP(DSMS, "unbcdify got too big nibble: 0x%02X\n", value);
+ LOGP(DSMS, LOGL_ERROR,
+ "unbcdify got too big nibble: 0x%02X\n", value);
ret = (value&0x0F)*10;
ret += value>>4;
@@ -311,7 +312,8 @@ static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
unsigned long minutes;
vp = *(sms_vp);
if (vp == 0) {
- DEBUGP(DSMS, "reserved relative_integer validity period\n");
+ LOGP(DSMS, LOGL_ERROR,
+ "reserved relative_integer validity period\n");
return gsm340_vp_default();
}
minutes = vp/60;
@@ -356,7 +358,8 @@ static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
default:
/* The GSM spec says that the SC should reject any
unsupported and/or undefined values. FIXME */
- DEBUGP(DSMS, "Reserved enhanced validity period format\n");
+ LOGP(DSMS, LOGL_ERROR,
+ "Reserved enhanced validity period format\n");
return gsm340_vp_default();
}
case GSM340_TP_VPF_NONE:
@@ -373,7 +376,8 @@ enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
if ((cgbits & 0xc) == 0) {
if (cgbits & 2)
- DEBUGP(DSMS, "Compressed SMS not supported yet\n");
+ LOGP(DSMS, LOGL_NOTICE,
+ "Compressed SMS not supported yet\n");
switch ((dcs >> 2)&0x03) {
case 0:
@@ -403,7 +407,7 @@ enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
{
if (db_sms_store(gsms) != 0) {
- DEBUGP(DSMS, "Failed to store SMS in Database\n");
+ LOGP(DSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
}
/* dispatch a signal to tell higher level about it */
@@ -497,7 +501,8 @@ static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
memcpy(smsp, sms->user_data, sms->user_data_len);
break;
default:
- DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
+ LOGP(DSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
+ sms->data_coding_scheme);
break;
}
@@ -517,6 +522,8 @@ static int gsm340_rx_tpdu(struct msgb *msg)
u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
int rc = 0;
+ counter_inc(bts->network->stats.sms.submitted);
+
gsms = sms_alloc();
if (!gsms)
return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
@@ -535,7 +542,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
/* length in bytes of the destination address */
da_len_bytes = 2 + *smsp/2 + *smsp%2;
if (da_len_bytes > 12) {
- DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
+ LOGP(DSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
goto out;
}
@@ -560,15 +567,16 @@ static int gsm340_rx_tpdu(struct msgb *msg)
case GSM340_TP_VPF_ENHANCED:
sms_vp = smsp;
/* the additional functionality indicator... */
- if (*smsp & (1<<7)) smsp++;
+ if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
+ smsp++;
smsp += 7;
break;
case GSM340_TP_VPF_NONE:
sms_vp = 0;
break;
default:
- DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
- sms_vpf);
+ LOGP(DSMS, LOGL_NOTICE,
+ "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
}
gsms->user_data_len = *smsp++;
@@ -586,16 +594,17 @@ static int gsm340_rx_tpdu(struct msgb *msg)
}
}
- DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
- "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
- "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
- gsms->protocol_id, gsms->data_coding_scheme,
- gsms->dest_addr, gsms->user_data_len,
+ gsms->sender = subscr_get(msg->lchan->subscr);
+
+ LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
+ "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
+ "UserDataLength: 0x%02x, UserData: \"%s\"\n",
+ subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref,
+ gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
+ gsms->user_data_len,
sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
hexdump(gsms->user_data, gsms->user_data_len));
- gsms->sender = subscr_get(msg->lchan->subscr);
-
gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
dispatch_signal(SS_SMS, 0, gsms);
@@ -604,6 +613,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
if (!gsms->receiver) {
rc = 1; /* cause 1: unknown subscriber */
+ counter_inc(bts->network->stats.sms.no_receiver);
goto out;
}
@@ -614,11 +624,11 @@ static int gsm340_rx_tpdu(struct msgb *msg)
break;
case GSM340_SMS_COMMAND_MS2SC:
case GSM340_SMS_DELIVER_REP_MS2SC:
- DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
+ LOGP(DSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
rc = GSM411_RP_CAUSE_IE_NOTEXIST;
break;
default:
- DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
+ LOGP(DSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
rc = GSM411_RP_CAUSE_IE_NOTEXIST;
break;
}
@@ -648,7 +658,7 @@ static int gsm411_send_rp_error(struct gsm_trans *trans,
msgb_tv_put(msg, 1, cause);
- DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
+ LOGP(DSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
get_value_string(rp_cause_strs, cause));
return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
@@ -664,10 +674,11 @@ static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
int rc = 0;
if (src_len && src)
- DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
+ LOGP(DSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
if (!dst_len || !dst || !tpdu_len || !tpdu) {
- DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
+ LOGP(DSMS, LOGL_ERROR,
+ "RP-DATA (MO) without DST or TPDU ?!?\n");
gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_INV_MAND_INF);
return -EIO;
@@ -722,13 +733,13 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
* transmitted */
if (!trans->sms.is_mt) {
- DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
+ LOGP(DSMS, LOGL_ERROR, "RX RP-ACK on a MO transfer ?\n");
return gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_MSG_INCOMP_STATE);
}
if (!sms) {
- DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
+ LOGP(DSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
return gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_PROTOCOL_ERR);
}
@@ -741,14 +752,16 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
sms_free(sms);
trans->sms.sms = NULL;
- /* free the transaction here */
- trans_free(trans);
-
/* check for more messages for this subscriber */
sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
if (sms)
gsm411_send_sms_lchan(msg->lchan, sms);
- else
+
+ /* free the transaction here */
+ trans_free(trans);
+
+ /* release channel if done */
+ if (!sms)
rsl_release_request(msg->lchan, trans->sms.link_id);
return 0;
@@ -757,6 +770,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
struct gsm411_rp_hdr *rph)
{
+ struct gsm_network *net = trans->lchan->ts->trx->bts->network;
struct gsm_sms *sms = trans->sms.sms;
u_int8_t cause_len = rph->data[0];
u_int8_t cause = rph->data[1];
@@ -765,11 +779,12 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
* successfully receive the SMS. We need to investigate
* the cause and take action depending on it */
- DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d:%d (%s)\n", cause_len, cause,
- get_value_string(rp_cause_strs, cause));
+ LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
+ subscr_name(msg->lchan->subscr), cause_len, cause,
+ get_value_string(rp_cause_strs, cause));
if (!trans->sms.is_mt) {
- DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
+ LOGP(DSMS, LOGL_ERROR, "RX RP-ERR on a MO transfer ?\n");
#if 0
return gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_MSG_INCOMP_STATE);
@@ -777,7 +792,8 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
}
if (!sms) {
- DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
+ LOGP(DSMS, LOGL_ERROR,
+ "RX RP-ERR, but no sms in transaction?!?\n");
return -EINVAL;
#if 0
return gsm411_send_rp_error(trans, rph->msg_ref,
@@ -790,7 +806,9 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
* to store this in our database and wati for a SMMA message */
/* FIXME */
dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
- }
+ counter_inc(net->stats.sms.rp_err_mem);
+ } else
+ counter_inc(net->stats.sms.rp_err_other);
sms_free(sms);
trans->sms.sms = NULL;
@@ -852,7 +870,7 @@ static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
rc = gsm411_rx_rp_error(msg, trans, rp_data);
break;
default:
- DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
+ LOGP(DSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
break;
@@ -883,7 +901,7 @@ static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
struct msgb *msg = gsm411_msgb_alloc();
u_int8_t *causep;
- DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
+ LOGP(DSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
get_value_string(cp_cause_strs, cause));
causep = msgb_put(msg, 1);
@@ -930,6 +948,33 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
switch(msg_type) {
case GSM411_MT_CP_DATA:
DEBUGPC(DSMS, "RX SMS CP-DATA\n");
+
+ /* 5.4: For MO, if a CP-DATA is received for a new
+ * transaction, equals reception of an implicit
+ * last CP-ACK for previous transaction */
+ if (trans->sms.cp_state == GSM411_CPS_IDLE) {
+ int i;
+ struct gsm_trans *ptrans;
+
+ /* Scan through all remote initiated transactions */
+ for (i=8; i<15; i++) {
+ if (i == transaction_id)
+ continue;
+
+ ptrans = trans_find_by_id(lchan->subscr,
+ GSM48_PDISC_SMS, i);
+ if (!ptrans)
+ continue;
+
+ DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i);
+
+ /* Finish it for good */
+ bsc_del_timer(&ptrans->sms.cp_timer);
+ ptrans->sms.cp_state = GSM411_CPS_IDLE;
+ trans_free(ptrans);
+ }
+ }
+
/* 5.2.3.1.3: MO state exists when SMC has received
* CP-DATA, including sending of the assoc. CP-ACK */
/* 5.2.3.2.4: MT state exists when SMC has received
@@ -1002,10 +1047,14 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
struct gsm_trans *trans;
u_int8_t *data, *rp_ud_len;
u_int8_t msg_ref = 42;
- u_int8_t transaction_id;
+ int transaction_id;
int rc;
- transaction_id = 4; /* FIXME: we always use 4 for now */
+ transaction_id = trans_assign_trans_id(lchan->subscr, GSM48_PDISC_SMS, 0);
+ if (transaction_id == -1) {
+ LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
+ return -EBUSY;
+ }
msg->lchan = lchan;
@@ -1015,7 +1064,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
transaction_id, new_callref++);
if (!trans) {
- DEBUGP(DSMS, "No memory for trans\n");
+ LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
/* FIXME: send some error message */
return -ENOMEM;
}
@@ -1063,6 +1112,8 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
DEBUGP(DSMS, "TX: SMS DELIVER\n");
+ counter_inc(lchan->ts->trx->bts->network->stats.sms.delivered);
+
return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
/* FIXME: enter 'wait for RP-ACK' state, start TR1N */
}
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index 1e2480dd9..f0165552a 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -30,22 +30,10 @@
#include <openbsc/gsm_data.h>
#include <openbsc/talloc.h>
#include <openbsc/abis_nm.h>
+#include <openbsc/statistics.h>
void *tall_bsc_ctx;
-const char *get_value_string(const struct value_string *vs, u_int32_t val)
-{
- int i;
-
- for (i = 0;; i++) {
- if (vs[i].value == 0 && vs[i].str == NULL)
- break;
- if (vs[i].value == val)
- return vs[i].str;
- }
- return "unknown";
-}
-
void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
u_int8_t e1_ts, u_int8_t e1_ts_ss)
{
@@ -94,7 +82,7 @@ static const char *lchan_names[] = {
[GSM_LCHAN_UNKNOWN] = "UNKNOWN",
};
-const char *gsm_lchan_name(enum gsm_chan_t c)
+const char *gsm_lchant_name(enum gsm_chan_t c)
{
if (c >= ARRAY_SIZE(lchan_names))
return "INVALID";
@@ -102,6 +90,20 @@ const char *gsm_lchan_name(enum gsm_chan_t c)
return lchan_names[c];
}
+static const struct value_string lchan_s_names[] = {
+ { LCHAN_S_NONE, "NONE" },
+ { LCHAN_S_ACT_REQ, "ACTIVATION REQUESTED" },
+ { LCHAN_S_ACTIVE, "ACTIVE" },
+ { LCHAN_S_INACTIVE, "INACTIVE" },
+ { LCHAN_S_REL_REQ, "RELEASE REQUESTED" },
+ { 0, NULL },
+};
+
+const char *gsm_lchans_name(enum gsm_lchan_state s)
+{
+ return get_value_string(lchan_s_names, s);
+}
+
static const char *chreq_names[] = {
[GSM_CHREQ_REASON_EMERG] = "EMERGENCY",
[GSM_CHREQ_REASON_PAG] = "PAGING",
@@ -128,6 +130,7 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
trx->bts = bts;
trx->nr = bts->num_trx++;
+ trx->nm_state.administrative = NM_STATE_UNLOCKED;
for (k = 0; k < TRX_NR_TS; k++) {
struct gsm_bts_trx_ts *ts = &trx->ts[k];
@@ -147,6 +150,9 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
}
}
+ if (trx->nr != 0)
+ trx->nominal_power = bts->c0->nominal_power;
+
llist_add_tail(&trx->list, &bts->trx_list);
return trx;
@@ -177,6 +183,10 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
bts->si_common.cell_alloc.data_len =
sizeof(bts->si_common.data.cell_alloc);
+ bts->si_common.rach_control.re = 1; /* no re-establishment */
+ bts->si_common.rach_control.tx_integer = 9; /* 12 slots spread - 217/115 slots delay */
+ bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
+ bts->si_common.rach_control.t2 = 4; /* no emergency calls */
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
bts->gprs.nsvc[i].bts = bts;
@@ -224,6 +234,32 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
INIT_LLIST_HEAD(&net->upqueue);
INIT_LLIST_HEAD(&net->bts_list);
+ net->stats.chreq.total = counter_alloc("net.chreq.total");
+ net->stats.chreq.no_channel = counter_alloc("net.chreq.no_channel");
+ net->stats.handover.attempted = counter_alloc("net.handover.attempted");
+ net->stats.handover.no_channel = counter_alloc("net.handover.no_channel");
+ net->stats.handover.timeout = counter_alloc("net.handover.timeout");
+ net->stats.handover.completed = counter_alloc("net.handover.completed");
+ net->stats.handover.failed = counter_alloc("net.handover.failed");
+ net->stats.loc_upd_type.attach = counter_alloc("net.loc_upd_type.attach");
+ net->stats.loc_upd_type.normal = counter_alloc("net.loc_upd_type.normal");
+ net->stats.loc_upd_type.periodic = counter_alloc("net.loc_upd_type.periodic");
+ net->stats.loc_upd_type.detach = counter_alloc("net.imsi_detach.count");
+ net->stats.loc_upd_resp.reject = counter_alloc("net.loc_upd_resp.reject");
+ net->stats.loc_upd_resp.accept = counter_alloc("net.loc_upd_resp.accept");
+ net->stats.paging.attempted = counter_alloc("net.paging.attempted");
+ net->stats.paging.detached = counter_alloc("net.paging.detached");
+ net->stats.paging.completed = counter_alloc("net.paging.completed");
+ net->stats.paging.expired = counter_alloc("net.paging.expired");
+ net->stats.sms.submitted = counter_alloc("net.sms.submitted");
+ net->stats.sms.no_receiver = counter_alloc("net.sms.no_receiver");
+ net->stats.sms.delivered = counter_alloc("net.sms.delivered");
+ net->stats.sms.rp_err_mem = counter_alloc("net.sms.rp_err_mem");
+ net->stats.sms.rp_err_other = counter_alloc("net.sms.rp_err_other");
+ net->stats.call.dialled = counter_alloc("net.call.dialled");
+ net->stats.call.alerted = counter_alloc("net.call.alerted");
+ net->stats.call.connected = counter_alloc("net.call.connected");
+
net->mncc_recv = mncc_recv;
return net;
@@ -280,6 +316,15 @@ struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num)
static char ts2str[255];
+char *gsm_trx_name(struct gsm_bts_trx *trx)
+{
+ snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
+ trx->bts->nr, trx->nr);
+
+ return ts2str;
+}
+
+
char *gsm_ts_name(struct gsm_bts_trx_ts *ts)
{
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
@@ -288,6 +333,16 @@ char *gsm_ts_name(struct gsm_bts_trx_ts *ts)
return ts2str;
}
+char *gsm_lchan_name(struct gsm_lchan *lchan)
+{
+ struct gsm_bts_trx_ts *ts = lchan->ts;
+
+ snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
+ ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
+
+ return ts2str;
+}
+
static const char *bts_types[] = {
[GSM_BTS_TYPE_UNKNOWN] = "unknown",
[GSM_BTS_TYPE_BS11] = "bs11",
@@ -482,3 +537,18 @@ struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
return meas_rep;
}
+
+void gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type)
+{
+ bts->type = type;
+
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NANOBTS:
+ /* Set the default OML Stream ID to 0xff */
+ bts->oml_tei = 0xff;
+ bts->c0->nominal_power = 23;
+ break;
+ case GSM_BTS_TYPE_BS11:
+ break;
+ }
+}
diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c
index c81b522d4..692508753 100644
--- a/openbsc/src/gsm_subscriber.c
+++ b/openbsc/src/gsm_subscriber.c
@@ -34,6 +34,14 @@
extern struct llist_head *subscr_bsc_active_subscriber(void);
+char *subscr_name(struct gsm_subscriber *subscr)
+{
+ if (strlen(subscr->name))
+ return subscr->name;
+
+ return subscr->imsi;
+}
+
struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net,
u_int32_t tmsi)
{
@@ -100,12 +108,15 @@ int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason)
s->net = bts->network;
/* Indicate "attached to LAC" */
s->lac = bts->location_area_code;
+ LOGP(DMM, LOGL_INFO, "Subscriber %s ATTACHED LAC=%u\n",
+ subscr_name(s), s->lac);
dispatch_signal(SS_SUBSCR, S_SUBSCR_ATTACHED, s);
break;
case GSM_SUBSCRIBER_UPDATE_DETACHED:
/* Only detach if we are currently in this area */
if (bts->location_area_code == s->lac)
s->lac = GSM_LAC_RESERVED_DETACHED;
+ LOGP(DMM, LOGL_INFO, "Subscriber %s DETACHED\n", subscr_name(s));
dispatch_signal(SS_SUBSCR, S_SUBSCR_DETACHED, s);
break;
default:
diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c
index 48374eae5..0570061a2 100644
--- a/openbsc/src/gsm_subscriber_base.c
+++ b/openbsc/src/gsm_subscriber_base.c
@@ -137,7 +137,7 @@ static void subscr_free(struct gsm_subscriber *subscr)
struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr)
{
subscr->use_count++;
- DEBUGP(DCC, "subscr %s usage increases usage to: %d\n",
+ DEBUGP(DREF, "subscr %s usage increases usage to: %d\n",
subscr->extension, subscr->use_count);
return subscr;
}
@@ -145,7 +145,7 @@ struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr)
struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr)
{
subscr->use_count--;
- DEBUGP(DCC, "subscr %s usage decreased usage to: %d\n",
+ DEBUGP(DREF, "subscr %s usage decreased usage to: %d\n",
subscr->extension, subscr->use_count);
if (subscr->use_count <= 0)
subscr_free(subscr);
diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c
index 94d3d0d1e..1bf048fed 100644
--- a/openbsc/src/handover_logic.c
+++ b/openbsc/src/handover_logic.c
@@ -97,9 +97,12 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts)
DEBUGP(DHO, "(old_lchan on BTS %u, new BTS %u)\n",
old_lchan->ts->trx->bts->nr, bts->nr);
+ counter_inc(bts->network->stats.handover.attempted);
+
new_lchan = lchan_alloc(bts, old_lchan->type);
if (!new_lchan) {
LOGP(DHO, LOGL_NOTICE, "No free channel\n");
+ counter_inc(bts->network->stats.handover.no_channel);
return -ENOSPC;
}
@@ -141,8 +144,10 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts)
static void ho_T3103_cb(void *_ho)
{
struct bsc_handover *ho = _ho;
+ struct gsm_network *net = ho->new_lchan->ts->trx->bts->network;
DEBUGP(DHO, "HO T3103 expired\n");
+ counter_inc(net->stats.handover.timeout);
lchan_free(ho->new_lchan);
llist_del(&ho->list);
@@ -203,6 +208,7 @@ static int ho_chan_activ_nack(struct gsm_lchan *new_lchan)
/* GSM 04.08 HANDOVER COMPLETE has been received on new channel */
static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
{
+ struct gsm_network *net = new_lchan->ts->trx->bts->network;
struct bsc_handover *ho;
ho = bsc_ho_by_new_lchan(new_lchan);
@@ -211,6 +217,13 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
return -ENODEV;
}
+ LOGP(DHO, LOGL_INFO, "Subscriber %s HO from BTS %u->%u on ARFCN "
+ "%u->%u\n", subscr_name(ho->old_lchan->subscr),
+ ho->old_lchan->ts->trx->bts->nr, new_lchan->ts->trx->bts->nr,
+ ho->old_lchan->ts->trx->arfcn, new_lchan->ts->trx->arfcn);
+
+ counter_inc(net->stats.handover.completed);
+
bsc_del_timer(&ho->T3103);
/* update lchan pointer of transaction */
@@ -230,6 +243,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
/* GSM 04.08 HANDOVER FAIL has been received */
static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
{
+ struct gsm_network *net = old_lchan->ts->trx->bts->network;
struct bsc_handover *ho;
ho = bsc_ho_by_old_lchan(old_lchan);
@@ -238,6 +252,8 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
return -ENODEV;
}
+ counter_inc(net->stats.handover.failed);
+
bsc_del_timer(&ho->T3103);
llist_del(&ho->list);
put_lchan(ho->new_lchan);
@@ -269,8 +285,8 @@ static int ho_ipac_crcx_ack(struct gsm_lchan *new_lchan)
ho = bsc_ho_by_new_lchan(new_lchan);
if (!ho) {
- LOGP(DHO, LOGL_ERROR, "unable to find HO record\n");
- return -ENODEV;
+ /* it is perfectly normal, we have CRCX even in non-HO cases */
+ return 0;
}
if (ipacc_rtp_direct) {
diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c
index 9d972d8fa..dbf00a857 100644
--- a/openbsc/src/input/ipaccess.c
+++ b/openbsc/src/input/ipaccess.c
@@ -214,7 +214,7 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
&site_id, &bts_id, &trx_id);
bts = find_bts_by_unitid(e1h->gsmnet, site_id, bts_id);
if (!bts) {
- DEBUGP(DINP, "Unable to find BTS configuration for "
+ LOGP(DINP, LOGL_ERROR, "Unable to find BTS configuration for "
" %u/%u/%u, disconnecting\n", site_id, bts_id,
trx_id);
return -EIO;
@@ -271,7 +271,8 @@ struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
hh = (struct ipaccess_head *) msg->data;
ret = recv(bfd->fd, msg->data, 3, 0);
if (ret < 0) {
- fprintf(stderr, "recv error %s\n", strerror(errno));
+ if (errno != EAGAIN)
+ LOGP(DINP, LOGL_ERROR, "recv error %d %s\n", ret, strerror(errno));
msgb_free(msg);
*error = ret;
return NULL;
@@ -288,7 +289,7 @@ struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
len = ntohs(hh->len);
ret = recv(bfd->fd, msg->l2h, len, 0);
if (ret < len) {
- fprintf(stderr, "short read!\n");
+ LOGP(DINP, LOGL_ERROR, "short read!\n");
msgb_free(msg);
*error = -EIO;
return NULL;
@@ -311,7 +312,13 @@ static int handle_ts1_read(struct bsc_fd *bfd)
msg = ipaccess_read_msg(bfd, &error);
if (!msg) {
if (error == 0) {
- fprintf(stderr, "BTS disappeared, dead socket\n");
+ link = e1inp_lookup_sign_link(e1i_ts, IPAC_PROTO_OML, 0);
+ if (link) {
+ link->trx->bts->ip_access.flags = 0;
+ LOGP(DINP, LOGL_NOTICE, "BTS %u disappeared, dead socket\n",
+ link->trx->bts->nr);
+ } else
+ LOGP(DINP, LOGL_NOTICE, "unknown BTS disappeared, dead socket\n");
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_RSL);
e1inp_event(e1i_ts, EVT_E1_TEI_DN, 0, IPAC_PROTO_OML);
bsc_unregister_fd(bfd);
@@ -341,7 +348,8 @@ static int handle_ts1_read(struct bsc_fd *bfd)
link = e1inp_lookup_sign_link(e1i_ts, hh->proto, 0);
if (!link) {
- printf("no matching signalling link for hh->proto=0x%02x\n", hh->proto);
+ LOGP(DINP, LOGL_ERROR, "no matching signalling link for "
+ "hh->proto=0x%02x\n", hh->proto);
msgb_free(msg);
return -EIO;
}
@@ -363,7 +371,7 @@ static int handle_ts1_read(struct bsc_fd *bfd)
ret = abis_nm_rcvmsg(msg);
break;
default:
- DEBUGP(DMI, "Unknown IP.access protocol proto=0x%02x\n", hh->proto);
+ LOGP(DINP, LOGL_NOTICE, "Unknown IP.access protocol proto=0x%02x\n", hh->proto);
msgb_free(msg);
break;
}
@@ -463,11 +471,15 @@ static int ipaccess_fd_cb(struct bsc_fd *bfd, unsigned int what)
if (what & BSC_FD_WRITE)
rc = handle_ts1_write(bfd);
} else
- fprintf(stderr, "unknown E1 TS type %u\n", e1i_ts->type);
+ LOGP(DINP, LOGL_ERROR, "unknown E1 TS type %u\n", e1i_ts->type);
return rc;
}
+/* declare this as a weak symbol to ensure code will still build
+ * even if it does not provide this function */
+extern int gprs_ns_rcvmsg(struct msgb *msg) __attribute__((weak));
+
static struct msgb *read_gprs_msg(struct bsc_fd *bfd, int *error)
{
struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "Abis/IP/GPRS");
@@ -504,7 +516,12 @@ static int handle_gprs_read(struct bsc_fd *bfd)
if (!msg)
return error;
- return gprs_ns_rcvmsg(msg);
+ if (gprs_ns_rcvmsg)
+ return gprs_ns_rcvmsg(msg);
+ else {
+ msgb_free(msg);
+ return 0;
+ }
}
static int handle_gprs_write(struct bsc_fd *bfd)
@@ -565,7 +582,8 @@ static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
perror("accept");
return ret;
}
- DEBUGP(DINP, "accept()ed new OML link from %s\n", inet_ntoa(sa.sin_addr));
+ LOGP(DINP, LOGL_NOTICE, "accept()ed new OML link from %s\n",
+ inet_ntoa(sa.sin_addr));
line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
if (!line) {
@@ -587,7 +605,7 @@ static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
bfd->when = BSC_FD_READ;
ret = bsc_register_fd(bfd);
if (ret < 0) {
- fprintf(stderr, "could not register FD\n");
+ LOGP(DINP, LOGL_ERROR, "could not register FD\n");
close(bfd->fd);
talloc_free(line);
return ret;
@@ -623,13 +641,13 @@ static int rsl_listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
perror("accept");
return bfd->fd;
}
- DEBUGP(DINP, "accept()ed new RSL link from %s\n", inet_ntoa(sa.sin_addr));
+ LOGP(DINP, LOGL_NOTICE, "accept()ed new RSL link from %s\n", inet_ntoa(sa.sin_addr));
bfd->priv_nr = 2;
bfd->cb = ipaccess_fd_cb;
bfd->when = BSC_FD_READ;
ret = bsc_register_fd(bfd);
if (ret < 0) {
- fprintf(stderr, "could not register FD\n");
+ LOGP(DINP, LOGL_ERROR, "could not register FD\n");
close(bfd->fd);
talloc_free(bfd);
return ret;
@@ -664,7 +682,7 @@ static int make_sock(struct bsc_fd *bfd, int proto, u_int16_t port,
ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
- fprintf(stderr, "could not bind l2 socket %s\n",
+ LOGP(DINP, LOGL_ERROR, "could not bind l2 socket %s\n",
strerror(errno));
return -EIO;
}
@@ -702,7 +720,7 @@ int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa)
ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa));
if (ret < 0) {
- fprintf(stderr, "could not connect socket\n");
+ LOGP(DINP, LOGL_ERROR, "could not connect socket\n");
close(bfd->fd);
return ret;
}
@@ -736,13 +754,14 @@ int ipaccess_setup(struct gsm_network *gsmnet)
e1h->gsmnet = gsmnet;
/* Listen for OML connections */
- ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, 3002, listen_fd_cb);
+ ret = make_sock(&e1h->listen_fd, IPPROTO_TCP, IPA_TCP_PORT_OML,
+ listen_fd_cb);
if (ret < 0)
return ret;
/* Listen for RSL connections */
- ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP, 3003,
- rsl_listen_fd_cb);
+ ret = make_sock(&e1h->rsl_listen_fd, IPPROTO_TCP,
+ IPA_TCP_PORT_RSL, rsl_listen_fd_cb);
if (ret < 0)
return ret;
diff --git a/openbsc/src/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c
index 9f46d585a..ceac7bdf4 100644
--- a/openbsc/src/ipaccess-config.c
+++ b/openbsc/src/ipaccess/ipaccess-config.c
@@ -1,6 +1,8 @@
/* ip.access nanoBTS configuration tool */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009 by Holger Hans Peter Freyther
+ * (C) 2009 by On Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +26,8 @@
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -39,8 +43,9 @@
#include <openbsc/abis_nm.h>
#include <openbsc/signal.h>
#include <openbsc/debug.h>
+#include <openbsc/talloc.h>
-struct gsm_network *bsc_gsmnet;
+static struct gsm_network *gsmnet;
static int net_listen_testnr;
static int restart;
@@ -48,6 +53,21 @@ static char *prim_oml_ip;
static char *unit_id;
static u_int16_t nv_flags;
static u_int16_t nv_mask;
+static char *software = NULL;
+static int sw_load_state = 0;
+static int oml_state = 0;
+
+struct sw_load {
+ u_int8_t file_id[255];
+ u_int8_t file_id_len;
+
+ u_int8_t file_version[255];
+ u_int8_t file_version_len;
+};
+
+static void *tall_ctx_config = NULL;
+static struct sw_load *sw_load1 = NULL;
+static struct sw_load *sw_load2 = NULL;
/*
static u_int8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 };
@@ -68,6 +88,28 @@ static int ipacc_msg_nack(u_int8_t mt)
return 0;
}
+static int ipacc_msg_ack(u_int8_t mt, struct gsm_bts *bts)
+{
+ if (sw_load_state == 1) {
+ fprintf(stderr, "The new software is activaed.\n");
+
+ if (restart) {
+ abis_nm_ipaccess_restart(bts);
+ } else {
+ exit(0);
+ }
+ } else if (oml_state == 1) {
+ fprintf(stderr, "Set the primary OML IP.\n");
+ if (restart) {
+ abis_nm_ipaccess_restart(bts);
+ } else {
+ exit(0);
+ }
+ }
+
+ return 0;
+}
+
struct ipacc_ferr_elem {
int16_t freq_err;
u_int8_t freq_qual;
@@ -149,14 +191,25 @@ static int test_rep(void *_msg)
static int nm_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
- u_int8_t *msg_type;
+ struct ipacc_ack_signal_data *ipacc_data;
switch (signal) {
case S_NM_IPACC_NACK:
- msg_type = signal_data;
- return ipacc_msg_nack(*msg_type);
+ ipacc_data = signal_data;
+ return ipacc_msg_nack(ipacc_data->msg_type);
+ case S_NM_IPACC_ACK:
+ ipacc_data = signal_data;
+ return ipacc_msg_ack(ipacc_data->msg_type, ipacc_data->bts);
case S_NM_TEST_REP:
return test_rep(signal_data);
+ case S_NM_IPACC_RESTART_ACK:
+ printf("The BTS has acked the restart. Exiting.\n");
+ exit(0);
+ break;
+ case S_NM_IPACC_RESTART_NACK:
+ printf("The BTS has nacked the restart. Exiting.\n");
+ exit(0);
+ break;
default:
break;
}
@@ -164,6 +217,84 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal,
return 0;
}
+/* callback function passed to the ABIS OML code */
+static int percent;
+static int percent_old;
+static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg,
+ void *data, void *param)
+{
+ struct msgb *msg;
+ struct gsm_bts *bts;
+
+ if (hook != GSM_HOOK_NM_SWLOAD)
+ return 0;
+
+ bts = (struct gsm_bts *) data;
+
+ switch (event) {
+ case NM_MT_LOAD_INIT_ACK:
+ fprintf(stdout, "Software Load Initiate ACK\n");
+ break;
+ case NM_MT_LOAD_INIT_NACK:
+ fprintf(stderr, "ERROR: Software Load Initiate NACK\n");
+ exit(5);
+ break;
+ case NM_MT_LOAD_END_ACK:
+ fprintf(stderr, "LOAD END ACK...");
+ /* now make it the default */
+ sw_load_state = 1;
+
+ msg = msgb_alloc(1024, "sw: nvattr");
+ msg->l2h = msgb_put(msg, 3);
+ msg->l3h = &msg->l2h[3];
+
+ /* activate software */
+ if (sw_load1) {
+ msgb_v_put(msg, NM_ATT_SW_DESCR);
+ msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw_load1->file_id_len, sw_load1->file_id);
+ msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw_load1->file_version_len,
+ sw_load1->file_version);
+ }
+
+ if (sw_load2) {
+ msgb_v_put(msg, NM_ATT_SW_DESCR);
+ msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw_load2->file_id_len, sw_load2->file_id);
+ msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw_load2->file_version_len,
+ sw_load2->file_version);
+ }
+
+ /* fill in the data */
+ msg->l2h[0] = NM_ATT_IPACC_CUR_SW_CFG;
+ msg->l2h[1] = msgb_l3len(msg) >> 8;
+ msg->l2h[2] = msgb_l3len(msg) & 0xff;
+ printf("Foo l2h: %p l3h: %p... length l2: %u l3: %u\n", msg->l2h, msg->l3h, msgb_l2len(msg), msgb_l3len(msg));
+ abis_nm_ipaccess_set_nvattr(bts, msg->l2h, msgb_l2len(msg));
+ msgb_free(msg);
+ break;
+ case NM_MT_LOAD_END_NACK:
+ fprintf(stderr, "ERROR: Software Load End NACK\n");
+ exit(3);
+ break;
+ case NM_MT_ACTIVATE_SW_NACK:
+ fprintf(stderr, "ERROR: Activate Software NACK\n");
+ exit(4);
+ break;
+ case NM_MT_ACTIVATE_SW_ACK:
+ break;
+ case NM_MT_LOAD_SEG_ACK:
+ percent = abis_nm_software_load_status(bts);
+ if (percent > percent_old)
+ printf("Software Download Progress: %d%%\n", percent);
+ percent_old = percent;
+ break;
+ case NM_MT_LOAD_ABORT:
+ fprintf(stderr, "ERROR: Load aborted by the BTS.\n");
+ exit(6);
+ break;
+ }
+ return 0;
+}
+
static void bootstrap_om(struct gsm_bts *bts)
{
int len;
@@ -205,6 +336,7 @@ static void bootstrap_om(struct gsm_bts *bts)
*cur++ = 0;
*cur++ = 0;
printf("setting primary OML link IP to '%s'\n", inet_ntoa(ia));
+ oml_state = 1;
abis_nm_ipaccess_set_nvattr(bts, buf, 3+len);
}
if (nv_mask) {
@@ -222,10 +354,11 @@ static void bootstrap_om(struct gsm_bts *bts)
abis_nm_ipaccess_set_nvattr(bts, buf, 3+len);
}
- if (restart) {
+ if (restart && !prim_oml_ip && !software) {
printf("restarting BTS\n");
abis_nm_ipaccess_restart(bts);
}
+
}
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
@@ -257,17 +390,146 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
{
if (evt == EVT_STATECHG_OPER &&
obj_class == NM_OC_RADIO_CARRIER &&
- new_state->availability == 3 &&
- net_listen_testnr) {
+ new_state->availability == 3) {
struct gsm_bts_trx *trx = obj;
- u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 };
- abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff,
- net_listen_testnr, 1,
- phys_config, sizeof(phys_config));
+
+ if (net_listen_testnr) {
+ u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 };
+ abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff,
+ net_listen_testnr, 1,
+ phys_config, sizeof(phys_config));
+ } else if (software) {
+ int rc;
+ printf("Attempting software upload with '%s'\n", software);
+ rc = abis_nm_software_load(trx->bts, software, 19, 0, swload_cbfn, trx->bts);
+ if (rc < 0) {
+ fprintf(stderr, "Failed to start software load\n");
+ exit(-3);
+ }
+ }
}
return 0;
}
+static struct sw_load *create_swload(struct sdp_header *header)
+{
+ struct sw_load *load;
+
+ load = talloc_zero(tall_ctx_config, struct sw_load);
+
+ strncpy((char *)load->file_id, header->firmware_info.sw_part, 20);
+ load->file_id_len = strlen(header->firmware_info.sw_part) + 1;
+
+ strncpy((char *)load->file_version, header->firmware_info.version, 20);
+ load->file_version_len = strlen(header->firmware_info.version) + 1;
+
+ return load;
+}
+
+static void find_sw_load_params(const char *filename)
+{
+ struct stat stat;
+ struct sdp_header *header;
+ struct llist_head *entry;
+ int fd;
+ void *tall_firm_ctx = 0;
+
+ entry = talloc_zero(tall_firm_ctx, struct llist_head);
+ INIT_LLIST_HEAD(entry);
+
+ fd = open(filename, O_RDONLY);
+ if (!fd) {
+ perror("nada");
+ return;
+ }
+
+ /* verify the file */
+ if (fstat(fd, &stat) == -1) {
+ perror("Can not stat the file");
+ return;
+ }
+
+ ipaccess_analyze_file(fd, stat.st_size, 0, entry);
+ if (close(fd) != 0) {
+ perror("Close failed.\n");
+ return;
+ }
+
+ /* try to find what we are looking for */
+ llist_for_each_entry(header, entry, entry) {
+ if (ntohs(header->firmware_info.more_more_magic) == 0x1000) {
+ sw_load1 = create_swload(header);
+ } else if (ntohs(header->firmware_info.more_more_magic) == 0x2001) {
+ sw_load2 = create_swload(header);
+ }
+ }
+
+ talloc_free(tall_firm_ctx);
+}
+
+static void analyze_firmware(const char *filename)
+{
+ struct stat stat;
+ struct sdp_header *header;
+ struct sdp_header_item *sub_entry;
+ struct llist_head *entry;
+ int fd;
+ void *tall_firm_ctx = 0;
+
+ entry = talloc_zero(tall_firm_ctx, struct llist_head);
+ INIT_LLIST_HEAD(entry);
+
+ printf("Opening possible firmware '%s'\n", filename);
+ fd = open(filename, O_RDONLY);
+ if (!fd) {
+ perror("nada");
+ return;
+ }
+
+ /* verify the file */
+ if (fstat(fd, &stat) == -1) {
+ perror("Can not stat the file");
+ return;
+ }
+
+ ipaccess_analyze_file(fd, stat.st_size, 0, entry);
+ if (close(fd) != 0) {
+ perror("Close failed.\n");
+ return;
+ }
+
+ llist_for_each_entry(header, entry, entry) {
+ printf("Printing header information:\n");
+ printf("more_more_magic: 0x%x\n", ntohs(header->firmware_info.more_more_magic));
+ printf("header_length: %u\n", ntohl(header->firmware_info.header_length));
+ printf("file_length: %u\n", ntohl(header->firmware_info.file_length));
+ printf("sw_part: %.20s\n", header->firmware_info.sw_part);
+ printf("text1: %.64s\n", header->firmware_info.text1);
+ printf("time: %.12s\n", header->firmware_info.time);
+ printf("date: %.14s\n", header->firmware_info.date);
+ printf("text2: %.10s\n", header->firmware_info.text2);
+ printf("version: %.20s\n", header->firmware_info.version);
+ printf("subitems...\n");
+
+ llist_for_each_entry(sub_entry, &header->header_list, entry) {
+ printf("\tsomething1: %u\n", sub_entry->header_entry.something1);
+ printf("\ttext1: %.64s\n", sub_entry->header_entry.text1);
+ printf("\ttime: %.12s\n", sub_entry->header_entry.time);
+ printf("\tdate: %.14s\n", sub_entry->header_entry.date);
+ printf("\ttext2: %.10s\n", sub_entry->header_entry.text2);
+ printf("\tversion: %.20s\n", sub_entry->header_entry.version);
+ printf("\tlength: %u\n", ntohl(sub_entry->header_entry.length));
+ printf("\taddr1: 0x%x\n", ntohl(sub_entry->header_entry.addr1));
+ printf("\taddr2: 0x%x\n", ntohl(sub_entry->header_entry.addr2));
+ printf("\tstart: 0x%x\n", ntohl(sub_entry->header_entry.start));
+ printf("\n\n");
+ }
+ printf("\n\n");
+ }
+
+ talloc_free(tall_firm_ctx);
+}
+
static void print_usage(void)
{
printf("Usage: ipaccess-config\n");
@@ -282,6 +544,8 @@ static void print_help(void)
printf(" -l --listen testnr \tPerform specified test number\n");
printf(" -h --help this text\n");
printf(" -s --stream-id ID\n");
+ printf(" -d --software firmware\n");
+ printf(" -f --firmware firmware Provide firmware information\n");
}
int main(int argc, char **argv)
@@ -289,6 +553,14 @@ int main(int argc, char **argv)
struct gsm_bts *bts;
struct sockaddr_in sin;
int rc, option_index = 0, stream_id = 0xff;
+ struct debug_target *stderr_target;
+
+ debug_init();
+ stderr_target = debug_target_create_stderr();
+ debug_add_target(stderr_target);
+ debug_set_all_filter(stderr_target, 1);
+ debug_set_log_level(stderr_target, 0);
+ debug_parse_category_mask(stderr_target, "DNM,0");
printf("ipaccess-config (C) 2009 by Harald Welte\n");
printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
@@ -304,9 +576,11 @@ int main(int argc, char **argv)
{ "help", 0, 0, 'h' },
{ "listen", 1, 0, 'l' },
{ "stream-id", 1, 0, 's' },
+ { "software", 1, 0, 'd' },
+ { "firmware", 1, 0, 'f' },
};
- c = getopt_long(argc, argv, "u:o:rn:l:hs:", long_options,
+ c = getopt_long(argc, argv, "u:o:rn:l:hs:d:f:", long_options,
&option_index);
if (c == -1)
@@ -336,8 +610,14 @@ int main(int argc, char **argv)
break;
case 's':
stream_id = atoi(optarg);
- printf("foo: %d\n", stream_id);
break;
+ case 'd':
+ software = strdup(optarg);
+ find_sw_load_params(optarg);
+ break;
+ case 'f':
+ analyze_firmware(optarg);
+ exit(0);
case 'h':
print_usage();
print_help();
@@ -350,12 +630,16 @@ int main(int argc, char **argv)
exit(2);
}
- bsc_gsmnet = gsm_network_init(1, 1, NULL);
- if (!bsc_gsmnet)
+ gsmnet = gsm_network_init(1, 1, NULL);
+ if (!gsmnet)
exit(1);
- bts = gsm_bts_alloc(bsc_gsmnet, GSM_BTS_TYPE_NANOBTS, HARDCODED_TSC,
+ bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_NANOBTS, HARDCODED_TSC,
HARDCODED_BSIC);
+ /* ip.access supports up to 4 chained TRX */
+ gsm_bts_trx_alloc(bts);
+ gsm_bts_trx_alloc(bts);
+ gsm_bts_trx_alloc(bts);
bts->oml_tei = stream_id;
register_signal_handler(SS_NM, nm_sig_cb, NULL);
diff --git a/openbsc/src/ipaccess-find.c b/openbsc/src/ipaccess/ipaccess-find.c
index f469b6788..f469b6788 100644
--- a/openbsc/src/ipaccess-find.c
+++ b/openbsc/src/ipaccess/ipaccess-find.c
diff --git a/openbsc/src/ipaccess/ipaccess-firmware.c b/openbsc/src/ipaccess/ipaccess-firmware.c
new file mode 100644
index 000000000..ed4bc9a0c
--- /dev/null
+++ b/openbsc/src/ipaccess/ipaccess-firmware.c
@@ -0,0 +1,123 @@
+/* Routines for parsing an ipacces SDP firmware file */
+
+/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/debug.h>
+#include <openbsc/ipaccess.h>
+#include <openbsc/talloc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define PART_LENGTH 138
+
+static_assert(sizeof(struct sdp_header_entry) == 138, right_entry);
+static_assert(sizeof(struct sdp_firmware) == 160, _right_header_length);
+
+/* more magic, the second "int" in the header */
+static char more_magic[] = { 0x10, 0x02 };
+
+int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned int base_offset, struct llist_head *list)
+{
+ struct sdp_firmware *firmware_header = 0;
+ struct sdp_header *header;
+ char buf[4096];
+ int rc, i;
+
+ rc = read(fd, buf, sizeof(*firmware_header));
+ if (rc < 0) {
+ perror("Can not read header start.");
+ return -1;
+ }
+
+ firmware_header = (struct sdp_firmware *) &buf[0];
+ if (strncmp(firmware_header->magic, " SDP", 4) != 0) {
+ fprintf(stderr, "Wrong magic.\n");
+ return -1;
+ }
+
+ if (memcmp(firmware_header->more_magic, more_magic, 2) != 0) {
+ fprintf(stderr, "Wrong more magic. Got: 0x%x %x %x %x\n",
+ firmware_header->more_magic[0] & 0xff, firmware_header->more_magic[1] & 0xff,
+ firmware_header->more_magic[2] & 0xff, firmware_header->more_magic[3] & 0xff);
+ return -1;
+ }
+
+
+ if (!firmware_header)
+ return -1;
+
+ if (ntohl(firmware_header->file_length) != st_size) {
+ fprintf(stderr, "The filesize and the header do not match.\n");
+ return -1;
+ }
+
+ /* add the firmware */
+ header = talloc_zero(list, struct sdp_header);
+ header->firmware_info = *firmware_header;
+ INIT_LLIST_HEAD(&header->header_list);
+ llist_add(&header->entry, list);
+
+ /* this semantic appears to be only the case for 0x0000 */
+ if (firmware_header->more_more_magic != 0)
+ return -1;
+
+ if (ntohs(firmware_header->part_length) % PART_LENGTH != 0) {
+ fprintf(stderr, "The part length seems to be wrong.\n");
+ return -1;
+ }
+
+ /* look into each firmware now */
+ for (i = 0; i < ntohs(firmware_header->part_length) / PART_LENGTH; ++i) {
+ struct sdp_header_entry entry;
+ struct sdp_header_item *header_entry;
+ unsigned int offset = base_offset + sizeof(struct sdp_firmware);
+ offset += i * 138;
+
+ if (lseek(fd, offset, SEEK_SET) != offset) {
+ fprintf(stderr, "Can not seek to the offset: %u.\n", offset);
+ return -1;
+ }
+
+ rc = read(fd, &entry, sizeof(entry));
+ if (rc != sizeof(entry)) {
+ fprintf(stderr, "Can not read the header entry.\n");
+ return -1;
+ }
+
+ /* now we need to find the SDP file... */
+ offset = ntohl(entry.start) + 4 + base_offset;
+ if (lseek(fd, offset, SEEK_SET) != offset) {
+ perror("can't seek to sdp");
+ return -1;
+ }
+
+ header_entry = talloc_zero(header, struct sdp_header_item);
+ header_entry->header_entry = entry;
+ llist_add(&header_entry->entry, &header->header_list);
+
+ ipaccess_analyze_file(fd, ntohl(entry.length), offset, list);
+ }
+
+ return 0;
+}
+
diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c
new file mode 100644
index 000000000..d018b6ebd
--- /dev/null
+++ b/openbsc/src/ipaccess/ipaccess-proxy.c
@@ -0,0 +1,1127 @@
+/* OpenBSC Abis/IP proxy ip.access nanoBTS */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/select.h>
+#include <openbsc/tlv.h>
+#include <openbsc/msgb.h>
+#include <openbsc/debug.h>
+#include <openbsc/ipaccess.h>
+#include <openbsc/talloc.h>
+
+static struct debug_target *stderr_target;
+
+/* one instance of an ip.access protocol proxy */
+struct ipa_proxy {
+ /* socket where we listen for incoming OML from BTS */
+ struct bsc_fd oml_listen_fd;
+ /* socket where we listen for incoming RSL from BTS */
+ struct bsc_fd rsl_listen_fd;
+ /* list of BTS's (struct ipa_bts_conn */
+ struct llist_head bts_list;
+ /* the BSC reconnect timer */
+ struct timer_list reconn_timer;
+};
+
+/* global pointer to the proxy structure */
+static struct ipa_proxy *ipp;
+
+struct ipa_proxy_conn {
+ struct bsc_fd fd;
+ struct llist_head tx_queue;
+ struct ipa_bts_conn *bts_conn;
+};
+
+#define MAX_TRX 4
+
+/* represents a particular BTS in our proxy */
+struct ipa_bts_conn {
+ /* list of BTS's (ipa_proxy->bts_list) */
+ struct llist_head list;
+ /* back pointer to the proxy which we belong to */
+ struct ipa_proxy *ipp;
+ /* the unit ID as determined by CCM */
+ struct {
+ u_int16_t site_id;
+ u_int16_t bts_id;
+ } unit_id;
+
+ /* incoming connections from BTS */
+ struct ipa_proxy_conn *oml_conn;
+ struct ipa_proxy_conn *rsl_conn[MAX_TRX];
+
+ /* outgoing connections to BSC */
+ struct ipa_proxy_conn *bsc_oml_conn;
+ struct ipa_proxy_conn *bsc_rsl_conn[MAX_TRX];
+
+ /* UDP sockets for BTS and BSC injection */
+ struct bsc_fd udp_bts_fd;
+ struct bsc_fd udp_bsc_fd;
+
+ char *id_tags[0xff];
+ u_int8_t *id_resp;
+ unsigned int id_resp_len;
+};
+
+enum ipp_fd_type {
+ OML_FROM_BTS = 1,
+ RSL_FROM_BTS = 2,
+ OML_TO_BSC = 3,
+ RSL_TO_BSC = 4,
+ UDP_TO_BTS = 5,
+ UDP_TO_BSC = 6,
+};
+
+/* some of the code against we link from OpenBSC needs this */
+void *tall_bsc_ctx;
+
+static char *listen_ipaddr;
+static char *bsc_ipaddr;
+
+#define PROXY_ALLOC_SIZE 300
+
+static const u_int8_t pong[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG };
+static const u_int8_t id_ack[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK };
+static const u_int8_t id_req[] = { 0, 17, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_GET,
+ 0x01, IPAC_IDTAG_UNIT,
+ 0x01, IPAC_IDTAG_MACADDR,
+ 0x01, IPAC_IDTAG_LOCATION1,
+ 0x01, IPAC_IDTAG_LOCATION2,
+ 0x01, IPAC_IDTAG_EQUIPVERS,
+ 0x01, IPAC_IDTAG_SWVERSION,
+ 0x01, IPAC_IDTAG_UNITNAME,
+ 0x01, IPAC_IDTAG_SERNR,
+ };
+
+static const char *idtag_names[] = {
+ [IPAC_IDTAG_SERNR] = "Serial_Number",
+ [IPAC_IDTAG_UNITNAME] = "Unit_Name",
+ [IPAC_IDTAG_LOCATION1] = "Location_1",
+ [IPAC_IDTAG_LOCATION2] = "Location_2",
+ [IPAC_IDTAG_EQUIPVERS] = "Equipment_Version",
+ [IPAC_IDTAG_SWVERSION] = "Software_Version",
+ [IPAC_IDTAG_IPADDR] = "IP_Address",
+ [IPAC_IDTAG_MACADDR] = "MAC_Address",
+ [IPAC_IDTAG_UNIT] = "Unit_ID",
+};
+
+static const char *ipac_idtag_name(int tag)
+{
+ if (tag >= ARRAY_SIZE(idtag_names))
+ return "unknown";
+
+ return idtag_names[tag];
+}
+
+static int ipac_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)
+{
+ u_int8_t t_len;
+ u_int8_t t_tag;
+ u_int8_t *cur = buf;
+
+ while (cur < buf + len) {
+ t_len = *cur++;
+ t_tag = *cur++;
+
+ DEBUGPC(DMI, "%s='%s' ", ipac_idtag_name(t_tag), cur);
+
+ dec->lv[t_tag].len = t_len;
+ dec->lv[t_tag].val = cur;
+
+ cur += t_len;
+ }
+ return 0;
+}
+
+static int parse_unitid(const char *str, u_int16_t *site_id, u_int16_t *bts_id,
+ u_int16_t *trx_id)
+{
+ unsigned long ul;
+ char *endptr;
+ const char *nptr;
+
+ nptr = str;
+ ul = strtoul(nptr, &endptr, 10);
+ if (endptr <= nptr)
+ return -EINVAL;
+ if (site_id)
+ *site_id = ul & 0xffff;
+
+ if (*endptr++ != '/')
+ return -EINVAL;
+
+ nptr = endptr;
+ ul = strtoul(nptr, &endptr, 10);
+ if (endptr <= nptr)
+ return -EINVAL;
+ if (bts_id)
+ *bts_id = ul & 0xffff;
+
+ if (*endptr++ != '/')
+ return -EINVAL;
+
+ nptr = endptr;
+ ul = strtoul(nptr, &endptr, 10);
+ if (endptr <= nptr)
+ return -EINVAL;
+ if (trx_id)
+ *trx_id = ul & 0xffff;
+
+ return 0;
+}
+
+static struct ipa_bts_conn *find_bts_by_unitid(struct ipa_proxy *ipp,
+ u_int16_t site_id,
+ u_int16_t bts_id)
+{
+ struct ipa_bts_conn *ipbc;
+
+ llist_for_each_entry(ipbc, &ipp->bts_list, list) {
+ if (ipbc->unit_id.site_id == site_id &&
+ ipbc->unit_id.bts_id == bts_id)
+ return ipbc;
+ }
+
+ return NULL;
+}
+
+struct ipa_proxy_conn *alloc_conn(void)
+{
+ struct ipa_proxy_conn *ipc;
+
+ ipc = talloc_zero(tall_bsc_ctx, struct ipa_proxy_conn);
+ if (!ipc)
+ return NULL;
+
+ INIT_LLIST_HEAD(&ipc->tx_queue);
+
+ return ipc;
+}
+
+static int store_idtags(struct ipa_bts_conn *ipbc, struct tlv_parsed *tlvp)
+{
+ unsigned int i, len;
+
+ for (i = 0; i <= 0xff; i++) {
+ if (!TLVP_PRESENT(tlvp, i))
+ continue;
+
+ len = TLVP_LEN(tlvp, i);
+#if 0
+ if (!ipbc->id_tags[i])
+ ipbc->id_tags[i] = talloc_size(tall_bsc_ctx, len);
+ else
+#endif
+ ipbc->id_tags[i] = talloc_realloc_size(ipbc,
+ ipbc->id_tags[i], len);
+ if (!ipbc->id_tags[i])
+ return -ENOMEM;
+
+ memset(ipbc->id_tags[i], 0, len);
+ //memcpy(ipbc->id_tags[i], TLVP_VAL(tlvp, i), len);
+ }
+ return 0;
+}
+
+
+static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data);
+
+#define logp_ipbc_uid(ss, lvl, ipbc, trx_id) _logp_ipbc_uid(ss, lvl, __FILE__, __LINE__, ipbc, trx_id)
+
+static void _logp_ipbc_uid(unsigned int ss, unsigned int lvl, char *file, int line,
+ struct ipa_bts_conn *ipbc, u_int8_t trx_id)
+{
+ if (ipbc)
+ debugp2(ss, lvl, file, line, 0, "(%u/%u/%u) ", ipbc->unit_id.site_id,
+ ipbc->unit_id.bts_id, trx_id);
+ else
+ debugp2(ss, lvl, file, line, 0, "unknown ");
+}
+
+/* UDP socket handling */
+
+static int make_sock(struct bsc_fd *bfd, u_int16_t port, int proto, int priv_nr,
+ int (*cb)(struct bsc_fd *fd, unsigned int what),
+ void *data)
+{
+ struct sockaddr_in addr;
+ int ret, on = 1;
+
+ bfd->fd = socket(AF_INET, SOCK_DGRAM, proto);
+ bfd->cb = cb;
+ bfd->when = BSC_FD_READ;
+ bfd->data = data;
+ bfd->priv_nr = priv_nr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+ ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "could not bind socket: %s\n",
+ strerror(errno));
+ return -EIO;
+ }
+
+ ret = bsc_register_fd(bfd);
+ if (ret < 0) {
+ perror("register UDP fd");
+ return ret;
+ }
+ return 0;
+}
+
+static int handle_udp_read(struct bsc_fd *bfd)
+{
+ struct ipa_bts_conn *ipbc = bfd->data;
+ struct ipa_proxy_conn *other_conn = NULL;
+ struct msgb *msg = msgb_alloc(PROXY_ALLOC_SIZE, "Abis/IP UDP");
+ struct ipaccess_head *hh;
+ int ret;
+
+ /* with UDP sockets, we cannot read partial packets but have to read
+ * all of it in one go */
+ hh = (struct ipaccess_head *) msg->data;
+ ret = recv(bfd->fd, msg->data, msg->data_len, 0);
+ if (ret < 0) {
+ if (errno != EAGAIN)
+ LOGP(DINP, LOGL_ERROR, "recv error %s\n", strerror(errno));
+ msgb_free(msg);
+ return ret;
+ }
+ if (ret == 0) {
+ DEBUGP(DINP, "UDP peer disappeared, dead socket\n");
+ bsc_unregister_fd(bfd);
+ close(bfd->fd);
+ bfd->fd = -1;
+ msgb_free(msg);
+ return -EIO;
+ }
+ if (ret < sizeof(*hh)) {
+ DEBUGP(DINP, "could not even read header!?!\n");
+ msgb_free(msg);
+ return -EIO;
+ }
+ msgb_put(msg, ret);
+ msg->l2h = msg->data + sizeof(*hh);
+ DEBUGP(DMI, "UDP RX: %s\n", hexdump(msg->data, msg->len));
+
+ if (hh->len != msg->len - sizeof(*hh)) {
+ DEBUGP(DINP, "length (%u/%u) disagrees with header(%u)\n",
+ msg->len, msg->len - 3, hh->len);
+ msgb_free(msg);
+ return -EIO;
+ }
+
+ switch (bfd->priv_nr & 0xff) {
+ case UDP_TO_BTS:
+ /* injection towards BTS */
+ switch (hh->proto) {
+ case IPAC_PROTO_RSL:
+ /* FIXME: what to do about TRX > 0 */
+ other_conn = ipbc->rsl_conn[0];
+ break;
+ default:
+ DEBUGP(DINP, "Unknown protocol 0x%02x, sending to "
+ "OML FD\n", hh->proto);
+ /* fall through */
+ case IPAC_PROTO_IPACCESS:
+ case IPAC_PROTO_OML:
+ other_conn = ipbc->oml_conn;
+ break;
+ }
+ break;
+ case UDP_TO_BSC:
+ /* injection towards BSC */
+ switch (hh->proto) {
+ case IPAC_PROTO_RSL:
+ /* FIXME: what to do about TRX > 0 */
+ other_conn = ipbc->bsc_rsl_conn[0];
+ break;
+ default:
+ DEBUGP(DINP, "Unknown protocol 0x%02x, sending to "
+ "OML FD\n", hh->proto);
+ case IPAC_PROTO_IPACCESS:
+ case IPAC_PROTO_OML:
+ other_conn = ipbc->bsc_oml_conn;
+ break;
+ }
+ break;
+ default:
+ DEBUGP(DINP, "Unknown filedescriptor priv_nr=%04x\n", bfd->priv_nr);
+ break;
+ }
+
+ if (other_conn) {
+ /* enqueue the message for TX on the respective FD */
+ msgb_enqueue(&other_conn->tx_queue, msg);
+ other_conn->fd.when |= BSC_FD_WRITE;
+ } else
+ msgb_free(msg);
+
+ return 0;
+}
+
+static int handle_udp_write(struct bsc_fd *bfd)
+{
+ /* not implemented yet */
+ bfd->when &= ~BSC_FD_WRITE;
+
+ return -EIO;
+}
+
+/* callback from select.c in case one of the fd's can be read/written */
+static int udp_fd_cb(struct bsc_fd *bfd, unsigned int what)
+{
+ int rc = 0;
+
+ if (what & BSC_FD_READ)
+ rc = handle_udp_read(bfd);
+ if (what & BSC_FD_WRITE)
+ rc = handle_udp_write(bfd);
+
+ return rc;
+}
+
+
+static int ipbc_alloc_connect(struct ipa_proxy_conn *ipc, struct bsc_fd *bfd,
+ u_int16_t site_id, u_int16_t bts_id,
+ u_int16_t trx_id, struct tlv_parsed *tlvp,
+ struct msgb *msg)
+{
+ struct ipa_bts_conn *ipbc;
+ u_int16_t udp_port;
+ int ret = 0;
+ struct sockaddr_in sin;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ inet_aton(bsc_ipaddr, &sin.sin_addr);
+
+ DEBUGP(DINP, "(%u/%u/%u) New BTS connection: ",
+ site_id, bts_id, trx_id);
+
+ /* OML needs to be established before RSL */
+ if ((bfd->priv_nr & 0xff) != OML_FROM_BTS) {
+ DEBUGPC(DINP, "Not a OML connection ?!?\n");
+ return -EIO;
+ }
+
+ /* allocate new BTS connection data structure */
+ ipbc = talloc_zero(tall_bsc_ctx, struct ipa_bts_conn);
+ if (!ipbc) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ DEBUGPC(DINP, "Created BTS Conn data structure\n");
+ ipbc->ipp = ipp;
+ ipbc->unit_id.site_id = site_id;
+ ipbc->unit_id.bts_id = bts_id;
+ ipbc->oml_conn = ipc;
+ ipc->bts_conn = ipbc;
+
+ /* store the content of the ID TAGS for later reference */
+ store_idtags(ipbc, tlvp);
+ ipbc->id_resp_len = msg->len;
+ ipbc->id_resp = talloc_size(tall_bsc_ctx, ipbc->id_resp_len);
+ memcpy(ipbc->id_resp, msg->data, ipbc->id_resp_len);
+
+ /* Create OML TCP connection towards BSC */
+ sin.sin_port = htons(IPA_TCP_PORT_OML);
+ ipbc->bsc_oml_conn = connect_bsc(&sin, OML_TO_BSC, ipbc);
+ if (!ipbc->bsc_oml_conn) {
+ ret = -EIO;
+ goto err_bsc_conn;
+ }
+
+ DEBUGP(DINP, "(%u/%u/%u) OML Connected to BSC\n",
+ site_id, bts_id, trx_id);
+
+ /* Create UDP socket for BTS packet injection */
+ udp_port = 10000 + (site_id % 1000)*100 + (bts_id % 100);
+ ret = make_sock(&ipbc->udp_bts_fd, udp_port, IPPROTO_UDP,
+ UDP_TO_BTS, udp_fd_cb, ipbc);
+ if (ret < 0)
+ goto err_udp_bts;
+ DEBUGP(DINP, "(%u/%u/%u) Created UDP socket for injection "
+ "towards BTS at port %u\n", site_id, bts_id, trx_id, udp_port);
+
+ /* Create UDP socket for BSC packet injection */
+ udp_port = 20000 + (site_id % 1000)*100 + (bts_id % 100);
+ ret = make_sock(&ipbc->udp_bsc_fd, udp_port, IPPROTO_UDP,
+ UDP_TO_BSC, udp_fd_cb, ipbc);
+ if (ret < 0)
+ goto err_udp_bsc;
+ DEBUGP(DINP, "(%u/%u/%u) Created UDP socket for injection "
+ "towards BSC at port %u\n", site_id, bts_id, trx_id, udp_port);
+ llist_add(&ipbc->list, &ipp->bts_list);
+
+ return 0;
+
+err_udp_bsc:
+ bsc_unregister_fd(&ipbc->udp_bts_fd);
+err_udp_bts:
+ bsc_unregister_fd(&ipbc->bsc_oml_conn->fd);
+ close(ipbc->bsc_oml_conn->fd.fd);
+ talloc_free(ipbc->bsc_oml_conn);
+ ipbc->bsc_oml_conn = NULL;
+err_bsc_conn:
+ talloc_free(ipbc->id_resp);
+ talloc_free(ipbc);
+#if 0
+ bsc_unregister_fd(bfd);
+ close(bfd->fd);
+ talloc_free(bfd);
+#endif
+err_out:
+ return ret;
+}
+
+static int ipaccess_rcvmsg(struct ipa_proxy_conn *ipc, struct msgb *msg,
+ struct bsc_fd *bfd)
+{
+ struct tlv_parsed tlvp;
+ u_int8_t msg_type = *(msg->l2h);
+ u_int16_t site_id, bts_id, trx_id;
+ struct ipa_bts_conn *ipbc;
+ int ret = 0;
+
+ switch (msg_type) {
+ case IPAC_MSGT_PING:
+ ret = write(bfd->fd, pong, sizeof(pong));
+ if (ret < 0)
+ return ret;
+ if (ret < sizeof(pong)) {
+ DEBUGP(DINP, "short write\n");
+ return -EIO;
+ }
+ break;
+ case IPAC_MSGT_PONG:
+ DEBUGP(DMI, "PONG!\n");
+ break;
+ case IPAC_MSGT_ID_RESP:
+ DEBUGP(DMI, "ID_RESP ");
+ /* parse tags, search for Unit ID */
+ ipac_idtag_parse(&tlvp, (u_int8_t *)msg->l2h + 2,
+ msgb_l2len(msg)-2);
+ DEBUGP(DMI, "\n");
+
+ if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT)) {
+ LOGP(DINP, LOGL_ERROR, "No Unit ID in ID RESPONSE !?!\n");
+ return -EIO;
+ }
+
+ /* lookup BTS, create sign_link, ... */
+ parse_unitid((char *)TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT),
+ &site_id, &bts_id, &trx_id);
+ ipbc = find_bts_by_unitid(ipp, site_id, bts_id);
+ if (!ipbc) {
+ /* We have not found an ipbc (per-bts proxy instance)
+ * for this BTS yet. The first connection of a new BTS must
+ * be a OML connection. We allocate the associated data structures,
+ * and try to connect to the remote end */
+
+ return ipbc_alloc_connect(ipc, bfd, site_id, bts_id,
+ trx_id, &tlvp, msg);
+ /* if this fails, the caller will clean up bfd */
+ } else {
+ struct sockaddr_in sin;
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ inet_aton(bsc_ipaddr, &sin.sin_addr);
+
+ DEBUGP(DINP, "Identified BTS %u/%u/%u\n",
+ site_id, bts_id, trx_id);
+
+ if ((bfd->priv_nr & 0xff) != RSL_FROM_BTS) {
+ LOGP(DINP, LOGL_ERROR, "Second OML connection from "
+ "same BTS ?!?\n");
+ return 0;
+ }
+
+ if (trx_id > MAX_TRX) {
+ LOGP(DINP, LOGL_ERROR, "We don't support more "
+ "than %u TRX\n", MAX_TRX);
+ return -EINVAL;
+ }
+
+ ipc->bts_conn = ipbc;
+ /* store TRX number in higher 8 bit of the bfd private number */
+ bfd->priv_nr |= trx_id << 8;
+ ipbc->rsl_conn[trx_id] = ipc;
+
+ /* Create RSL TCP connection towards BSC */
+ sin.sin_port = htons(IPA_TCP_PORT_RSL);
+ ipbc->bsc_rsl_conn[trx_id] =
+ connect_bsc(&sin, RSL_TO_BSC | (trx_id << 8), ipbc);
+ if (!ipbc->bsc_oml_conn)
+ return -EIO;
+ DEBUGP(DINP, "(%u/%u/%u) Connected RSL to BSC\n",
+ site_id, bts_id, trx_id);
+ }
+ break;
+ case IPAC_MSGT_ID_GET:
+ DEBUGP(DMI, "ID_GET\n");
+ if ((bfd->priv_nr & 0xff) != OML_TO_BSC &&
+ (bfd->priv_nr & 0xff) != RSL_TO_BSC) {
+ DEBUGP(DINP, "IDentity REQuest from BTS ?!?\n");
+ return -EIO;
+ }
+ ipbc = ipc->bts_conn;
+ if (!ipbc) {
+ DEBUGP(DINP, "ID_GET from BSC before we have ID_RESP from BTS\n");
+ return -EIO;
+ }
+ ret = write(bfd->fd, ipbc->id_resp, ipbc->id_resp_len);
+ break;
+ case IPAC_MSGT_ID_ACK:
+ DEBUGP(DMI, "ID_ACK? -> ACK!\n");
+ ret = write(bfd->fd, id_ack, sizeof(id_ack));
+ break;
+ }
+ return 0;
+}
+
+struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error)
+{
+ struct msgb *msg = msgb_alloc(PROXY_ALLOC_SIZE, "Abis/IP");
+ struct ipaccess_head *hh;
+ int len, ret = 0;
+
+ if (!msg) {
+ *error = -ENOMEM;
+ return NULL;
+ }
+
+ /* first read our 3-byte header */
+ hh = (struct ipaccess_head *) msg->data;
+ ret = recv(bfd->fd, msg->data, 3, 0);
+ if (ret < 0) {
+ if (errno != EAGAIN)
+ LOGP(DINP, LOGL_ERROR, "recv error: %s\n", strerror(errno));
+ msgb_free(msg);
+ *error = ret;
+ return NULL;
+ } else if (ret == 0) {
+ msgb_free(msg);
+ *error = ret;
+ return NULL;
+ }
+
+ msgb_put(msg, ret);
+
+ /* then read te length as specified in header */
+ msg->l2h = msg->data + sizeof(*hh);
+ len = ntohs(hh->len);
+ ret = recv(bfd->fd, msg->l2h, len, 0);
+ if (ret < len) {
+ LOGP(DINP, LOGL_ERROR, "short read!\n");
+ msgb_free(msg);
+ *error = -EIO;
+ return NULL;
+ }
+ msgb_put(msg, ret);
+
+ return msg;
+}
+
+static struct ipa_proxy_conn *ipc_by_priv_nr(struct ipa_bts_conn *ipbc,
+ unsigned int priv_nr)
+{
+ struct ipa_proxy_conn *bsc_conn;
+ unsigned int trx_id = priv_nr >> 8;
+
+ switch (priv_nr & 0xff) {
+ case OML_FROM_BTS: /* incoming OML data from BTS, forward to BSC OML */
+ bsc_conn = ipbc->bsc_oml_conn;
+ break;
+ case RSL_FROM_BTS: /* incoming RSL data from BTS, forward to BSC RSL */
+ bsc_conn = ipbc->bsc_rsl_conn[trx_id];
+ break;
+ case OML_TO_BSC: /* incoming OML data from BSC, forward to BTS OML */
+ bsc_conn = ipbc->oml_conn;
+ break;
+ case RSL_TO_BSC: /* incoming RSL data from BSC, forward to BTS RSL */
+ bsc_conn = ipbc->rsl_conn[trx_id];
+ break;
+ default:
+ bsc_conn = NULL;
+ break;
+ }
+ return bsc_conn;
+}
+
+static void reconn_tmr_cb(void *data)
+{
+ struct ipa_proxy *ipp = data;
+ struct ipa_bts_conn *ipbc;
+ struct sockaddr_in sin;
+ int i;
+
+ DEBUGP(DINP, "Running reconnect timer\n");
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ inet_aton(bsc_ipaddr, &sin.sin_addr);
+
+ llist_for_each_entry(ipbc, &ipp->bts_list, list) {
+ /* if OML to BSC is dead, try to restore it */
+ if (ipbc->oml_conn && !ipbc->bsc_oml_conn) {
+ sin.sin_port = htons(IPA_TCP_PORT_OML);
+ logp_ipbc_uid(DINP, LOGL_NOTICE, ipbc, 0);
+ LOGPC(DINP, LOGL_NOTICE, "OML Trying to reconnect\n");
+ ipbc->bsc_oml_conn = connect_bsc(&sin, OML_TO_BSC, ipbc);
+ if (!ipbc->bsc_oml_conn)
+ goto reschedule;
+ logp_ipbc_uid(DINP, LOGL_NOTICE, ipbc, 0);
+ LOGPC(DINP, LOGL_NOTICE, "OML Reconnected\n");
+ }
+ /* if we (still) don't have a OML connection, skip RSL */
+ if (!ipbc->oml_conn || !ipbc->bsc_oml_conn)
+ continue;
+
+ for (i = 0; i < ARRAY_SIZE(ipbc->rsl_conn); i++) {
+ unsigned int priv_nr;
+ /* don't establish RSL links which we don't have */
+ if (!ipbc->rsl_conn[i])
+ continue;
+ if (ipbc->bsc_rsl_conn[i])
+ continue;
+ priv_nr = ipbc->rsl_conn[i]->fd.priv_nr;
+ priv_nr &= ~0xff;
+ priv_nr |= RSL_TO_BSC;
+ sin.sin_port = htons(IPA_TCP_PORT_RSL);
+ logp_ipbc_uid(DINP, LOGL_NOTICE, ipbc, priv_nr >> 8);
+ LOGPC(DINP, LOGL_NOTICE, "RSL Trying to reconnect\n");
+ ipbc->bsc_rsl_conn[i] = connect_bsc(&sin, priv_nr, ipbc);
+ if (!ipbc->bsc_rsl_conn)
+ goto reschedule;
+ logp_ipbc_uid(DINP, LOGL_NOTICE, ipbc, priv_nr >> 8);
+ LOGPC(DINP, LOGL_NOTICE, "RSL Reconnected\n");
+ }
+ }
+ return;
+
+reschedule:
+ bsc_schedule_timer(&ipp->reconn_timer, 5, 0);
+}
+
+static void handle_dead_socket(struct bsc_fd *bfd)
+{
+ struct ipa_proxy_conn *ipc = bfd->data; /* local conn */
+ struct ipa_proxy_conn *bsc_conn; /* remote conn */
+ struct ipa_bts_conn *ipbc = ipc->bts_conn;
+ unsigned int trx_id = bfd->priv_nr >> 8;
+ struct msgb *msg, *msg2;
+
+ bsc_unregister_fd(bfd);
+ close(bfd->fd);
+ bfd->fd = -1;
+
+ /* FIXME: clear tx_queue, remove all references, etc. */
+ llist_for_each_entry_safe(msg, msg2, &ipc->tx_queue, list)
+ msgb_free(msg);
+
+ switch (bfd->priv_nr & 0xff) {
+ case OML_FROM_BTS: /* incoming OML data from BTS, forward to BSC OML */
+ ipbc->oml_conn = NULL;
+ bsc_conn = ipbc->bsc_oml_conn;
+ /* close the connection to the BSC */
+ bsc_unregister_fd(&bsc_conn->fd);
+ close(bsc_conn->fd.fd);
+ llist_for_each_entry_safe(msg, msg2, &bsc_conn->tx_queue, list)
+ msgb_free(msg);
+ talloc_free(bsc_conn);
+ ipbc->bsc_oml_conn = NULL;
+ /* FIXME: do we need to delete the entire ipbc ? */
+ break;
+ case RSL_FROM_BTS: /* incoming RSL data from BTS, forward to BSC RSL */
+ ipbc->rsl_conn[trx_id] = NULL;
+ bsc_conn = ipbc->bsc_rsl_conn[trx_id];
+ /* close the connection to the BSC */
+ bsc_unregister_fd(&bsc_conn->fd);
+ close(bsc_conn->fd.fd);
+ llist_for_each_entry_safe(msg, msg2, &bsc_conn->tx_queue, list)
+ msgb_free(msg);
+ talloc_free(bsc_conn);
+ ipbc->bsc_rsl_conn[trx_id] = NULL;
+ break;
+ case OML_TO_BSC: /* incoming OML data from BSC, forward to BTS OML */
+ ipbc->bsc_oml_conn = NULL;
+ bsc_conn = ipbc->oml_conn;
+ /* start reconnect timer */
+ bsc_schedule_timer(&ipp->reconn_timer, 5, 0);
+ break;
+ case RSL_TO_BSC: /* incoming RSL data from BSC, forward to BTS RSL */
+ ipbc->bsc_rsl_conn[trx_id] = NULL;
+ bsc_conn = ipbc->rsl_conn[trx_id];
+ /* start reconnect timer */
+ bsc_schedule_timer(&ipp->reconn_timer, 5, 0);
+ break;
+ default:
+ bsc_conn = NULL;
+ break;
+ }
+
+ talloc_free(ipc);
+}
+
+static int handle_tcp_read(struct bsc_fd *bfd)
+{
+ struct ipa_proxy_conn *ipc = bfd->data;
+ struct ipa_bts_conn *ipbc = ipc->bts_conn;
+ struct ipa_proxy_conn *bsc_conn;
+ struct msgb *msg;
+ struct ipaccess_head *hh;
+ int ret = 0;
+ char *btsbsc;
+
+ if ((bfd->priv_nr & 0xff) <= 2)
+ btsbsc = "BTS";
+ else
+ btsbsc = "BSC";
+
+ msg = ipaccess_read_msg(bfd, &ret);
+ if (!msg) {
+ if (ret == 0) {
+ logp_ipbc_uid(DINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8);
+ LOGPC(DINP, LOGL_NOTICE, "%s disappeared, "
+ "dead socket\n", btsbsc);
+ handle_dead_socket(bfd);
+ }
+ return ret;
+ }
+
+ msgb_put(msg, ret);
+ logp_ipbc_uid(DMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8);
+ DEBUGPC(DMI, "RX<-%s: %s\n", btsbsc, hexdump(msg->data, msg->len));
+
+ hh = (struct ipaccess_head *) msg->data;
+ if (hh->proto == IPAC_PROTO_IPACCESS) {
+ ret = ipaccess_rcvmsg(ipc, msg, bfd);
+ if (ret < 0) {
+ bsc_unregister_fd(bfd);
+ close(bfd->fd);
+ bfd->fd = -1;
+ talloc_free(bfd);
+ }
+ /* we do not forward the CCM protocol through the
+ * proxy but rather terminate it ourselves */
+ msgb_free(msg);
+ return ret;
+ }
+
+ if (!ipbc) {
+ LOGP(DINP, LOGL_ERROR,
+ "received %s packet but no ipc->bts_conn?!?\n", btsbsc);
+ msgb_free(msg);
+ return -EIO;
+ }
+
+ bsc_conn = ipc_by_priv_nr(ipbc, bfd->priv_nr);
+ if (bsc_conn) {
+ /* enqueue packet towards BSC */
+ msgb_enqueue(&bsc_conn->tx_queue, msg);
+ /* mark respective filedescriptor as 'we want to write' */
+ bsc_conn->fd.when |= BSC_FD_WRITE;
+ } else {
+ logp_ipbc_uid(DINP, LOGL_INFO, ipbc, bfd->priv_nr >> 8);
+ LOGPC(DINP, LOGL_INFO, "Dropping packet from %s, "
+ "since remote connection is dead\n", btsbsc);
+ msgb_free(msg);
+ }
+
+ return ret;
+}
+
+/* a TCP socket is ready to be written to */
+static int handle_tcp_write(struct bsc_fd *bfd)
+{
+ struct ipa_proxy_conn *ipc = bfd->data;
+ struct ipa_bts_conn *ipbc = ipc->bts_conn;
+ struct llist_head *lh;
+ struct msgb *msg;
+ char *btsbsc;
+ int ret;
+
+ if ((bfd->priv_nr & 0xff) <= 2)
+ btsbsc = "BTS";
+ else
+ btsbsc = "BSC";
+
+
+ /* get the next msg for this timeslot */
+ if (llist_empty(&ipc->tx_queue)) {
+ bfd->when &= ~BSC_FD_WRITE;
+ return 0;
+ }
+ lh = ipc->tx_queue.next;
+ llist_del(lh);
+ msg = llist_entry(lh, struct msgb, list);
+
+ logp_ipbc_uid(DMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8);
+ DEBUGPC(DMI, "TX %04x: %s\n", bfd->priv_nr,
+ hexdump(msg->data, msg->len));
+
+ ret = send(bfd->fd, msg->data, msg->len, 0);
+ msgb_free(msg);
+
+ if (ret == 0) {
+ logp_ipbc_uid(DINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8);
+ LOGP(DINP, LOGL_NOTICE, "%s disappeared, dead socket\n", btsbsc);
+ handle_dead_socket(bfd);
+ }
+
+ return ret;
+}
+
+/* callback from select.c in case one of the fd's can be read/written */
+static int ipaccess_fd_cb(struct bsc_fd *bfd, unsigned int what)
+{
+ int rc = 0;
+
+ if (what & BSC_FD_READ) {
+ rc = handle_tcp_read(bfd);
+ if (rc < 0)
+ return rc;
+ }
+ if (what & BSC_FD_WRITE)
+ rc = handle_tcp_write(bfd);
+
+ return rc;
+}
+
+/* callback of the listening filedescriptor */
+static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
+{
+ int ret;
+ struct ipa_proxy_conn *ipc;
+ struct bsc_fd *bfd;
+ struct sockaddr_in sa;
+ socklen_t sa_len = sizeof(sa);
+
+ if (!(what & BSC_FD_READ))
+ return 0;
+
+ ret = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len);
+ if (ret < 0) {
+ perror("accept");
+ return ret;
+ }
+ DEBUGP(DINP, "accept()ed new %s link from %s\n",
+ (listen_bfd->priv_nr & 0xff) == OML_FROM_BTS ? "OML" : "RSL",
+ inet_ntoa(sa.sin_addr));
+
+ ipc = alloc_conn();
+ if (!ipc) {
+ close(ret);
+ return -ENOMEM;
+ }
+
+ bfd = &ipc->fd;
+ bfd->fd = ret;
+ bfd->data = ipc;
+ bfd->priv_nr = listen_bfd->priv_nr;
+ bfd->cb = ipaccess_fd_cb;
+ bfd->when = BSC_FD_READ;
+ ret = bsc_register_fd(bfd);
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "could not register FD\n");
+ close(bfd->fd);
+ talloc_free(ipc);
+ return ret;
+ }
+
+ /* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
+ ret = write(bfd->fd, id_req, sizeof(id_req));
+
+ return 0;
+}
+
+static int make_listen_sock(struct bsc_fd *bfd, u_int16_t port, int priv_nr,
+ int (*cb)(struct bsc_fd *fd, unsigned int what))
+{
+ struct sockaddr_in addr;
+ int ret, on = 1;
+
+ bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ bfd->cb = cb;
+ bfd->when = BSC_FD_READ;
+ bfd->priv_nr = priv_nr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ if (!listen_ipaddr)
+ addr.sin_addr.s_addr = INADDR_ANY;
+ else
+ inet_aton(listen_ipaddr, &addr.sin_addr);
+
+ setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+ ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "could not bind listen socket %s\n",
+ strerror(errno));
+ return -EIO;
+ }
+
+ ret = listen(bfd->fd, 1);
+ if (ret < 0) {
+ perror("listen");
+ return ret;
+ }
+
+ ret = bsc_register_fd(bfd);
+ if (ret < 0) {
+ perror("register_listen_fd");
+ return ret;
+ }
+ return 0;
+}
+
+/* Actively connect to a BSC. */
+static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data)
+{
+ struct ipa_proxy_conn *ipc;
+ struct bsc_fd *bfd;
+ int ret, on = 1;
+
+ ipc = alloc_conn();
+ if (!ipc)
+ return NULL;
+
+ ipc->bts_conn = data;
+
+ bfd = &ipc->fd;
+ bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ bfd->cb = ipaccess_fd_cb;
+ bfd->when = BSC_FD_READ | BSC_FD_WRITE;
+ bfd->data = ipc;
+ bfd->priv_nr = priv_nr;
+
+ setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+ ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa));
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "could not connect socket\n");
+ close(bfd->fd);
+ talloc_free(ipc);
+ return NULL;
+ }
+
+ /* pre-fill tx_queue with identity request */
+ ret = bsc_register_fd(bfd);
+ if (ret < 0) {
+ close(bfd->fd);
+ talloc_free(ipc);
+ return NULL;
+ }
+
+ return ipc;
+}
+
+static int ipaccess_proxy_setup(void)
+{
+ int ret;
+
+ ipp = talloc_zero(tall_bsc_ctx, struct ipa_proxy);
+ if (!ipp)
+ return -ENOMEM;
+ INIT_LLIST_HEAD(&ipp->bts_list);
+ ipp->reconn_timer.cb = reconn_tmr_cb;
+ ipp->reconn_timer.data = ipp;
+
+ /* Listen for OML connections */
+ ret = make_listen_sock(&ipp->oml_listen_fd, IPA_TCP_PORT_OML,
+ OML_FROM_BTS, listen_fd_cb);
+ if (ret < 0)
+ return ret;
+
+ /* Listen for RSL connections */
+ ret = make_listen_sock(&ipp->rsl_listen_fd, IPA_TCP_PORT_RSL,
+ RSL_FROM_BTS, listen_fd_cb);
+
+ return ret;
+}
+
+static void signal_handler(int signal)
+{
+ fprintf(stdout, "signal %u received\n", signal);
+
+ switch (signal) {
+ case SIGABRT:
+ /* in case of abort, we want to obtain a talloc report
+ * and then return to the caller, who will abort the process */
+ case SIGUSR1:
+ talloc_report_full(tall_bsc_ctx, stderr);
+ break;
+ default:
+ break;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int rc;
+
+ listen_ipaddr = "192.168.100.11";
+ bsc_ipaddr = "192.168.100.239";
+
+ tall_bsc_ctx = talloc_named_const(NULL, 1, "ipaccess-proxy");
+
+ debug_init();
+ stderr_target = debug_target_create_stderr();
+ debug_add_target(stderr_target);
+ debug_set_all_filter(stderr_target, 1);
+ debug_parse_category_mask(stderr_target, "DINP:DMI");
+
+ rc = ipaccess_proxy_setup();
+ if (rc < 0)
+ exit(1);
+
+ signal(SIGUSR1, &signal_handler);
+ signal(SIGABRT, &signal_handler);
+
+ while (1) {
+ bsc_select_main(0);
+ }
+}
diff --git a/openbsc/src/msgb.c b/openbsc/src/msgb.c
index 48a5a7b03..9f2fcfa96 100644
--- a/openbsc/src/msgb.c
+++ b/openbsc/src/msgb.c
@@ -28,7 +28,7 @@
#include <openbsc/talloc.h>
#include <openbsc/debug.h>
-static void *tall_msgb_ctx;
+void *tall_msgb_ctx;
struct msgb *msgb_alloc(u_int16_t size, const char *name)
{
@@ -96,8 +96,3 @@ void msgb_reset(struct msgb *msg)
msg->l3h = NULL;
msg->smsh = NULL;
}
-
-static __attribute__((constructor)) void on_dso_load_trau_msgb(void)
-{
- tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 1, "msgb");
-}
diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c
index b273419c3..91de70241 100644
--- a/openbsc/src/paging.c
+++ b/openbsc/src/paging.c
@@ -212,7 +212,9 @@ static void paging_T3113_expired(void *data)
cbfn = req->cbfn;
paging_remove_request(&req->bts->paging, req);
- dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
+ counter_inc(req->bts->network->stats.paging.expired);
+
+ dispatch_signal(SS_PAGING, S_PAGING_EXPIRED, &sig_data);
if (cbfn)
cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED, NULL, NULL,
cbfn_param);
@@ -254,6 +256,8 @@ int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
struct gsm_bts *bts = NULL;
int num_pages = 0;
+ counter_inc(network->stats.paging.attempted);
+
/* start paging subscriber on all BTS within Location Area */
do {
int rc;
@@ -261,6 +265,11 @@ int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
bts = gsm_bts_by_lac(network, subscr->lac, bts);
if (!bts)
break;
+
+ /* skip all currently inactive TRX */
+ if (!trx_is_usable(bts->c0))
+ continue;
+
num_pages++;
/* Trigger paging, pass any error to caller */
@@ -269,6 +278,9 @@ int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
return rc;
} while (1);
+ if (num_pages == 0)
+ counter_inc(network->stats.paging.detached);
+
return num_pages;
}
diff --git a/openbsc/src/rrlp.c b/openbsc/src/rrlp.c
index d4665d570..35044518c 100644
--- a/openbsc/src/rrlp.c
+++ b/openbsc/src/rrlp.c
@@ -89,14 +89,12 @@ static int paging_sig_cb(unsigned int subsys, unsigned int signal,
struct paging_signal_data *psig_data = signal_data;
switch (signal) {
- case S_PAGING_COMPLETED:
- /* paging might have "completed' unsucessfully,
- * in this case we don't have a lchan */
- if (!psig_data->lchan)
- break;
+ case S_PAGING_SUCCEEDED:
/* A subscriber has attached. */
send_rrlp_req(psig_data->lchan);
break;
+ case S_PAGING_EXPIRED:
+ break;
}
return 0;
}
diff --git a/openbsc/src/rtp_proxy.c b/openbsc/src/rtp_proxy.c
index 0f4e32799..83b774f97 100644
--- a/openbsc/src/rtp_proxy.c
+++ b/openbsc/src/rtp_proxy.c
@@ -240,7 +240,8 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame)
if (abs(frame_diff) > 1) {
long int frame_diff_excess = frame_diff - 1;
- DEBUGP(DMUX, "Correcting frame difference of %ld frames\n", frame_diff_excess);
+ LOGP(DMUX, LOGL_NOTICE,
+ "Correcting frame difference of %ld frames\n", frame_diff_excess);
rs->transmit.sequence += frame_diff_excess;
rs->transmit.timestamp += frame_diff_excess * duration;
}
diff --git a/openbsc/src/silent_call.c b/openbsc/src/silent_call.c
index 82b656327..a0c166e0a 100644
--- a/openbsc/src/silent_call.c
+++ b/openbsc/src/silent_call.c
@@ -34,6 +34,7 @@
#include <openbsc/abis_rsl.h>
#include <openbsc/chan_alloc.h>
+/* paging of the requested subscriber has completed */
static int paging_cb_silent(unsigned int hooknum, unsigned int event,
struct msgb *msg, void *_lchan, void *_data)
{
@@ -53,6 +54,7 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event,
case GSM_PAGING_SUCCEEDED:
DEBUGPC(DSMS, "success, using Timeslot %u on ARFCN %u\n",
lchan->ts->nr, lchan->ts->trx->arfcn);
+ lchan->silent_call = 1;
/* increment lchan reference count */
dispatch_signal(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
use_lchan(lchan);
@@ -69,15 +71,58 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event,
return rc;
}
-int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data)
+/* receive a layer 3 message from a silent call */
+int silent_call_rx(struct msgb *msg)
+{
+ /* FIXME: do something like sending it through a UDP port */
+ return 0;
+}
+
+struct msg_match {
+ u_int8_t pdisc;
+ u_int8_t msg_type;
+};
+
+/* list of messages that are handled inside OpenBSC, even in a silent call */
+static const struct msg_match silent_call_accept[] = {
+ { GSM48_PDISC_MM, GSM48_MT_MM_LOC_UPD_REQUEST },
+ { GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_REQ },
+};
+
+/* decide if we need to reroute a message as part of a silent call */
+int silent_call_reroute(struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ u_int8_t pdisc = gh->proto_discr & 0x0f;
+ int i;
+
+ /* if we're not part of a silent call, never reroute */
+ if (!msg->lchan->silent_call)
+ return 0;
+
+ /* check if we are a special message that is handled in openbsc */
+ for (i = 0; i < ARRAY_SIZE(silent_call_accept); i++) {
+ if (silent_call_accept[i].pdisc == pdisc &&
+ silent_call_accept[i].msg_type == gh->msg_type)
+ return 0;
+ }
+
+ /* otherwise, reroute */
+ return 1;
+}
+
+
+/* initiate a silent call with a given subscriber */
+int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data, int type)
{
int rc;
- rc = paging_request(subscr->net, subscr, RSL_CHANNEED_TCH_F,
+ rc = paging_request(subscr->net, subscr, type,
paging_cb_silent, data);
return rc;
}
+/* end a silent call with a given subscriber */
int gsm_silent_call_stop(struct gsm_subscriber *subscr)
{
struct gsm_lchan *lchan;
@@ -86,7 +131,10 @@ int gsm_silent_call_stop(struct gsm_subscriber *subscr)
if (!lchan)
return -EINVAL;
- /* FIXME: did we actually establish a silent call for this guy? */
+ /* did we actually establish a silent call for this guy? */
+ if (!lchan->silent_call)
+ return -EINVAL;
+
put_lchan(lchan);
return 0;
diff --git a/openbsc/src/statistics.c b/openbsc/src/statistics.c
new file mode 100644
index 000000000..9452b16e1
--- /dev/null
+++ b/openbsc/src/statistics.c
@@ -0,0 +1,70 @@
+/* utility routines for keeping some statistics */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+
+#include <sys/types.h>
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/signal.h>
+#include <openbsc/linuxlist.h>
+#include <openbsc/talloc.h>
+#include <openbsc/statistics.h>
+#include <openbsc/db.h>
+#include <openbsc/timer.h>
+
+static LLIST_HEAD(counters);
+
+void *tall_ctr_ctx;
+
+struct counter *counter_alloc(const char *name)
+{
+ struct counter *ctr = talloc_zero(tall_ctr_ctx, struct counter);
+
+ if (!ctr)
+ return NULL;
+
+ ctr->name = name;
+ llist_add_tail(&ctr->list, &counters);
+
+ return ctr;
+}
+
+void counter_free(struct counter *ctr)
+{
+ llist_del(&ctr->list);
+ talloc_free(ctr);
+}
+
+int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data)
+{
+ struct counter *ctr;
+ int rc = 0;
+
+ llist_for_each_entry(ctr, &counters, list) {
+ rc = handle_counter(ctr, data);
+ if (rc < 0)
+ return rc;
+ }
+
+ return rc;
+}
+
diff --git a/openbsc/src/system_information.c b/openbsc/src/system_information.c
index 830d84709..7461ea545 100644
--- a/openbsc/src/system_information.c
+++ b/openbsc/src/system_information.c
@@ -38,6 +38,22 @@
#define GSM_MACBLOCK_LEN 23
#define GSM_MACBLOCK_PADDING 0x2b
+/* verify the sizes of the system information type structs */
+
+/* rest octets are not part of the struct */
+static_assert(sizeof(struct gsm48_system_information_type_header) == 3, _si_header_size);
+static_assert(sizeof(struct gsm48_rach_control) == 3, _si_rach_control);
+static_assert(sizeof(struct gsm48_system_information_type_1) == 22, _si1_size);
+static_assert(sizeof(struct gsm48_system_information_type_2) == 23, _si2_size);
+static_assert(sizeof(struct gsm48_system_information_type_3) == 19, _si3_size);
+static_assert(sizeof(struct gsm48_system_information_type_4) == 13, _si4_size);
+
+/* bs11 forgot the l2 len, 0-6 rest octets */
+static_assert(sizeof(struct gsm48_system_information_type_5) == 18, _si5_size);
+static_assert(sizeof(struct gsm48_system_information_type_6) == 11, _si6_size);
+
+static_assert(sizeof(struct gsm48_system_information_type_13) == 3, _si13_size);
+
/* Frequency Lists as per TS 04.08 10.5.2.13 */
/* 10.5.2.13.2: Bit map 0 format */
@@ -98,7 +114,7 @@ static int freq_list_bmrel_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
static int bitvec2freq_list(u_int8_t *chan_list, struct bitvec *bv,
const struct gsm_bts *bts)
{
- int i, rc, min = 1024, max = 0;
+ int i, rc, min = 1024, max = -1;
memset(chan_list, 0, 16);
@@ -128,6 +144,12 @@ static int bitvec2freq_list(u_int8_t *chan_list, struct bitvec *bv,
}
}
+ if (max == -1) {
+ /* Empty set, use 'bit map 0 format' */
+ chan_list[0] = 0;
+ return 0;
+ }
+
if ((max - min) > 111) {
LOGP(DRR, LOGL_ERROR, "min_arfcn=%u, max_arfcn=%u, "
"distance > 111\n", min, max);
diff --git a/openbsc/src/talloc_ctx.c b/openbsc/src/talloc_ctx.c
index aa9f0b4d7..5f0ee4de8 100644
--- a/openbsc/src/talloc_ctx.c
+++ b/openbsc/src/talloc_ctx.c
@@ -1,6 +1,7 @@
#include <openbsc/talloc.h>
#include <openbsc/gsm_data.h>
+extern void *tall_msgb_ctx;
extern void *tall_fle_ctx;
extern void *tall_locop_ctx;
extern void *tall_gsms_ctx;
@@ -13,9 +14,11 @@ extern void *tall_tqe_ctx;
extern void *tall_trans_ctx;
extern void *tall_map_ctx;
extern void *tall_upq_ctx;
+extern void *tall_ctr_ctx;
void talloc_ctx_init(void)
{
+ tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 0,
"bs11_file_list_entry");
tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 0, "loc_updating_oper");
@@ -29,4 +32,5 @@ void talloc_ctx_init(void)
tall_trans_ctx = talloc_named_const(tall_bsc_ctx, 0, "transaction");
tall_map_ctx = talloc_named_const(tall_bsc_ctx, 0, "trau_map_entry");
tall_upq_ctx = talloc_named_const(tall_bsc_ctx, 0, "trau_upq_entry");
+ tall_ctr_ctx = talloc_named_const(tall_bsc_ctx, 0, "counter");
}
diff --git a/openbsc/src/telnet_interface.c b/openbsc/src/telnet_interface.c
index 2d7b05c70..ebddaf57a 100644
--- a/openbsc/src/telnet_interface.c
+++ b/openbsc/src/telnet_interface.c
@@ -84,12 +84,12 @@ void telnet_init(struct gsm_network *network, int port) {
sock_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (bind(fd, (struct sockaddr*)&sock_addr, sizeof(sock_addr)) < 0) {
- LOGP(DNM, LOG_ERROR, "Telnet interface failed to bind\n");
+ LOGP(DNM, LOGL_ERROR, "Telnet interface failed to bind\n");
return;
}
if (listen(fd, 0) < 0) {
- LOGP(DNM, LOG_ERROR, "Telnet interface failed to listen\n");
+ LOGP(DNM, LOGL_ERROR, "Telnet interface failed to listen\n");
return;
}
@@ -120,6 +120,12 @@ int telnet_close_client(struct bsc_fd *fd) {
close(fd->fd);
bsc_unregister_fd(fd);
+
+ if (conn->dbg) {
+ debug_del_target(conn->dbg);
+ talloc_free(conn->dbg);
+ }
+
llist_del(&conn->entry);
talloc_free(conn);
return 0;
diff --git a/openbsc/src/token_auth.c b/openbsc/src/token_auth.c
index f6be0bc98..fd81f035a 100644
--- a/openbsc/src/token_auth.c
+++ b/openbsc/src/token_auth.c
@@ -103,7 +103,7 @@ unauth:
if (lchan) {
u_int8_t auth_rand[16];
/* kick the subscriber off the network */
- gsm48_tx_mm_auth_req(lchan, auth_rand);
+ gsm48_tx_mm_auth_req(lchan, auth_rand, 0);
gsm48_tx_mm_auth_rej(lchan);
/* FIXME: close the channel early ?*/
//gsm48_send_rr_Release(lchan);
@@ -139,7 +139,7 @@ static int token_sms_cb(unsigned int subsys, unsigned int signal,
lchan = lchan_for_subscr(sms->receiver);
if (lchan) {
/* kick the subscriber off the network */
- gsm48_tx_mm_auth_req(lchan, auth_rand);
+ gsm48_tx_mm_auth_req(lchan, auth_rand, 0);
gsm48_tx_mm_auth_rej(lchan);
/* FIXME: close the channel early ?*/
//gsm48_send_rr_Release(lchan);
diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c
index e49f75b28..c972037be 100644
--- a/openbsc/src/transaction.c
+++ b/openbsc/src/transaction.c
@@ -119,7 +119,7 @@ int trans_assign_trans_id(struct gsm_subscriber *subscr,
struct gsm_network *net = subscr->net;
struct gsm_trans *trans;
unsigned int used_tid_bitmask = 0;
- int i;
+ int i, j, h;
if (ti_flag)
ti_flag = 0x8;
@@ -133,9 +133,14 @@ int trans_assign_trans_id(struct gsm_subscriber *subscr,
used_tid_bitmask |= (1 << trans->transaction_id);
}
+ /* find a new one, trying to go in a 'circular' pattern */
+ for (h = 6; h > 0; h--)
+ if (used_tid_bitmask & (1 << (h | ti_flag)))
+ break;
for (i = 0; i < 7; i++) {
- if ((used_tid_bitmask & (1 << (i | ti_flag))) == 0)
- return i | ti_flag;
+ j = ((h + i) % 7) | ti_flag;
+ if ((used_tid_bitmask & (1 << j)) == 0)
+ return j;
}
return -1;
diff --git a/openbsc/src/vty/command.c b/openbsc/src/vty/command.c
index 6372fb13b..5b1dcb977 100644
--- a/openbsc/src/vty/command.c
+++ b/openbsc/src/vty/command.c
@@ -49,6 +49,8 @@ Boston, MA 02111-1307, USA. */
#include <openbsc/gsm_subscriber.h>
#include <openbsc/talloc.h>
+void *tall_vty_cmd_ctx;
+
/* Command vector which includes some level of command lists. Normally
each daemon maintains each own cmdvec. */
vector cmdvec;
@@ -173,7 +175,7 @@ char *argv_concat(const char **argv, int argc, int shift)
len += strlen(argv[i]) + 1;
if (!len)
return NULL;
- p = str = _talloc_zero(tall_vty_ctx, len, "arvg_concat");
+ p = str = _talloc_zero(tall_vty_cmd_ctx, len, "arvg_concat");
for (i = shift; i < argc; i++) {
size_t arglen;
memcpy(p, argv[i], (arglen = strlen(argv[i])));
@@ -275,7 +277,7 @@ vector cmd_make_strvec(const char *string)
*cp != '\0')
cp++;
strlen = cp - start;
- token = _talloc_zero(tall_vty_ctx, strlen + 1, "make_strvec");
+ token = _talloc_zero(tall_vty_cmd_ctx, strlen + 1, "make_strvec");
memcpy(token, start, strlen);
*(token + strlen) = '\0';
vector_set(strvec, token);
@@ -331,7 +333,7 @@ static char *cmd_desc_str(const char **string)
cp++;
strlen = cp - start;
- token = _talloc_zero(tall_vty_ctx, strlen + 1, "cmd_desc_str");
+ token = _talloc_zero(tall_vty_cmd_ctx, strlen + 1, "cmd_desc_str");
memcpy(token, start, strlen);
*(token + strlen) = '\0';
@@ -402,11 +404,11 @@ static vector cmd_make_descvec(const char *string, const char *descstr)
len = cp - sp;
- token = _talloc_zero(tall_vty_ctx, len + 1, "cmd_make_descvec");
+ token = _talloc_zero(tall_vty_cmd_ctx, len + 1, "cmd_make_descvec");
memcpy(token, sp, len);
*(token + len) = '\0';
- desc = talloc_zero(tall_vty_ctx, struct desc);
+ desc = talloc_zero(tall_vty_cmd_ctx, struct desc);
desc->cmd = token;
desc->str = cmd_desc_str(&dp);
@@ -1804,7 +1806,7 @@ static char **cmd_complete_command_real(vector vline, struct vty *vty,
if ((desc = vector_slot(descvec, j))) {
if ((string = cmd_entry_function(vector_slot(vline, index), desc->cmd)))
if (cmd_unique_string (matchvec, string))
- vector_set (matchvec, talloc_strdup(tall_vty_ctx, string));
+ vector_set (matchvec, talloc_strdup(tall_vty_cmd_ctx, string));
}
}
}
@@ -1845,7 +1847,7 @@ static char **cmd_complete_command_real(vector vline, struct vty *vty,
if (len < lcd) {
char *lcdstr;
- lcdstr = _talloc_zero(tall_vty_ctx, lcd + 1,
+ lcdstr = _talloc_zero(tall_vty_cmd_ctx, lcd + 1,
"complete-lcdstr");
memcpy(lcdstr, matchvec->index[0], lcd);
lcdstr[lcd] = '\0';
@@ -2463,13 +2465,13 @@ DEFUN(config_write_file,
config_file = host.config;
config_file_sav =
- _talloc_zero(tall_vty_ctx,
+ _talloc_zero(tall_vty_cmd_ctx,
strlen(config_file) + strlen(CONF_BACKUP_EXT) + 1,
"config_file_sav");
strcpy(config_file_sav, config_file);
strcat(config_file_sav, CONF_BACKUP_EXT);
- config_file_tmp = _talloc_zero(tall_vty_ctx, strlen(config_file) + 8,
+ config_file_tmp = _talloc_zero(tall_vty_cmd_ctx, strlen(config_file) + 8,
"config_file_tmp");
sprintf(config_file_tmp, "%s.XXXXXX", config_file);
@@ -2650,7 +2652,7 @@ DEFUN(config_hostname,
if (host.name)
talloc_free(host.name);
- host.name = talloc_strdup(tall_vty_ctx, argv[0]);
+ host.name = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
return CMD_SUCCESS;
}
@@ -2685,7 +2687,7 @@ DEFUN(config_password, password_cmd,
host.password = NULL;
if (host.password_encrypt)
talloc_free(host.password_encrypt);
- host.password_encrypt = talloc_strdup(tall_vty_ctx, argv[1]);
+ host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, argv[1]);
return CMD_SUCCESS;
} else {
vty_out(vty, "Unknown encryption type.%s", VTY_NEWLINE);
@@ -2708,10 +2710,10 @@ DEFUN(config_password, password_cmd,
if (host.encrypt) {
if (host.password_encrypt)
talloc_free(host.password_encrypt);
- host.password_encrypt = talloc_strdup(tall_vty_ctx, zencrypt(argv[0]));
+ host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(argv[0]));
} else
#endif
- host.password = talloc_strdup(tall_vty_ctx, argv[0]);
+ host.password = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
return CMD_SUCCESS;
}
@@ -2744,7 +2746,7 @@ ALIAS(config_password, password_text_cmd,
if (host.enable_encrypt)
talloc_free(host.enable_encrypt);
- host.enable_encrypt = talloc_strdup(tall_vty_ctx, argv[1]);
+ host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, argv[1]);
return CMD_SUCCESS;
} else {
@@ -2769,10 +2771,10 @@ ALIAS(config_password, password_text_cmd,
if (host.encrypt) {
if (host.enable_encrypt)
talloc_free(host.enable_encrypt);
- host.enable_encrypt = talloc_strdup(tall_vty_ctx, zencrypt(argv[0]));
+ host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(argv[0]));
} else
#endif
- host.enable = talloc_strdup(tall_vty_ctx, argv[0]);
+ host.enable = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
return CMD_SUCCESS;
}
@@ -2816,12 +2818,12 @@ DEFUN(service_password_encrypt,
if (host.password) {
if (host.password_encrypt)
talloc_free(host.password_encrypt);
- host.password_encrypt = talloc_strdup(tall_vty_ctx, zencrypt(host.password));
+ host.password_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(host.password));
}
if (host.enable) {
if (host.enable_encrypt)
talloc_free(host.enable_encrypt);
- host.enable_encrypt = talloc_strdup(tall_vty_ctx, zencrypt(host.enable));
+ host.enable_encrypt = talloc_strdup(tall_vty_cmd_ctx, zencrypt(host.enable));
}
return CMD_SUCCESS;
@@ -3095,7 +3097,7 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel)
if (host.logfile)
talloc_free(host.logfile);
- host.logfile = talloc_strdup(tall_vty_ctx, fname);
+ host.logfile = talloc_strdup(tall_vty_cmd_ctx, fname);
return CMD_SUCCESS;
}
@@ -3285,7 +3287,7 @@ DEFUN(banner_motd_file,
{
if (host.motdfile)
talloc_free(host.motdfile);
- host.motdfile = talloc_strdup(tall_vty_ctx, argv[0]);
+ host.motdfile = talloc_strdup(tall_vty_cmd_ctx, argv[0]);
return CMD_SUCCESS;
}
@@ -3313,7 +3315,7 @@ DEFUN(no_banner_motd,
/* Set config filename. Called from vty.c */
void host_config_set(const char *filename)
{
- host.config = talloc_strdup(tall_vty_ctx, filename);
+ host.config = talloc_strdup(tall_vty_cmd_ctx, filename);
}
void install_default(enum node_type node)
diff --git a/openbsc/src/vty/vector.c b/openbsc/src/vty/vector.c
index 371f71d95..06e1aaa8e 100644
--- a/openbsc/src/vty/vector.c
+++ b/openbsc/src/vty/vector.c
@@ -27,10 +27,12 @@
#include <openbsc/talloc.h>
#include <memory.h>
+void *tall_vty_vec_ctx;
+
/* Initialize vector : allocate memory and return vector. */
vector vector_init(unsigned int size)
{
- vector v = talloc_zero(tall_vty_ctx, struct _vector);
+ vector v = talloc_zero(tall_vty_vec_ctx, struct _vector);
if (!v)
return NULL;
@@ -40,7 +42,7 @@ vector vector_init(unsigned int size)
v->alloced = size;
v->active = 0;
- v->index = _talloc_zero(tall_vty_ctx, sizeof(void *) * size,
+ v->index = _talloc_zero(tall_vty_vec_ctx, sizeof(void *) * size,
"vector_init:index");
if (!v->index) {
talloc_free(v);
@@ -68,7 +70,7 @@ void vector_free(vector v)
vector vector_copy(vector v)
{
unsigned int size;
- vector new = talloc_zero(tall_vty_ctx, struct _vector);
+ vector new = talloc_zero(tall_vty_vec_ctx, struct _vector);
if (!new)
return NULL;
@@ -76,7 +78,7 @@ vector vector_copy(vector v)
new->alloced = v->alloced;
size = sizeof(void *) * (v->alloced);
- new->index = _talloc_zero(tall_vty_ctx, size, "vector_copy:index");
+ new->index = _talloc_zero(tall_vty_vec_ctx, size, "vector_copy:index");
if (!new->index) {
talloc_free(new);
return NULL;
@@ -92,7 +94,7 @@ void vector_ensure(vector v, unsigned int num)
if (v->alloced > num)
return;
- v->index = talloc_realloc_size(tall_vty_ctx, v->index,
+ v->index = talloc_realloc_size(tall_vty_vec_ctx, v->index,
sizeof(void *) * (v->alloced * 2));
memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced);
v->alloced *= 2;
diff --git a/openbsc/src/vty/vty.c b/openbsc/src/vty/vty.c
index 788c7fd6f..2339bbd4b 100644
--- a/openbsc/src/vty/vty.c
+++ b/openbsc/src/vty/vty.c
@@ -1633,6 +1633,8 @@ extern void *tall_bsc_ctx;
void vty_init()
{
tall_vty_ctx = talloc_named_const(NULL, 0, "vty");
+ tall_vty_vec_ctx = talloc_named_const(tall_vty_ctx, 0, "vty_vector");
+ tall_vty_cmd_ctx = talloc_named_const(tall_vty_ctx, 0, "vty_command");
/* For further configuration read, preserve current directory. */
vty_save_cwd();
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index dfba6810f..6ff586191 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -33,8 +33,11 @@
#include <openbsc/e1_input.h>
#include <openbsc/abis_nm.h>
#include <openbsc/gsm_utils.h>
+#include <openbsc/chan_alloc.h>
+#include <openbsc/meas_rep.h>
#include <openbsc/db.h>
#include <openbsc/talloc.h>
+#include <openbsc/telnet_interface.h>
static struct gsm_network *gsmnet;
@@ -74,8 +77,30 @@ static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
nm_avail_name(nms->availability), VTY_NEWLINE);
}
+static void dump_pchan_load_vty(struct vty *vty, char *prefix,
+ const struct pchan_load *pl)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pl->pchan); i++) {
+ const struct load_counter *lc = &pl->pchan[i];
+ unsigned int percent;
+
+ if (lc->total == 0)
+ continue;
+
+ percent = (lc->used * 100) / lc->total;
+
+ vty_out(vty, "%s%20s: %3u%% (%u/%u)%s", prefix,
+ gsm_pchan_name(i), percent, lc->used, lc->total,
+ VTY_NEWLINE);
+ }
+}
+
static void net_dump_vty(struct vty *vty, struct gsm_network *net)
{
+ struct pchan_load pl;
+
vty_out(vty, "BSC is on Country Code %u, Network Code %u "
"and has %u BTS%s", net->country_code, net->network_code,
net->num_bts, VTY_NEWLINE);
@@ -97,6 +122,9 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
VTY_NEWLINE);
vty_out(vty, " Handover: %s%s", net->handover.active ? "On" : "Off",
VTY_NEWLINE);
+ network_chan_load(&pl, net);
+ vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE);
+ dump_pchan_load_vty(vty, " ", &pl);
}
DEFUN(show_net, show_net_cmd, "show network",
@@ -128,6 +156,8 @@ static void e1isl_dump_vty(struct vty *vty, struct e1inp_sign_link *e1l)
static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
{
+ struct pchan_load pl;
+
vty_out(vty, "BTS %u is of %s type in band %s, has CI %u LAC %u, "
"BSIC %u, TSC %u and %u TRX%s",
bts->nr, btstype2str(bts->type), gsm_band_name(bts->band),
@@ -140,6 +170,11 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
VTY_NEWLINE);
vty_out(vty, "Cell Reselection Hysteresis: %u dBm%s",
bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE);
+ vty_out(vty, "RACH TX-Integer: %u%s", bts->si_common.rach_control.tx_integer,
+ VTY_NEWLINE);
+ vty_out(vty, "RACH Max transmissions: %u%s",
+ rach_max_trans_raw2val(bts->si_common.rach_control.max_trans),
+ VTY_NEWLINE);
if (bts->si_common.rach_control.cell_bar)
vty_out(vty, " CELL IS BARRED%s", VTY_NEWLINE);
if (is_ipaccess_bts(bts))
@@ -157,6 +192,10 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
e1isl_dump_vty(vty, bts->oml_link);
}
/* FIXME: oml_link, chan_desc */
+ memset(&pl, 0, sizeof(pl));
+ bts_chan_load(&pl, bts);
+ vty_out(vty, " Current Channel Load:%s", VTY_NEWLINE);
+ dump_pchan_load_vty(vty, " ", &pl);
}
DEFUN(show_bts, show_bts_cmd, "show bts [number]",
@@ -227,6 +266,7 @@ static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
vty_out(vty, " arfcn %u%s", trx->arfcn, VTY_NEWLINE);
+ vty_out(vty, " nominal power %u%s", trx->nominal_power, VTY_NEWLINE);
vty_out(vty, " max_power_red %u%s", trx->max_power_red, VTY_NEWLINE);
config_write_e1_link(vty, &trx->rsl_e1_link, " rsl ");
vty_out(vty, " rsl e1 tei %u%s", trx->rsl_tei, VTY_NEWLINE);
@@ -259,6 +299,11 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " channel allocator %s%s",
bts->chan_alloc_reverse ? "descending" : "ascending",
VTY_NEWLINE);
+ vty_out(vty, " rach tx integer %u%s",
+ bts->si_common.rach_control.tx_integer, VTY_NEWLINE);
+ vty_out(vty, " rach max transmission %u%s",
+ rach_max_trans_raw2val(bts->si_common.rach_control.max_trans),
+ VTY_NEWLINE);
if (bts->si_common.rach_control.cell_bar)
vty_out(vty, " cell barred 1%s", VTY_NEWLINE);
if (is_ipaccess_bts(bts)) {
@@ -474,8 +519,12 @@ DEFUN(show_ts,
return CMD_SUCCESS;
}
-void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr)
+static void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr)
{
+ int rc;
+ struct gsm_auth_info ainfo;
+ struct gsm_auth_tuple atuple;
+
vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
subscr->authorized, VTY_NEWLINE);
if (subscr->name)
@@ -488,16 +537,54 @@ void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr)
if (subscr->tmsi != GSM_RESERVED_TMSI)
vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
VTY_NEWLINE);
+
vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
}
+static void meas_rep_dump_uni_vty(struct vty *vty,
+ struct gsm_meas_rep_unidir *mru,
+ const char *prefix,
+ const char *dir)
+{
+ vty_out(vty, "%s RXL-FULL-%s: %4d dBm, RXL-SUB-%s: %4d dBm ",
+ prefix, dir, rxlev2dbm(mru->full.rx_lev),
+ dir, rxlev2dbm(mru->sub.rx_lev));
+ vty_out(vty, "RXQ-FULL-%s: %d, RXQ-SUB-%s: %d%s",
+ dir, mru->full.rx_qual, dir, mru->sub.rx_qual,
+ VTY_NEWLINE);
+}
+
+static void meas_rep_dump_vty(struct vty *vty, struct gsm_meas_rep *mr,
+ const char *prefix)
+{
+ vty_out(vty, "%sMeasurement Report:%s", prefix, VTY_NEWLINE);
+ vty_out(vty, "%s Flags: %s%s%s%s%s", prefix,
+ mr->flags & MEAS_REP_F_UL_DTX ? "DTXu " : "",
+ mr->flags & MEAS_REP_F_DL_DTX ? "DTXd " : "",
+ mr->flags & MEAS_REP_F_FPC ? "FPC " : "",
+ mr->flags & MEAS_REP_F_DL_VALID ? " " : "DLinval ",
+ VTY_NEWLINE);
+ if (mr->flags & MEAS_REP_F_MS_TO)
+ vty_out(vty, "%s MS Timing Offset: %u%s", prefix,
+ mr->ms_timing_offset, VTY_NEWLINE);
+ if (mr->flags & MEAS_REP_F_MS_L1)
+ vty_out(vty, "%s L1 MS Power: %u dBm, Timing Advance: %u%s",
+ prefix, mr->ms_l1.pwr, mr->ms_l1.ta, VTY_NEWLINE);
+ if (mr->flags & MEAS_REP_F_DL_VALID)
+ meas_rep_dump_uni_vty(vty, &mr->dl, prefix, "dl");
+ meas_rep_dump_uni_vty(vty, &mr->ul, prefix, "ul");
+}
+
static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan)
{
+ int idx;
+
vty_out(vty, "Lchan %u in Timeslot %u of TRX %u in BTS %u, Type %s%s",
lchan->nr, lchan->ts->nr, lchan->ts->trx->nr,
- lchan->ts->trx->bts->nr, gsm_lchan_name(lchan->type),
+ lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type),
VTY_NEWLINE);
- vty_out(vty, " Use Count: %u%s", lchan->use_count, VTY_NEWLINE);
+ vty_out(vty, " Use Count: %u, State: %s%s", lchan->use_count,
+ gsm_lchans_name(lchan->state), VTY_NEWLINE);
vty_out(vty, " BS Power: %u dBm, MS Power: %u dBm%s",
lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red
- lchan->bs_power*2,
@@ -516,6 +603,11 @@ static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan)
lchan->abis_ip.rtp_payload2, lchan->abis_ip.conn_id,
VTY_NEWLINE);
}
+
+ /* we want to report the last measurement report */
+ idx = calc_initial_idx(ARRAY_SIZE(lchan->meas_rep),
+ lchan->meas_rep_idx, 1);
+ meas_rep_dump_vty(vty, &lchan->meas_rep[idx], " ");
}
#if 0
@@ -768,6 +860,244 @@ DEFUN(show_paging,
return CMD_SUCCESS;
}
+static void _vty_output(struct debug_target *tgt, const char *line)
+{
+ struct vty *vty = tgt->tgt_vty.vty;
+ vty_out(vty, "%s", line);
+ /* This is an ugly hack, but there is no easy way... */
+ if (strchr(line, '\n'))
+ vty_out(vty, "\r");
+}
+
+struct debug_target *debug_target_create_vty(struct vty *vty)
+{
+ struct debug_target *target;
+
+ target = debug_target_create();
+ if (!target)
+ return NULL;
+
+ target->tgt_vty.vty = vty;
+ target->output = _vty_output;
+ return target;
+}
+
+DEFUN(enable_logging,
+ enable_logging_cmd,
+ "logging enable",
+ "Enables logging to this vty\n")
+{
+ struct telnet_connection *conn;
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (conn->dbg) {
+ vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ conn->dbg = debug_target_create_vty(vty);
+ if (!conn->dbg)
+ return CMD_WARNING;
+
+ debug_add_target(conn->dbg);
+ return CMD_SUCCESS;
+}
+
+DEFUN(logging_fltr_imsi,
+ logging_fltr_imsi_cmd,
+ "logging filter imsi IMSI",
+ "Print all messages related to a IMSI\n")
+{
+ struct telnet_connection *conn;
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ debug_set_imsi_filter(conn->dbg, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(logging_fltr_all,
+ logging_fltr_all_cmd,
+ "logging filter all <0-1>",
+ "Print all messages to the console\n")
+{
+ struct telnet_connection *conn;
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ debug_set_all_filter(conn->dbg, atoi(argv[0]));
+ return CMD_SUCCESS;
+}
+
+DEFUN(logging_use_clr,
+ logging_use_clr_cmd,
+ "logging color <0-1>",
+ "Use color for printing messages\n")
+{
+ struct telnet_connection *conn;
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ debug_set_use_color(conn->dbg, atoi(argv[0]));
+ return CMD_SUCCESS;
+}
+
+DEFUN(logging_prnt_timestamp,
+ logging_prnt_timestamp_cmd,
+ "logging timestamp <0-1>",
+ "Print the timestamp of each message\n")
+{
+ struct telnet_connection *conn;
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ debug_set_print_timestamp(conn->dbg, atoi(argv[0]));
+ return CMD_SUCCESS;
+}
+
+/* FIXME: those have to be kept in sync with the log levels and categories */
+#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref)"
+#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)"
+DEFUN(logging_level,
+ logging_level_cmd,
+ "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS,
+ "Set the log level for a specified category\n")
+{
+ struct telnet_connection *conn;
+ int category = debug_parse_category(argv[0]);
+ int level = debug_parse_level(argv[1]);
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (category < 0) {
+ vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (level < 0) {
+ vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ conn->dbg->categories[category].enabled = 1;
+ conn->dbg->categories[category].loglevel = level;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(logging_set_category_mask,
+ logging_set_category_mask_cmd,
+ "logging set debug mask MASK",
+ "Decide which categories to output.\n")
+{
+ struct telnet_connection *conn;
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ debug_parse_category_mask(conn->dbg, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(logging_set_log_level,
+ logging_set_log_level_cmd,
+ "logging set log level <0-8>",
+ "Set the global log level. The value 0 implies no filtering.\n")
+{
+ struct telnet_connection *conn;
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ debug_set_log_level(conn->dbg, atoi(argv[0]));
+ return CMD_SUCCESS;
+}
+
+DEFUN(diable_logging,
+ disable_logging_cmd,
+ "logging disable",
+ "Disables logging to this vty\n")
+{
+ struct telnet_connection *conn;
+
+ conn = (struct telnet_connection *) vty->priv;
+ if (!conn->dbg) {
+ vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ debug_del_target(conn->dbg);
+ talloc_free(conn->dbg);
+ conn->dbg = NULL;
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_stats,
+ show_stats_cmd,
+ "show statistics",
+ SHOW_STR "Display network statistics\n")
+{
+ struct gsm_network *net = gsmnet;
+
+ vty_out(vty, "Channel Requests : %lu total, %lu no channel%s",
+ counter_get(net->stats.chreq.total),
+ counter_get(net->stats.chreq.no_channel), VTY_NEWLINE);
+ vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
+ counter_get(net->stats.loc_upd_type.attach),
+ counter_get(net->stats.loc_upd_type.normal),
+ counter_get(net->stats.loc_upd_type.periodic), VTY_NEWLINE);
+ vty_out(vty, "IMSI Detach Indications : %lu%s",
+ counter_get(net->stats.loc_upd_type.detach), VTY_NEWLINE);
+ vty_out(vty, "Location Update Response: %lu accept, %lu reject%s",
+ counter_get(net->stats.loc_upd_resp.accept),
+ counter_get(net->stats.loc_upd_resp.reject), VTY_NEWLINE);
+ vty_out(vty, "Paging : %lu attempted, %lu complete, %lu expired%s",
+ counter_get(net->stats.paging.attempted),
+ counter_get(net->stats.paging.completed),
+ counter_get(net->stats.paging.expired), VTY_NEWLINE);
+ vty_out(vty, "Handover : %lu attempted, %lu no_channel, %lu timeout, "
+ "%lu completed, %lu failed%s",
+ counter_get(net->stats.handover.attempted),
+ counter_get(net->stats.handover.no_channel),
+ counter_get(net->stats.handover.timeout),
+ counter_get(net->stats.handover.completed),
+ counter_get(net->stats.handover.failed), VTY_NEWLINE);
+ vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
+ counter_get(net->stats.sms.submitted),
+ counter_get(net->stats.sms.no_receiver), VTY_NEWLINE);
+ vty_out(vty, "SMS MT : %lu delivered, %lu no memory, %lu other error%s",
+ counter_get(net->stats.sms.delivered),
+ counter_get(net->stats.sms.rp_err_mem),
+ counter_get(net->stats.sms.rp_err_other), VTY_NEWLINE);
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_net,
cfg_net_cmd,
"network",
@@ -948,11 +1278,11 @@ DEFUN(cfg_net_ho_max_distance, cfg_net_ho_max_distance_cmd,
return CMD_SUCCESS;
}
-#define DECLARE_TIMER(number) \
+#define DECLARE_TIMER(number, doc) \
DEFUN(cfg_net_T##number, \
cfg_net_T##number##_cmd, \
"timer t" #number " <0-65535>", \
- "Set the T" #number " value.") \
+ doc) \
{ \
int value = atoi(argv[0]); \
\
@@ -966,17 +1296,17 @@ DEFUN(cfg_net_ho_max_distance, cfg_net_ho_max_distance_cmd,
return CMD_SUCCESS; \
}
-DECLARE_TIMER(3101)
-DECLARE_TIMER(3103)
-DECLARE_TIMER(3105)
-DECLARE_TIMER(3107)
-DECLARE_TIMER(3109)
-DECLARE_TIMER(3111)
-DECLARE_TIMER(3113)
-DECLARE_TIMER(3115)
-DECLARE_TIMER(3117)
-DECLARE_TIMER(3119)
-DECLARE_TIMER(3141)
+DECLARE_TIMER(3101, "Set the timeout value for IMMEDIATE ASSIGNMENT.")
+DECLARE_TIMER(3103, "Set the timeout value for HANDOVER.")
+DECLARE_TIMER(3105, "Currently not used.")
+DECLARE_TIMER(3107, "Currently not used.")
+DECLARE_TIMER(3109, "Currently not used.")
+DECLARE_TIMER(3111, "Currently not used.")
+DECLARE_TIMER(3113, "Set the time to try paging a subscriber.")
+DECLARE_TIMER(3115, "Currently not used.")
+DECLARE_TIMER(3117, "Currently not used.")
+DECLARE_TIMER(3119, "Currently not used.")
+DECLARE_TIMER(3141, "Currently not used.")
/* per-BTS configuration */
@@ -1015,12 +1345,7 @@ DEFUN(cfg_bts_type,
{
struct gsm_bts *bts = vty->index;
- bts->type = parse_btstype(argv[0]);
-
- if (is_ipaccess_bts(bts)) {
- /* Set the default OML Stream ID to 0xff */
- bts->oml_tei = 0xff;
- }
+ gsm_set_bts_type(bts, parse_btstype(argv[0]));
return CMD_SUCCESS;
}
@@ -1203,6 +1528,26 @@ DEFUN(cfg_bts_challoc, cfg_bts_challoc_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_bts_rach_tx_integer,
+ cfg_bts_rach_tx_integer_cmd,
+ "rach tx integer <0-15>",
+ "Set the raw tx integer value in RACH Control parameters IE")
+{
+ struct gsm_bts *bts = vty->index;
+ bts->si_common.rach_control.tx_integer = atoi(argv[0]) & 0xf;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_rach_max_trans,
+ cfg_bts_rach_max_trans_cmd,
+ "rach max transmission (1|2|4|7)",
+ "Set the maximum number of RACH burst transmissions")
+{
+ struct gsm_bts *bts = vty->index;
+ bts->si_common.rach_control.max_trans = rach_max_trans_val2raw(atoi(argv[0]));
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_bts_cell_barred, cfg_bts_cell_barred_cmd,
"cell barred (0|1)",
"Should this cell be barred from access?")
@@ -1341,6 +1686,18 @@ DEFUN(cfg_trx_arfcn,
return CMD_SUCCESS;
}
+DEFUN(cfg_trx_nominal_power,
+ cfg_trx_nominal_power_cmd,
+ "nominal power <0-100>",
+ "Nominal TRX RF Power in dB\n")
+{
+ struct gsm_bts_trx *trx = vty->index;
+
+ trx->nominal_power = atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_trx_max_power_red,
cfg_trx_max_power_red_cmd,
"max_power_red <0-100>",
@@ -1476,6 +1833,17 @@ int bsc_vty_init(struct gsm_network *net)
install_element(VIEW_NODE, &show_e1ts_cmd);
install_element(VIEW_NODE, &show_paging_cmd);
+ install_element(VIEW_NODE, &show_stats_cmd);
+
+ install_element(VIEW_NODE, &enable_logging_cmd);
+ install_element(VIEW_NODE, &disable_logging_cmd);
+ install_element(VIEW_NODE, &logging_fltr_imsi_cmd);
+ install_element(VIEW_NODE, &logging_fltr_all_cmd);
+ install_element(VIEW_NODE, &logging_use_clr_cmd);
+ install_element(VIEW_NODE, &logging_prnt_timestamp_cmd);
+ install_element(VIEW_NODE, &logging_set_category_mask_cmd);
+ install_element(VIEW_NODE, &logging_level_cmd);
+ install_element(VIEW_NODE, &logging_set_log_level_cmd);
install_element(CONFIG_NODE, &cfg_net_cmd);
install_node(&net_node, config_write_net);
@@ -1523,6 +1891,8 @@ int bsc_vty_init(struct gsm_network *net)
install_element(BTS_NODE, &cfg_bts_oml_e1_cmd);
install_element(BTS_NODE, &cfg_bts_oml_e1_tei_cmd);
install_element(BTS_NODE, &cfg_bts_challoc_cmd);
+ install_element(BTS_NODE, &cfg_bts_rach_tx_integer_cmd);
+ install_element(BTS_NODE, &cfg_bts_rach_max_trans_cmd);
install_element(BTS_NODE, &cfg_bts_cell_barred_cmd);
install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
@@ -1536,6 +1906,7 @@ int bsc_vty_init(struct gsm_network *net)
install_node(&trx_node, dummy_config_write);
install_default(TRX_NODE);
install_element(TRX_NODE, &cfg_trx_arfcn_cmd);
+ install_element(TRX_NODE, &cfg_trx_nominal_power_cmd);
install_element(TRX_NODE, &cfg_trx_max_power_red_cmd);
install_element(TRX_NODE, &cfg_trx_rsl_e1_cmd);
install_element(TRX_NODE, &cfg_trx_rsl_e1_tei_cmd);
diff --git a/openbsc/src/vty_interface_layer3.c b/openbsc/src/vty_interface_layer3.c
index 4cc08c2da..f2b572895 100644
--- a/openbsc/src/vty_interface_layer3.c
+++ b/openbsc/src/vty_interface_layer3.c
@@ -40,9 +40,7 @@
#include <openbsc/db.h>
#include <openbsc/talloc.h>
#include <openbsc/signal.h>
-
-/* forward declarations */
-void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr);
+#include <openbsc/debug.h>
static struct gsm_network *gsmnet;
@@ -74,6 +72,33 @@ static struct buffer *argv_to_buffer(int argc, const char *argv[], int base)
return b;
}
+static int hexparse(const char *str, u_int8_t *b, int max_len)
+
+{
+ int i, l, v;
+
+ l = strlen(str);
+ if ((l&1) || ((l>>1) > max_len))
+ return -1;
+
+ memset(b, 0x00, max_len);
+
+ for (i=0; i<l; i++) {
+ char c = str[i];
+ if (c >= '0' && c <= '9')
+ v = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ v = 10 + (c - 'a');
+ else if (c >= 'A' && c <= 'F')
+ v = 10 + (c - 'a');
+ else
+ return -1;
+ b[i>>1] |= v << (i&1 ? 0 : 4);
+ }
+
+ return i>>1;
+}
+
/* per-subscriber configuration */
DEFUN(cfg_subscr,
cfg_subscr_cmd,
@@ -97,6 +122,55 @@ DEFUN(cfg_subscr,
return CMD_SUCCESS;
}
+static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr)
+{
+ int rc;
+ struct gsm_auth_info ainfo;
+ struct gsm_auth_tuple atuple;
+
+ vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
+ subscr->authorized, VTY_NEWLINE);
+ if (subscr->name)
+ vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE);
+ if (subscr->extension)
+ vty_out(vty, " Extension: %s%s", subscr->extension,
+ VTY_NEWLINE);
+ if (subscr->imsi)
+ vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
+ if (subscr->tmsi != GSM_RESERVED_TMSI)
+ vty_out(vty, " TMSI: %08X%s", subscr->tmsi,
+ VTY_NEWLINE);
+
+ rc = get_authinfo_by_subscr(&ainfo, subscr);
+ if (!rc) {
+ vty_out(vty, " A3A8 algorithm id: %d%s",
+ ainfo.auth_algo, VTY_NEWLINE);
+ vty_out(vty, " A3A8 Ki: %s%s",
+ hexdump(ainfo.a3a8_ki, ainfo.a3a8_ki_len),
+ VTY_NEWLINE);
+ }
+
+ rc = get_authtuple_by_subscr(&atuple, subscr);
+ if (!rc) {
+ vty_out(vty, " A3A8 last tuple (used %d times):%s",
+ atuple.use_count, VTY_NEWLINE);
+ vty_out(vty, " seq # : %d%s",
+ atuple.key_seq, VTY_NEWLINE);
+ vty_out(vty, " RAND : %s%s",
+ hexdump(atuple.rand, sizeof(atuple.rand)),
+ VTY_NEWLINE);
+ vty_out(vty, " SRES : %s%s",
+ hexdump(atuple.sres, sizeof(atuple.sres)),
+ VTY_NEWLINE);
+ vty_out(vty, " Kc : %s%s",
+ hexdump(atuple.kc, sizeof(atuple.kc)),
+ VTY_NEWLINE);
+ }
+
+ vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
+}
+
+
/* Subscriber */
DEFUN(show_subscr,
show_subscr_cmd,
@@ -114,7 +188,7 @@ DEFUN(show_subscr,
VTY_NEWLINE);
return CMD_WARNING;
}
- subscr_dump_vty(vty, subscr);
+ subscr_dump_full_vty(vty, subscr);
subscr_put(subscr);
return CMD_SUCCESS;
@@ -135,7 +209,7 @@ DEFUN(show_subscr_cache,
llist_for_each_entry(subscr, &active_subscribers, entry) {
vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
- subscr_dump_vty(vty, subscr);
+ subscr_dump_full_vty(vty, subscr);
}
return CMD_SUCCESS;
@@ -143,23 +217,20 @@ DEFUN(show_subscr_cache,
DEFUN(sms_send_pend,
sms_send_pend_cmd,
- "sms send pending MIN_ID",
- "Send all pending SMS starting from MIN_ID")
+ "sms send pending",
+ "Send all pending SMS")
{
struct gsm_sms *sms;
- int id = atoi(argv[0]);
+ int id = 0;
while (1) {
- sms = db_sms_get_unsent(gsmnet, id++);
+ sms = db_sms_get_unsent_by_subscr(gsmnet, id);
if (!sms)
- return CMD_WARNING;
-
- if (!sms->receiver) {
- sms_free(sms);
- continue;
- }
+ break;
gsm411_send_sms_subscr(sms->receiver, sms);
+
+ id = sms->receiver->id + 1;
}
return CMD_SUCCESS;
@@ -269,10 +340,46 @@ DEFUN(subscriber_silent_sms,
return rc;
}
-DEFUN(subscriber_silent_call,
- subscriber_silent_call_cmd,
- "subscriber " SUBSCR_TYPES " EXTEN silent call (start|stop)",
- "Send a silent call to a subscriber")
+DEFUN(subscriber_silent_call_start,
+ subscriber_silent_call_start_cmd,
+ "subscriber " SUBSCR_TYPES " EXTEN silent call start (any|tch/f|tch/any|sdcch)",
+ "Start a silent call to a subscriber")
+{
+ struct gsm_subscriber *subscr = get_subscr_by_argv(argv[0], argv[1]);
+ int rc, type;
+
+ if (!subscr) {
+ vty_out(vty, "%% No subscriber found for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(argv[2], "tch/f"))
+ type = RSL_CHANNEED_TCH_F;
+ else if (!strcmp(argv[2], "tch/any"))
+ type = RSL_CHANNEED_TCH_ForH;
+ else if (!strcmp(argv[2], "sdcch"))
+ type = RSL_CHANNEED_SDCCH;
+ else
+ type = RSL_CHANNEED_ANY; /* Defaults to ANY */
+
+ rc = gsm_silent_call_start(subscr, vty, type);
+ if (rc <= 0) {
+ vty_out(vty, "%% Subscriber not attached%s",
+ VTY_NEWLINE);
+ subscr_put(subscr);
+ return CMD_WARNING;
+ }
+
+ subscr_put(subscr);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(subscriber_silent_call_stop,
+ subscriber_silent_call_stop_cmd,
+ "subscriber " SUBSCR_TYPES " EXTEN silent call stop",
+ "Stop a silent call to a subscriber")
{
struct gsm_subscriber *subscr = get_subscr_by_argv(argv[0], argv[1]);
int rc;
@@ -283,17 +390,10 @@ DEFUN(subscriber_silent_call,
return CMD_WARNING;
}
- if (!strcmp(argv[2], "start")) {
- rc = gsm_silent_call_start(subscr, vty);
- if (rc <= 0) {
- vty_out(vty, "%% Subscriber not attached%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- } else {
- rc = gsm_silent_call_stop(subscr);
- if (rc < 0)
- return CMD_WARNING;
+ rc = gsm_silent_call_stop(subscr);
+ if (rc < 0) {
+ subscr_put(subscr);
+ return CMD_WARNING;
}
subscr_put(subscr);
@@ -349,6 +449,40 @@ DEFUN(cfg_subscr_authorized,
return CMD_SUCCESS;
}
+#define A3A8_ALG_TYPES "(none|comp128v1)"
+
+DEFUN(cfg_subscr_a3a8,
+ cfg_subscr_a3a8_cmd,
+ "a3a8 " A3A8_ALG_TYPES " [KI]",
+ "Set a3a8 parameters for the subscriber")
+{
+ struct gsm_subscriber *subscr = vty->index;
+ const char *alg_str = argv[0];
+ const char *ki_str = argv[1];
+ struct gsm_auth_info ainfo;
+ int rc;
+
+ if (!strcasecmp(alg_str, "none")) {
+ /* Just erase */
+ rc = set_authinfo_for_subscr(NULL, subscr);
+ } else if (!strcasecmp(alg_str, "comp128v1")) {
+ /* Parse hex string Ki */
+ rc = hexparse(ki_str, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki));
+ if (rc != 16)
+ return CMD_WARNING;
+
+ /* Set the infos */
+ ainfo.auth_algo = AUTH_ALGO_COMP128v1;
+ ainfo.a3a8_ki_len = rc;
+ rc = set_authinfo_for_subscr(&ainfo, subscr);
+ } else {
+ /* Unknown method */
+ return CMD_WARNING;
+ }
+
+ return rc ? CMD_WARNING : CMD_SUCCESS;
+}
+
static int scall_cbfn(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
@@ -381,7 +515,8 @@ int bsc_vty_init_extra(struct gsm_network *net)
install_element(VIEW_NODE, &subscriber_send_sms_cmd);
install_element(VIEW_NODE, &subscriber_silent_sms_cmd);
- install_element(VIEW_NODE, &subscriber_silent_call_cmd);
+ install_element(VIEW_NODE, &subscriber_silent_call_start_cmd);
+ install_element(VIEW_NODE, &subscriber_silent_call_stop_cmd);
install_element(CONFIG_NODE, &cfg_subscr_cmd);
install_node(&subscr_node, dummy_config_write);
@@ -390,6 +525,7 @@ int bsc_vty_init_extra(struct gsm_network *net)
install_element(SUBSCR_NODE, &cfg_subscr_name_cmd);
install_element(SUBSCR_NODE, &cfg_subscr_extension_cmd);
install_element(SUBSCR_NODE, &cfg_subscr_authorized_cmd);
+ install_element(SUBSCR_NODE, &cfg_subscr_a3a8_cmd);
return 0;
}
diff --git a/openbsc/tests/channel/Makefile.am b/openbsc/tests/channel/Makefile.am
index 50fadc582..564cbafe2 100644
--- a/openbsc/tests/channel/Makefile.am
+++ b/openbsc/tests/channel/Makefile.am
@@ -12,6 +12,7 @@ channel_test_SOURCES = channel_test.c \
$(top_srcdir)/src/select.c \
$(top_srcdir)/src/talloc.c \
$(top_srcdir)/src/gsm_data.c \
- $(top_srcdir)/src/signal.c
+ $(top_srcdir)/src/signal.c \
+ $(top_srcdir)/src/statistics.c
channel_test_LDADD = -ldl -ldbi
diff --git a/openbsc/tests/debug/Makefile.am b/openbsc/tests/debug/Makefile.am
index 0cdf46ad5..62c906e72 100644
--- a/openbsc/tests/debug/Makefile.am
+++ b/openbsc/tests/debug/Makefile.am
@@ -1,4 +1,4 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
noinst_PROGRAMS = debug_test
-debug_test_SOURCES = debug_test.c $(top_srcdir)/src/debug.c
+debug_test_SOURCES = debug_test.c $(top_srcdir)/src/debug.c $(top_srcdir)/src/talloc.c
diff --git a/openbsc/tests/debug/debug_test.c b/openbsc/tests/debug/debug_test.c
index 77ac01532..0f0c284ab 100644
--- a/openbsc/tests/debug/debug_test.c
+++ b/openbsc/tests/debug/debug_test.c
@@ -1,6 +1,6 @@
/* simple test for the debug interface */
/*
- * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -24,11 +24,18 @@
int main(int argc, char** argv)
{
- debug_parse_category_mask("DRLL");
- DEBUGP(DCC, "You should not see this\n");
+ struct debug_target *stderr_target;
- debug_parse_category_mask("DRLL:DCC");
- DEBUGP(DRLL, "You should see this\n");
- DEBUGP(DCC, "You should see this\n");
- DEBUGP(DMM, "You should not see this\n");
+ debug_init();
+ stderr_target = debug_target_create_stderr();
+ debug_add_target(stderr_target);
+ debug_set_all_filter(stderr_target, 1);
+
+ debug_parse_category_mask(stderr_target, "DRLL");
+ DEBUGP(DCC, "You should not see this\n");
+
+ debug_parse_category_mask(stderr_target, "DRLL:DCC");
+ DEBUGP(DRLL, "You should see this\n");
+ DEBUGP(DCC, "You should see this\n");
+ DEBUGP(DMM, "You should not see this\n");
}
diff --git a/openbsc/tests/sccp/sccp_test.c b/openbsc/tests/sccp/sccp_test.c
index bd28ed179..37615e0e2 100644
--- a/openbsc/tests/sccp/sccp_test.c
+++ b/openbsc/tests/sccp/sccp_test.c
@@ -722,3 +722,5 @@ int main(int argc, char **argv)
test_sccp_system_crash();
return 0;
}
+
+void db_store_counter() {}
diff --git a/openbsc/tools/hlrstat.pl b/openbsc/tools/hlrstat.pl
index a3fd2b81e..668fc9a4a 100755
--- a/openbsc/tools/hlrstat.pl
+++ b/openbsc/tools/hlrstat.pl
@@ -8,6 +8,18 @@ my $dbh = DBI->connect("dbi:SQLite:dbname=hlr.sqlite3","","");
my %mcc_names;
my %mcc_mnc_names;
+sub get_mcc_mnc_name($)
+{
+ my $mcc_mnc = shift;
+ my $ret = $mcc_mnc;
+
+ if ($mcc_mnc_names{$mcc_mnc} ne '') {
+ $ret = $mcc_mnc_names{$mcc_mnc};
+ }
+
+ return $ret;
+}
+
sub read_networks($)
{
my $filename = shift;
@@ -37,6 +49,7 @@ read_networks("networks.tab");
my %oper_count;
my %country_count;
+#my $sth = $dbh->prepare("SELECT imsi FROM subscriber where authorized=1");
my $sth = $dbh->prepare("SELECT imsi FROM subscriber");
$sth->execute();
@@ -49,10 +62,12 @@ while (my $href = $sth->fetchrow_hashref) {
}
-foreach my $c (keys %country_count) {
+foreach my $c (sort{$country_count{$b} <=> $country_count{$a}} keys %country_count) {
printf("%s: %d\n", $mcc_names{$c}, $country_count{$c});
-}
- foreach my $k (keys %oper_count) {
- printf("\t%s: %d\n", $mcc_mnc_names{$k}, $oper_count{$k});
+
+ foreach my $k (sort{$oper_count{$b} <=> $oper_count{$a}} keys %oper_count) {
+ if ($k =~ /^$c-/) {
+ printf("\t%s: %d\n", get_mcc_mnc_name($k), $oper_count{$k});
+ }
}
-#//}
+}
diff --git a/rrlp-ephemeris/.gitignore b/rrlp-ephemeris/.gitignore
new file mode 100644
index 000000000..88b45e491
--- /dev/null
+++ b/rrlp-ephemeris/.gitignore
@@ -0,0 +1,4 @@
+asn1_gen/*
+*.o
+*.a
+rrlp-test
diff --git a/rrlp-ephemeris/COPYING b/rrlp-ephemeris/COPYING
new file mode 100644
index 000000000..8d7088e89
--- /dev/null
+++ b/rrlp-ephemeris/COPYING
@@ -0,0 +1,2 @@
+See the included gpl-2.0.txt or gpl-3.0.txt depending on your
+preferences.
diff --git a/rrlp-ephemeris/Makefile b/rrlp-ephemeris/Makefile
new file mode 100644
index 000000000..742cac7a6
--- /dev/null
+++ b/rrlp-ephemeris/Makefile
@@ -0,0 +1,44 @@
+
+ASN1C=../../../tmp/rrlp/asn1c/asn1c/asn1c
+ASN1_INCLUDE=/home/tnt/tmp/rrlp/asn1c/skeletons
+CC=gcc
+CFLAGS=-I$(ASN1_INCLUDE) -Iasn1_gen -O3 -Wall
+
+ASN1_FILES=$(wildcard asn1/*.asn)
+
+
+all: rrlp-test
+
+
+rrlp-test: libgsm-asn1.a gps.o ubx.o ubx-parse.o rrlp.o main.o
+ $(CC) -o $@ gps.o ubx.o ubx-parse.o rrlp.o main.o -L. -lgsm-asn1 -lm
+
+
+#
+# ASN1 file autogeneration (need recursive makefile call)
+#
+
+ASN1_SOURCES = $(wildcard asn1_gen/*.c)
+ASN1_OBJECTS = $(ASN1_SOURCES:.c=.o)
+
+libgsm-asn1.a: $(ASN1_FILES)
+ mkdir -p asn1_gen && \
+ cd asn1_gen && \
+ $(ASN1C) -fskeletons-copy -fnative-types -gen-PER $(addprefix ../,$^)
+ @rm asn1_gen/converter-sample.c asn1_gen/Makefile.am.sample
+ @$(MAKE) libgsm-asn1.a.submake
+
+libgsm-asn1.a.submake: $(ASN1_OBJECTS)
+ $(AR) rcs libgsm-asn1.a $^
+
+.PHONY: libgsm-asn1.a.submake
+
+
+#
+# Clean
+#
+
+clean:
+ rm -Rf asn1_gen
+ rm -f libgsm-asn1.a *.o rrlp-test
+
diff --git a/rrlp-ephemeris/asn1/MAP-BS-Code.asn b/rrlp-ephemeris/asn1/MAP-BS-Code.asn
new file mode 100644
index 000000000..1d2536676
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-BS-Code.asn
@@ -0,0 +1,131 @@
+-- $Id: MAP-BS-Code.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+-- 17.7.10 Bearer Service Codes
+
+MAP-BS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-BS-Code (20) version11 (11)}
+
+DEFINITIONS
+
+::=
+
+BEGIN
+
+BearerServiceCode ::= OCTET STRING (SIZE (1))
+ -- This type is used to represent the code identifying a single
+ -- bearer service, a group of bearer services, or all bearer
+ -- services. The services are defined in TS 3GPP TS 22.002 [3].
+ -- The internal structure is defined as follows:
+ --
+ -- plmn-specific bearer services:
+ -- bits 87654321: defined by the HPLMN operator
+
+ -- rest of bearer services:
+ -- bit 8: 0 (unused)
+ -- bits 7654321: group (bits 7654), and rate, if applicable
+ -- (bits 321)
+
+Ext-BearerServiceCode ::= OCTET STRING (SIZE (1..5))
+ -- This type is used to represent the code identifying a single
+ -- bearer service, a group of bearer services, or all bearer
+ -- services. The services are defined in TS 3GPP TS 22.002 [3].
+ -- The internal structure is defined as follows:
+ --
+ -- OCTET 1:
+ -- plmn-specific bearer services:
+ -- bits 87654321: defined by the HPLMN operator
+ --
+ -- rest of bearer services:
+ -- bit 8: 0 (unused)
+ -- bits 7654321: group (bits 7654), and rate, if applicable
+ -- (bits 321)
+
+ -- OCTETS 2-5: reserved for future use. If received the
+ -- Ext-TeleserviceCode shall be
+ -- treated according to the exception handling defined for the
+ -- operation that uses this type.
+
+
+ -- Ext-BearerServiceCode includes all values defined for BearerServiceCode.
+
+allBearerServices BearerServiceCode ::= '00000000'B
+
+allDataCDA-Services BearerServiceCode ::= '00010000'B
+dataCDA-300bps BearerServiceCode ::= '00010001'B
+dataCDA-1200bps BearerServiceCode ::= '00010010'B
+dataCDA-1200-75bps BearerServiceCode ::= '00010011'B
+dataCDA-2400bps BearerServiceCode ::= '00010100'B
+dataCDA-4800bps BearerServiceCode ::= '00010101'B
+dataCDA-9600bps BearerServiceCode ::= '00010110'B
+general-dataCDA BearerServiceCode ::= '00010111'B
+
+allDataCDS-Services BearerServiceCode ::= '00011000'B
+dataCDS-1200bps BearerServiceCode ::= '00011010'B
+dataCDS-2400bps BearerServiceCode ::= '00011100'B
+dataCDS-4800bps BearerServiceCode ::= '00011101'B
+dataCDS-9600bps BearerServiceCode ::= '00011110'B
+general-dataCDS BearerServiceCode ::= '00011111'B
+
+allPadAccessCA-Services BearerServiceCode ::= '00100000'B
+padAccessCA-300bps BearerServiceCode ::= '00100001'B
+padAccessCA-1200bps BearerServiceCode ::= '00100010'B
+padAccessCA-1200-75bps BearerServiceCode ::= '00100011'B
+padAccessCA-2400bps BearerServiceCode ::= '00100100'B
+padAccessCA-4800bps BearerServiceCode ::= '00100101'B
+padAccessCA-9600bps BearerServiceCode ::= '00100110'B
+general-padAccessCA BearerServiceCode ::= '00100111'B
+
+allDataPDS-Services BearerServiceCode ::= '00101000'B
+dataPDS-2400bps BearerServiceCode ::= '00101100'B
+dataPDS-4800bps BearerServiceCode ::= '00101101'B
+dataPDS-9600bps BearerServiceCode ::= '00101110'B
+general-dataPDS BearerServiceCode ::= '00101111'B
+
+allAlternateSpeech-DataCDA BearerServiceCode ::= '00110000'B
+
+allAlternateSpeech-DataCDS BearerServiceCode ::= '00111000'B
+
+allSpeechFollowedByDataCDA BearerServiceCode ::= '01000000'B
+
+allSpeechFollowedByDataCDS BearerServiceCode ::= '01001000'B
+
+-- The following non-hierarchical Compound Bearer Service
+-- Groups are defined in TS 3GPP TS 22.030:
+allDataCircuitAsynchronous BearerServiceCode ::= '01010000'B
+ -- covers "allDataCDA-Services", "allAlternateSpeech-DataCDA" and
+ -- "allSpeechFollowedByDataCDA"
+allAsynchronousServices BearerServiceCode ::= '01100000'B
+ -- covers "allDataCDA-Services", "allAlternateSpeech-DataCDA",
+ -- "allSpeechFollowedByDataCDA" and "allPadAccessCDA-Services"
+allDataCircuitSynchronous BearerServiceCode ::= '01011000'B
+ -- covers "allDataCDS-Services", "allAlternateSpeech-DataCDS" and
+ -- "allSpeechFollowedByDataCDS"
+allSynchronousServices BearerServiceCode ::= '01101000'B
+ -- covers "allDataCDS-Services", "allAlternateSpeech-DataCDS",
+ -- "allSpeechFollowedByDataCDS" and "allDataPDS-Services"
+--
+-- Compound Bearer Service Group Codes are only used in call
+-- independent supplementary service operations, i.e. they
+-- are not used in InsertSubscriberData or in
+-- DeleteSubscriberData messages.
+
+allPLMN-specificBS BearerServiceCode ::= '11010000'B
+plmn-specificBS-1 BearerServiceCode ::= '11010001'B
+plmn-specificBS-2 BearerServiceCode ::= '11010010'B
+plmn-specificBS-3 BearerServiceCode ::= '11010011'B
+plmn-specificBS-4 BearerServiceCode ::= '11010100'B
+plmn-specificBS-5 BearerServiceCode ::= '11010101'B
+plmn-specificBS-6 BearerServiceCode ::= '11010110'B
+plmn-specificBS-7 BearerServiceCode ::= '11010111'B
+plmn-specificBS-8 BearerServiceCode ::= '11011000'B
+plmn-specificBS-9 BearerServiceCode ::= '11011001'B
+plmn-specificBS-A BearerServiceCode ::= '11011010'B
+plmn-specificBS-B BearerServiceCode ::= '11011011'B
+plmn-specificBS-C BearerServiceCode ::= '11011100'B
+plmn-specificBS-D BearerServiceCode ::= '11011101'B
+plmn-specificBS-E BearerServiceCode ::= '11011110'B
+plmn-specificBS-F BearerServiceCode ::= '11011111'B
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-CommonDataTypes.asn b/rrlp-ephemeris/asn1/MAP-CommonDataTypes.asn
new file mode 100644
index 000000000..f3d202e35
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-CommonDataTypes.asn
@@ -0,0 +1,633 @@
+-- $Id: MAP-CommonDataTypes.asn 30470 2009-10-10 12:37:56Z krj $
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+-- 17.7.8 Common data types
+
+MAP-CommonDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
+
+DEFINITIONS
+
+IMPLICIT TAGS
+
+::=
+
+BEGIN
+
+EXPORTS
+
+ -- general data types and values
+ AddressString,
+ ISDN-AddressString,
+ maxISDN-AddressLength,
+ FTN-AddressString,
+ ISDN-SubaddressString,
+ ExternalSignalInfo,
+ Ext-ExternalSignalInfo,
+AccessNetworkSignalInfo,
+ SignalInfo,
+ maxSignalInfoLength,
+ AlertingPattern,
+ TBCD-STRING,
+
+ -- data types for numbering and identification
+ IMSI,
+ TMSI,
+ Identity,
+ SubscriberId,
+ IMEI,
+ HLR-List,
+ LMSI,
+ GlobalCellId,
+ NetworkResource,
+ AdditionalNetworkResource,
+ NAEA-PreferredCI,
+ NAEA-CIC,
+ ASCI-CallReference,
+ SubscriberIdentity,
+ PLMN-Id,
+
+ -- data types for CAMEL
+ CellGlobalIdOrServiceAreaIdOrLAI,
+ CellGlobalIdOrServiceAreaIdFixedLength,
+ LAIFixedLength,
+
+ -- data types for subscriber management
+ BasicServiceCode,
+ Ext-BasicServiceCode,
+ EMLPP-Info,
+ EMLPP-Priority,
+ MC-SS-Info,
+ MaxMC-Bearers,
+ MC-Bearers,
+ Ext-SS-Status,
+
+ -- data types for geographic location
+ AgeOfLocationInformation,
+ LCSClientExternalID,
+ LCSClientInternalID,
+ LCSServiceTypeID,
+--- WS added exports needed by gsm_map.asn (extra asn1 file to handle older prot. ver.)
+ ProtocolId,
+ LCSServiceTypeID
+;
+
+IMPORTS
+ TeleserviceCode,
+ Ext-TeleserviceCode
+FROM MAP-TS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-TS-Code (19) version11 (11)}
+
+ BearerServiceCode,
+ Ext-BearerServiceCode
+FROM MAP-BS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-BS-Code (20) version11 (11)}
+
+ SS-Code
+FROM MAP-SS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
+
+ ExtensionContainer
+FROM MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+;
+
+
+-- general data types
+
+TBCD-STRING ::= OCTET STRING
+ -- This type (Telephony Binary Coded Decimal String) is used to
+ -- represent several digits from 0 through 9, *, #, a, b, c, two
+ -- digits per octet, each digit encoded 0000 to 1001 (0 to 9),
+ -- 1010 (*), 1011 (#), 1100 (a), 1101 (b) or 1110 (c); 1111 used
+ -- as filler when there is an odd number of digits.
+
+ -- bits 8765 of octet n encoding digit 2n
+ -- bits 4321 of octet n encoding digit 2(n-1) +1
+
+AddressString ::= OCTET STRING (SIZE (1..maxAddressLength))
+ -- This type is used to represent a number for addressing
+ -- purposes. It is composed of
+ -- a) one octet for nature of address, and numbering plan
+ -- indicator.
+ -- b) digits of an address encoded as TBCD-String.
+
+ -- a) The first octet includes a one bit extension indicator, a
+ -- 3 bits nature of address indicator and a 4 bits numbering
+ -- plan indicator, encoded as follows:
+
+ -- bit 8: 1 (no extension)
+
+ -- bits 765: nature of address indicator
+ -- 000 unknown
+ -- 001 international number
+ -- 010 national significant number
+ -- 011 network specific number
+ -- 100 subscriber number
+ -- 101 reserved
+ -- 110 abbreviated number
+ -- 111 reserved for extension
+
+ -- bits 4321: numbering plan indicator
+ -- 0000 unknown
+ -- 0001 ISDN/Telephony Numbering Plan (Rec ITU-T E.164)
+ -- 0010 spare
+ -- 0011 data numbering plan (ITU-T Rec X.121)
+ -- 0100 telex numbering plan (ITU-T Rec F.69)
+ -- 0101 spare
+ -- 0110 land mobile numbering plan (ITU-T Rec E.212)
+ -- 0111 spare
+ -- 1000 national numbering plan
+ -- 1001 private numbering plan
+ -- 1111 reserved for extension
+
+ -- all other values are reserved.
+
+ -- b) The following octets representing digits of an address
+ -- encoded as a TBCD-STRING.
+
+maxAddressLength INTEGER ::= 20
+
+ISDN-AddressString ::=
+ AddressString (SIZE (1..maxISDN-AddressLength))
+ -- This type is used to represent ISDN numbers.
+
+maxISDN-AddressLength INTEGER ::= 9
+
+FTN-AddressString ::=
+ AddressString (SIZE (1..maxFTN-AddressLength))
+ -- This type is used to represent forwarded-to numbers.
+ -- If NAI = international the first digits represent the country code (CC)
+ -- and the network destination code (NDC) as for E.164.
+
+maxFTN-AddressLength INTEGER ::= 15
+
+ISDN-SubaddressString ::=
+ OCTET STRING (SIZE (1..maxISDN-SubaddressLength))
+ -- This type is used to represent ISDN subaddresses.
+ -- It is composed of
+ -- a) one octet for type of subaddress and odd/even indicator.
+ -- b) 20 octets for subaddress information.
+
+ -- a) The first octet includes a one bit extension indicator, a
+ -- 3 bits type of subaddress and a one bit odd/even indicator,
+ -- encoded as follows:
+
+ -- bit 8: 1 (no extension)
+
+ -- bits 765: type of subaddress
+ -- 000 NSAP (X.213/ISO 8348 AD2)
+ -- 010 User Specified
+ -- All other values are reserved
+
+ -- bit 4: odd/even indicator
+ -- 0 even number of address signals
+ -- 1 odd number of address signals
+ -- The odd/even indicator is used when the type of subaddress
+ -- is "user specified" and the coding is BCD.
+
+ -- bits 321: 000 (unused)
+
+ -- b) Subaddress information.
+ -- The NSAP X.213/ISO8348AD2 address shall be formatted as specified
+ -- by octet 4 which contains the Authority and Format Identifier
+ -- (AFI). The encoding is made according to the "preferred binary
+ -- encoding" as defined in X.213/ISO834AD2. For the definition
+ -- of this type of subaddress, see ITU-T Rec I.334.
+
+ -- For User-specific subaddress, this field is encoded according
+ -- to the user specification, subject to a maximum length of 20
+ -- octets. When interworking with X.25 networks BCD coding should
+ -- be applied.
+
+maxISDN-SubaddressLength INTEGER ::= 21
+
+ExternalSignalInfo ::= SEQUENCE {
+ protocolId ProtocolId,
+ signalInfo SignalInfo,
+ -- Information about the internal structure is given in
+ -- clause 7.6.9.
+ extensionContainer ExtensionContainer OPTIONAL,
+ -- extensionContainer must not be used in version 2
+ ...}
+
+SignalInfo ::= OCTET STRING (SIZE (1..maxSignalInfoLength))
+
+maxSignalInfoLength INTEGER ::= 200
+ -- This NamedValue represents the theoretical maximum number of octets which is
+ -- available to carry a single instance of the SignalInfo data type,
+ -- without requiring segmentation to cope with the network layer service.
+ -- However, the actual maximum size available for an instance of the data
+ -- type may be lower, especially when other information elements
+ -- have to be included in the same component.
+
+ProtocolId ::= ENUMERATED {
+ gsm-0408 (1),
+ gsm-0806 (2),
+ gsm-BSSMAP (3),
+ -- Value 3 is reserved and must not be used
+ ets-300102-1 (4)}
+
+Ext-ExternalSignalInfo ::= SEQUENCE {
+ ext-ProtocolId Ext-ProtocolId,
+ signalInfo SignalInfo,
+ -- Information about the internal structure is given in
+ -- clause 7.6.9.10
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+Ext-ProtocolId ::= ENUMERATED {
+ ets-300356 (1),
+ ...
+ }
+-- exception handling:
+-- For Ext-ExternalSignalInfo sequences containing this parameter with any
+-- other value than the ones listed the receiver shall ignore the whole
+-- Ext-ExternalSignalInfo sequence.
+
+AccessNetworkSignalInfo ::= SEQUENCE {
+ accessNetworkProtocolId AccessNetworkProtocolId,
+ signalInfo LongSignalInfo,
+ -- Information about the internal structure is given in clause 7.6.9.1
+
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+LongSignalInfo ::= OCTET STRING (SIZE (1..maxLongSignalInfoLength))
+
+maxLongSignalInfoLength INTEGER ::= 2560
+ -- This Named Value represents the maximum number of octets which is available
+ -- to carry a single instance of the LongSignalInfo data type using
+ -- White Book SCCP with the maximum number of segments.
+ -- It takes account of the octets used by the lower layers of the protocol, and
+ -- other information elements which may be included in the same component.
+
+AccessNetworkProtocolId ::= ENUMERATED {
+ ts3G-48006 (1),
+ ts3G-25413 (2),
+ ...}
+ -- exception handling:
+ -- For AccessNetworkSignalInfo sequences containing this parameter with any
+ -- other value than the ones listed the receiver shall ignore the whole
+ -- AccessNetworkSignalInfo sequence.
+
+AlertingPattern ::= OCTET STRING (SIZE (1) )
+ -- This type is used to represent Alerting Pattern
+
+ -- bits 8765 : 0000 (unused)
+
+ -- bits 43 : type of Pattern
+ -- 00 level
+ -- 01 category
+ -- 10 category
+ -- all other values are reserved.
+
+ -- bits 21 : type of alerting
+
+alertingLevel-0 AlertingPattern ::= '00000000'B
+alertingLevel-1 AlertingPattern ::= '00000001'B
+alertingLevel-2 AlertingPattern ::= '00000010'B
+ -- all other values of Alerting level are reserved
+ -- Alerting Levels are defined in GSM 02.07
+
+alertingCategory-1 AlertingPattern ::= '00000100'B
+alertingCategory-2 AlertingPattern ::= '00000101'B
+alertingCategory-3 AlertingPattern ::= '00000110'B
+alertingCategory-4 AlertingPattern ::= '00000111'B
+alertingCategory-5 AlertingPattern ::= '00001000'B
+ -- all other values of Alerting Category are reserved
+ -- Alerting categories are defined in GSM 02.07
+
+-- data types for numbering and identification
+
+IMSI ::= TBCD-STRING (SIZE (3..8))
+ -- digits of MCC, MNC, MSIN are concatenated in this order.
+
+Identity ::= CHOICE {
+ imsi IMSI,
+ imsi-WithLMSI IMSI-WithLMSI}
+
+IMSI-WithLMSI ::= SEQUENCE {
+ imsi IMSI,
+ lmsi LMSI,
+ -- a special value 00000000 indicates that the LMSI is not in use
+ ...}
+
+ASCI-CallReference ::= TBCD-STRING (SIZE (1..8))
+ -- digits of VGCS/VBS-area,Group-ID are concatenated in this order if there is a
+ -- VGCS/VBS-area.
+
+TMSI ::= OCTET STRING (SIZE (1..4))
+
+SubscriberId ::= CHOICE {
+ imsi [0] IMSI,
+ tmsi [1] TMSI}
+
+IMEI ::= TBCD-STRING (SIZE (8))
+ -- Refers to International Mobile Station Equipment Identity
+ -- and Software Version Number (SVN) defined in TS 3GPP TS 23.003 [17].
+ -- If the SVN is not present the last octet shall contain the
+ -- digit 0 and a filler.
+ -- If present the SVN shall be included in the last octet.
+
+HLR-Id ::= IMSI
+ -- leading digits of IMSI, i.e. (MCC, MNC, leading digits of
+ -- MSIN) forming HLR Id defined in TS 3GPP TS 23.003 [17].
+
+HLR-List ::= SEQUENCE SIZE (1..maxNumOfHLR-Id) OF
+ HLR-Id
+
+maxNumOfHLR-Id INTEGER ::= 50
+
+LMSI ::= OCTET STRING (SIZE (4))
+
+GlobalCellId ::= OCTET STRING (SIZE (5..7))
+ -- Refers to Cell Global Identification defined in TS 3GPP TS 23.003 [17].
+ -- The internal structure is defined as follows:
+ -- octet 1 bits 4321 Mobile Country Code 1st digit
+ -- bits 8765 Mobile Country Code 2nd digit
+ -- octet 2 bits 4321 Mobile Country Code 3rd digit
+ -- bits 8765 Mobile Network Code 3rd digit
+ -- or filler (1111) for 2 digit MNCs
+ -- octet 3 bits 4321 Mobile Network Code 1st digit
+ -- bits 8765 Mobile Network Code 2nd digit
+ -- octets 4 and 5 Location Area Code according to TS 3GPP TS 24.008 [35]
+ -- octets 6 and 7 Cell Identity (CI) according to TS 3GPP TS 24.008 [35]
+
+NetworkResource ::= ENUMERATED {
+ plmn (0),
+ hlr (1),
+ vlr (2),
+ pvlr (3),
+ controllingMSC (4),
+ vmsc (5),
+ eir (6),
+ rss (7)}
+
+AdditionalNetworkResource ::= ENUMERATED {
+ sgsn (0),
+ ggsn (1),
+ gmlc (2),
+ gsmSCF (3),
+ nplr (4),
+ auc (5),
+ ... ,
+ ue (6),
+ mme (7)}
+ -- if unknown value is received in AdditionalNetworkResource
+ -- it shall be ignored.
+
+
+NAEA-PreferredCI ::= SEQUENCE {
+ naea-PreferredCIC [0] NAEA-CIC,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ...}
+
+NAEA-CIC ::= OCTET STRING (SIZE (3))
+ -- The internal structure is defined by the Carrier Identification
+ -- parameter in ANSI T1.113.3. Carrier codes between "000" and "999" may
+ -- be encoded as 3 digits using "000" to "999" or as 4 digits using
+ -- "0000" to "0999". Carrier codes between "1000" and "9999" are encoded
+ -- using 4 digits.
+
+SubscriberIdentity ::= CHOICE {
+ imsi [0] IMSI,
+ msisdn [1] ISDN-AddressString
+ }
+
+LCSClientExternalID ::= SEQUENCE {
+ externalAddress [0] ISDN-AddressString OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ... }
+
+LCSClientInternalID ::= ENUMERATED {
+ broadcastService (0),
+ o-andM-HPLMN (1),
+ o-andM-VPLMN (2),
+ anonymousLocation (3),
+ targetMSsubscribedService (4),
+ ... }
+-- for a CAMEL phase 3 PLMN operator client, the value targetMSsubscribedService shall be used
+
+LCSServiceTypeID ::= INTEGER (0..127)
+ -- the integer values 0-63 are reserved for Standard LCS service types
+ -- the integer values 64-127 are reserved for Non Standard LCS service types
+
+-- Standard LCS Service Types
+emergencyServices LCSServiceTypeID ::= 0
+emergencyAlertServices LCSServiceTypeID ::= 1
+personTracking LCSServiceTypeID ::= 2
+fleetManagement LCSServiceTypeID ::= 3
+assetManagement LCSServiceTypeID ::= 4
+trafficCongestionReporting LCSServiceTypeID ::= 5
+roadsideAssistance LCSServiceTypeID ::= 6
+routingToNearestCommercialEnterprise LCSServiceTypeID ::= 7
+navigation LCSServiceTypeID ::= 8
+ --this service type is reserved for use in previous releases
+citySightseeing LCSServiceTypeID ::= 9
+localizedAdvertising LCSServiceTypeID ::= 10
+mobileYellowPages LCSServiceTypeID ::= 11
+trafficAndPublicTransportationInfo LCSServiceTypeID ::= 12
+weather LCSServiceTypeID ::= 13
+assetAndServiceFinding LCSServiceTypeID ::= 14
+gaming LCSServiceTypeID ::= 15
+findYourFriend LCSServiceTypeID ::= 16
+dating LCSServiceTypeID ::= 17
+chatting LCSServiceTypeID ::= 18
+routeFinding LCSServiceTypeID ::= 19
+whereAmI LCSServiceTypeID ::= 20
+
+-- The values of LCSServiceTypeID are defined according to 3GPP TS 22.071.
+
+-- Non Standard LCS Service Types
+serv64 LCSServiceTypeID ::= 64
+serv65 LCSServiceTypeID ::= 65
+serv66 LCSServiceTypeID ::= 66
+serv67 LCSServiceTypeID ::= 67
+serv68 LCSServiceTypeID ::= 68
+serv69 LCSServiceTypeID ::= 69
+serv70 LCSServiceTypeID ::= 70
+serv71 LCSServiceTypeID ::= 71
+serv72 LCSServiceTypeID ::= 72
+serv73 LCSServiceTypeID ::= 73
+serv74 LCSServiceTypeID ::= 74
+serv75 LCSServiceTypeID ::= 75
+serv76 LCSServiceTypeID ::= 76
+serv77 LCSServiceTypeID ::= 77
+serv78 LCSServiceTypeID ::= 78
+serv79 LCSServiceTypeID ::= 79
+serv80 LCSServiceTypeID ::= 80
+serv81 LCSServiceTypeID ::= 81
+serv82 LCSServiceTypeID ::= 82
+serv83 LCSServiceTypeID ::= 83
+serv84 LCSServiceTypeID ::= 84
+serv85 LCSServiceTypeID ::= 85
+serv86 LCSServiceTypeID ::= 86
+serv87 LCSServiceTypeID ::= 87
+serv88 LCSServiceTypeID ::= 88
+serv89 LCSServiceTypeID ::= 89
+serv90 LCSServiceTypeID ::= 90
+serv91 LCSServiceTypeID ::= 91
+serv92 LCSServiceTypeID ::= 92
+serv93 LCSServiceTypeID ::= 93
+serv94 LCSServiceTypeID ::= 94
+serv95 LCSServiceTypeID ::= 95
+serv96 LCSServiceTypeID ::= 96
+serv97 LCSServiceTypeID ::= 97
+serv98 LCSServiceTypeID ::= 98
+serv99 LCSServiceTypeID ::= 99
+serv100 LCSServiceTypeID ::= 100
+serv101 LCSServiceTypeID ::= 101
+serv102 LCSServiceTypeID ::= 102
+serv103 LCSServiceTypeID ::= 103
+serv104 LCSServiceTypeID ::= 104
+serv105 LCSServiceTypeID ::= 105
+serv106 LCSServiceTypeID ::= 106
+serv107 LCSServiceTypeID ::= 107
+serv108 LCSServiceTypeID ::= 108
+serv109 LCSServiceTypeID ::= 109
+serv110 LCSServiceTypeID ::= 110
+serv111 LCSServiceTypeID ::= 111
+serv112 LCSServiceTypeID ::= 112
+serv113 LCSServiceTypeID ::= 113
+serv114 LCSServiceTypeID ::= 114
+serv115 LCSServiceTypeID ::= 115
+serv116 LCSServiceTypeID ::= 116
+serv117 LCSServiceTypeID ::= 117
+serv118 LCSServiceTypeID ::= 118
+serv119 LCSServiceTypeID ::= 119
+serv120 LCSServiceTypeID ::= 120
+serv121 LCSServiceTypeID ::= 121
+serv122 LCSServiceTypeID ::= 122
+serv123 LCSServiceTypeID ::= 123
+serv124 LCSServiceTypeID ::= 124
+serv125 LCSServiceTypeID ::= 125
+serv126 LCSServiceTypeID ::= 126
+serv127 LCSServiceTypeID ::= 127
+
+PLMN-Id ::= OCTET STRING (SIZE (3))
+ -- The internal structure is defined as follows:
+ -- octet 1 bits 4321 Mobile Country Code 1st digit
+ -- bits 8765 Mobile Country Code 2nd digit
+ -- octet 2 bits 4321 Mobile Country Code 3rd digit
+ -- bits 8765 Mobile Network Code 3rd digit
+ -- or filler (1111) for 2 digit MNCs
+ -- octet 3 bits 4321 Mobile Network Code 1st digit
+ -- bits 8765 Mobile Network Code 2nd digit
+
+-- data types for CAMEL
+
+CellGlobalIdOrServiceAreaIdOrLAI ::= CHOICE {
+ cellGlobalIdOrServiceAreaIdFixedLength [0] CellGlobalIdOrServiceAreaIdFixedLength,
+ laiFixedLength [1] LAIFixedLength}
+
+CellGlobalIdOrServiceAreaIdFixedLength ::= OCTET STRING (SIZE (7))
+ -- Refers to Cell Global Identification or Service Are Identification
+ -- defined in 3GPP TS 23.003.
+ -- The internal structure is defined as follows:
+ -- octet 1 bits 4321 Mobile Country Code 1st digit
+ -- bits 8765 Mobile Country Code 2nd digit
+ -- octet 2 bits 4321 Mobile Country Code 3rd digit
+ -- bits 8765 Mobile Network Code 3rd digit
+ -- or filler (1111) for 2 digit MNCs
+ -- octet 3 bits 4321 Mobile Network Code 1st digit
+ -- bits 8765 Mobile Network Code 2nd digit
+ -- octets 4 and 5 Location Area Code according to 3GPP TS 24.008
+ -- octets 6 and 7 Cell Identity (CI) value or
+ -- Service Area Code (SAC) value
+ -- according to 3GPP TS 23.003
+
+LAIFixedLength ::= OCTET STRING (SIZE (5))
+ -- Refers to Location Area Identification defined in 3GPP TS 23.003 [17].
+ -- The internal structure is defined as follows:
+ -- octet 1 bits 4321 Mobile Country Code 1st digit
+ -- bits 8765 Mobile Country Code 2nd digit
+ -- octet 2 bits 4321 Mobile Country Code 3rd digit
+ -- bits 8765 Mobile Network Code 3rd digit
+ -- or filler (1111) for 2 digit MNCs
+ -- octet 3 bits 4321 Mobile Network Code 1st digit
+ -- bits 8765 Mobile Network Code 2nd digit
+ -- octets 4 and 5 Location Area Code according to 3GPP TS 24.008 [35]
+
+-- data types for subscriber management
+
+BasicServiceCode ::= CHOICE {
+ bearerService [2] BearerServiceCode,
+ teleservice [3] TeleserviceCode}
+
+Ext-BasicServiceCode ::= CHOICE {
+ ext-BearerService [2] Ext-BearerServiceCode,
+ ext-Teleservice [3] Ext-TeleserviceCode}
+
+EMLPP-Info ::= SEQUENCE {
+ maximumentitledPriority EMLPP-Priority,
+ defaultPriority EMLPP-Priority,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+EMLPP-Priority ::= INTEGER (0..15)
+ -- The mapping from the values A,B,0,1,2,3,4 to the integer-value is
+ -- specified as follows where A is the highest and 4 is the lowest
+ -- priority level
+ -- the integer values 7-15 are spare and shall be mapped to value 4
+
+priorityLevelA EMLPP-Priority ::= 6
+priorityLevelB EMLPP-Priority ::= 5
+priorityLevel0 EMLPP-Priority ::= 0
+priorityLevel1 EMLPP-Priority ::= 1
+priorityLevel2 EMLPP-Priority ::= 2
+priorityLevel3 EMLPP-Priority ::= 3
+priorityLevel4 EMLPP-Priority ::= 4
+
+MC-SS-Info ::= SEQUENCE {
+ ss-Code [0] SS-Code,
+ ss-Status [1] Ext-SS-Status,
+ nbrSB [2] MaxMC-Bearers,
+ nbrUser [3] MC-Bearers,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ...}
+
+MaxMC-Bearers ::= INTEGER (2..maxNumOfMC-Bearers)
+
+MC-Bearers ::= INTEGER (1..maxNumOfMC-Bearers)
+
+maxNumOfMC-Bearers INTEGER ::= 7
+
+Ext-SS-Status ::= OCTET STRING (SIZE (1..5))
+
+ -- OCTET 1:
+ --
+ -- bits 8765: 0000 (unused)
+ -- bits 4321: Used to convey the "P bit","R bit","A bit" and "Q bit",
+ -- representing supplementary service state information
+ -- as defined in TS 3GPP TS 23.011 [22]
+
+ -- bit 4: "Q bit"
+
+ -- bit 3: "P bit"
+
+ -- bit 2: "R bit"
+
+ -- bit 1: "A bit"
+
+ -- OCTETS 2-5: reserved for future use. They shall be discarded if
+ -- received and not understood.
+
+
+ -- data types for geographic location
+
+AgeOfLocationInformation ::= INTEGER (0..32767)
+-- the value represents the elapsed time in minutes since the last
+-- network contact of the mobile station (i.e. the actuality of the
+-- location information).
+-- value "0" indicates that the MS is currently in contact with the
+-- network
+-- value "32767" indicates that the location information is at least
+-- 32767 minutes old
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-ER-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-ER-DataTypes.asn
new file mode 100644
index 000000000..d0b90fc78
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-ER-DataTypes.asn
@@ -0,0 +1,415 @@
+-- $Id: MAP-ER-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+-- 17.7.7 Error data types
+
+MAP-ER-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ER-DataTypes (17) version11 (11)}
+
+DEFINITIONS
+
+IMPLICIT TAGS
+
+::=
+
+BEGIN
+
+EXPORTS
+ RoamingNotAllowedParam,
+ CallBarredParam,
+ CUG-RejectParam,
+ SS-IncompatibilityCause,
+ PW-RegistrationFailureCause,
+ SM-DeliveryFailureCause,
+ SystemFailureParam,
+ DataMissingParam,
+ UnexpectedDataParam,
+ FacilityNotSupParam,
+ OR-NotAllowedParam,
+ UnknownSubscriberParam,
+ NumberChangedParam,
+ UnidentifiedSubParam,
+ IllegalSubscriberParam,
+ IllegalEquipmentParam,
+ BearerServNotProvParam,
+ TeleservNotProvParam,
+ TracingBufferFullParam,
+ NoRoamingNbParam,
+ AbsentSubscriberParam,
+ BusySubscriberParam,
+ NoSubscriberReplyParam,
+ ForwardingViolationParam,
+ ForwardingFailedParam,
+ ATI-NotAllowedParam,
+ SubBusyForMT-SMS-Param,
+ MessageWaitListFullParam,
+ AbsentSubscriberSM-Param,
+ AbsentSubscriberDiagnosticSM,
+ ResourceLimitationParam,
+ NoGroupCallNbParam,
+ IncompatibleTerminalParam,
+ ShortTermDenialParam,
+ LongTermDenialParam,
+ UnauthorizedRequestingNetwork-Param,
+ UnauthorizedLCSClient-Param,
+ PositionMethodFailure-Param,
+UnknownOrUnreachableLCSClient-Param,
+ MM-EventNotSupported-Param,
+ATSI-NotAllowedParam,
+ATM-NotAllowedParam,
+IllegalSS-OperationParam,
+SS-NotAvailableParam,
+SS-SubscriptionViolationParam,
+InformationNotAvailableParam,
+TargetCellOutsideGCA-Param,
+OngoingGroupCallParam
+
+;
+
+IMPORTS
+ SS-Status
+FROM MAP-SS-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SS-DataTypes (14) version11 (11)}
+
+ SignalInfo,
+ BasicServiceCode,
+ NetworkResource,
+ AdditionalNetworkResource
+FROM MAP-CommonDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
+
+
+ SS-Code
+FROM MAP-SS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
+
+ ExtensionContainer
+FROM MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+;
+
+RoamingNotAllowedParam ::= SEQUENCE {
+ roamingNotAllowedCause RoamingNotAllowedCause,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ additionalRoamingNotAllowedCause [0] AdditionalRoamingNotAllowedCause OPTIONAL }
+
+-- if the additionalRoamingNotallowedCause is received by the MSC/VLR or SGSN then the
+-- roamingNotAllowedCause shall be discarded.
+
+AdditionalRoamingNotAllowedCause ::= ENUMERATED {
+ supportedRAT-TypesNotAllowed (0),
+ ...}
+
+RoamingNotAllowedCause ::= ENUMERATED {
+ plmnRoamingNotAllowed (0),
+ operatorDeterminedBarring (3)}
+
+CallBarredParam ::= CHOICE {
+ callBarringCause CallBarringCause,
+ -- call BarringCause must not be used in version 3 and higher
+ extensibleCallBarredParam ExtensibleCallBarredParam
+ -- extensibleCallBarredParam must not be used in version <3
+ }
+
+CallBarringCause ::= ENUMERATED {
+ barringServiceActive (0),
+ operatorBarring (1)}
+
+ExtensibleCallBarredParam ::= SEQUENCE {
+ callBarringCause CallBarringCause OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ unauthorisedMessageOriginator [1] NULL OPTIONAL }
+
+CUG-RejectParam ::= SEQUENCE {
+ cug-RejectCause CUG-RejectCause OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+CUG-RejectCause ::= ENUMERATED {
+ incomingCallsBarredWithinCUG (0),
+ subscriberNotMemberOfCUG (1),
+ requestedBasicServiceViolatesCUG-Constraints (5),
+ calledPartySS-InteractionViolation (7)}
+
+SS-IncompatibilityCause ::= SEQUENCE {
+ ss-Code [1] SS-Code OPTIONAL,
+ basicService BasicServiceCode OPTIONAL,
+ ss-Status [4] SS-Status OPTIONAL,
+ ...}
+
+PW-RegistrationFailureCause ::= ENUMERATED {
+ undetermined (0),
+ invalidFormat (1),
+ newPasswordsMismatch (2)}
+
+SM-EnumeratedDeliveryFailureCause ::= ENUMERATED {
+ memoryCapacityExceeded (0),
+ equipmentProtocolError (1),
+ equipmentNotSM-Equipped (2),
+ unknownServiceCentre (3),
+ sc-Congestion (4),
+ invalidSME-Address (5),
+ subscriberNotSC-Subscriber (6)}
+
+SM-DeliveryFailureCause ::= SEQUENCE {
+ sm-EnumeratedDeliveryFailureCause SM-EnumeratedDeliveryFailureCause,
+ diagnosticInfo SignalInfo OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+AbsentSubscriberSM-Param ::= SEQUENCE {
+ absentSubscriberDiagnosticSM AbsentSubscriberDiagnosticSM OPTIONAL,
+ -- AbsentSubscriberDiagnosticSM can be either for non-GPRS
+ -- or for GPRS
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ additionalAbsentSubscriberDiagnosticSM [0] AbsentSubscriberDiagnosticSM OPTIONAL }
+ -- if received, additionalAbsentSubscriberDiagnosticSM
+ -- is for GPRS and absentSubscriberDiagnosticSM is
+ -- for non-GPRS
+
+AbsentSubscriberDiagnosticSM ::= INTEGER (0..255)
+ -- AbsentSubscriberDiagnosticSM values are defined in 3GPP TS 23.040
+
+SystemFailureParam ::= CHOICE {
+ networkResource NetworkResource,
+ -- networkResource must not be used in version 3
+ extensibleSystemFailureParam ExtensibleSystemFailureParam
+ -- extensibleSystemFailureParam must not be used in version <3
+ }
+
+ExtensibleSystemFailureParam ::= SEQUENCE {
+ networkResource NetworkResource OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ additionalNetworkResource [0] AdditionalNetworkResource OPTIONAL,
+ failureCauseParam [1] FailureCauseParam OPTIONAL }
+
+FailureCauseParam ::= ENUMERATED {
+ limitReachedOnNumberOfConcurrentLocationRequests (0),
+ ... }
+ -- if unknown value is received in FailureCauseParam it shall be ignored
+
+
+DataMissingParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+UnexpectedDataParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+FacilityNotSupParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ shapeOfLocationEstimateNotSupported [0] NULL OPTIONAL,
+ neededLcsCapabilityNotSupportedInServingNode [1] NULL OPTIONAL }
+
+OR-NotAllowedParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+UnknownSubscriberParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ unknownSubscriberDiagnostic UnknownSubscriberDiagnostic OPTIONAL}
+
+UnknownSubscriberDiagnostic ::= ENUMERATED {
+ imsiUnknown (0),
+ gprs-eps-SubscriptionUnknown (1),
+ ...,
+ npdbMismatch (2)}
+ -- if unknown values are received in
+ -- UnknownSubscriberDiagnostic they shall be discarded
+
+NumberChangedParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+UnidentifiedSubParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+IllegalSubscriberParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+IllegalEquipmentParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+BearerServNotProvParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+TeleservNotProvParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+TracingBufferFullParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+NoRoamingNbParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+AbsentSubscriberParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ absentSubscriberReason [0] AbsentSubscriberReason OPTIONAL}
+
+AbsentSubscriberReason ::= ENUMERATED {
+ imsiDetach (0),
+ restrictedArea (1),
+ noPageResponse (2),
+ ... ,
+ purgedMS (3)}
+-- exception handling: at reception of other values than the ones listed the
+-- AbsentSubscriberReason shall be ignored.
+-- The AbsentSubscriberReason: purgedMS is defined for the Super-Charger feature
+-- (see TS 23.116). If this value is received in a Provide Roaming Number response
+-- it shall be mapped to the AbsentSubscriberReason: imsiDetach in the Send Routeing
+-- Information response
+
+BusySubscriberParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ ccbs-Possible [0] NULL OPTIONAL,
+ ccbs-Busy [1] NULL OPTIONAL}
+
+NoSubscriberReplyParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+ForwardingViolationParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+ForwardingFailedParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+ATI-NotAllowedParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+ATSI-NotAllowedParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+ATM-NotAllowedParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+IllegalSS-OperationParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+SS-NotAvailableParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+SS-SubscriptionViolationParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+InformationNotAvailableParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+SubBusyForMT-SMS-Param ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ gprsConnectionSuspended NULL OPTIONAL }
+ -- If GprsConnectionSuspended is not understood it shall
+ -- be discarded
+
+MessageWaitListFullParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+ResourceLimitationParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+NoGroupCallNbParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+IncompatibleTerminalParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+ShortTermDenialParam ::= SEQUENCE {
+ ...}
+
+LongTermDenialParam ::= SEQUENCE {
+ ...}
+
+UnauthorizedRequestingNetwork-Param ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+UnauthorizedLCSClient-Param ::= SEQUENCE {
+ unauthorizedLCSClient-Diagnostic [0] UnauthorizedLCSClient-Diagnostic OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ... }
+
+UnauthorizedLCSClient-Diagnostic ::= ENUMERATED {
+ noAdditionalInformation (0),
+ clientNotInMSPrivacyExceptionList (1),
+ callToClientNotSetup (2),
+ privacyOverrideNotApplicable (3),
+ disallowedByLocalRegulatoryRequirements (4),
+ ...,
+ unauthorizedPrivacyClass (5),
+ unauthorizedCallSessionUnrelatedExternalClient (6),
+ unauthorizedCallSessionRelatedExternalClient (7) }
+-- exception handling:
+-- any unrecognized value shall be ignored
+
+PositionMethodFailure-Param ::= SEQUENCE {
+ positionMethodFailure-Diagnostic [0] PositionMethodFailure-Diagnostic OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ... }
+
+PositionMethodFailure-Diagnostic ::= ENUMERATED {
+ congestion (0),
+ insufficientResources (1),
+ insufficientMeasurementData (2),
+ inconsistentMeasurementData (3),
+ locationProcedureNotCompleted (4),
+ locationProcedureNotSupportedByTargetMS (5),
+ qoSNotAttainable (6),
+ positionMethodNotAvailableInNetwork (7),
+ positionMethodNotAvailableInLocationArea (8),
+ ... }
+-- exception handling:
+-- any unrecognized value shall be ignored
+
+UnknownOrUnreachableLCSClient-Param ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+MM-EventNotSupported-Param ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+TargetCellOutsideGCA-Param ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+OngoingGroupCallParam ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-ExtensionDataTypes.asn b/rrlp-ephemeris/asn1/MAP-ExtensionDataTypes.asn
new file mode 100644
index 000000000..d94c057cc
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-ExtensionDataTypes.asn
@@ -0,0 +1,74 @@
+-- $Id: MAP-ExtensionDataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- MAP-ExtensionDataTypes.asn
+--
+-- Taken from 3GPP TS 29.002 V8.9.0 (2009-04)
+--
+-- 17.7.11 Extension data types
+--
+
+MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+
+DEFINITIONS
+
+IMPLICIT TAGS
+
+::=
+
+BEGIN
+
+EXPORTS
+
+ PrivateExtension,
+ ExtensionContainer,
+ SLR-ArgExtensionContainer;
+
+
+-- IOC for private MAP extensions
+
+
+MAP-EXTENSION ::= CLASS {
+ &ExtensionType OPTIONAL,
+ &extensionId OBJECT IDENTIFIER }
+ -- The length of the Object Identifier shall not exceed 16 octets and the
+ -- number of components of the Object Identifier shall not exceed 16
+
+-- data types
+
+ExtensionContainer ::= SEQUENCE {
+ privateExtensionList [0]PrivateExtensionList OPTIONAL,
+ pcs-Extensions [1]PCS-Extensions OPTIONAL,
+ ...}
+
+SLR-ArgExtensionContainer ::= SEQUENCE {
+ privateExtensionList [0]PrivateExtensionList OPTIONAL,
+ slr-Arg-PCS-Extensions [1]SLR-Arg-PCS-Extensions OPTIONAL,
+ ...}
+
+PrivateExtensionList ::= SEQUENCE SIZE (1..maxNumOfPrivateExtensions) OF
+ PrivateExtension
+
+PrivateExtension ::= SEQUENCE {
+ extId MAP-EXTENSION.&extensionId
+ ({ExtensionSet}),
+ extType MAP-EXTENSION.&ExtensionType
+ ({ExtensionSet}{@extId}) OPTIONAL}
+
+maxNumOfPrivateExtensions INTEGER ::= 10
+
+ExtensionSet MAP-EXTENSION ::=
+ {...
+ -- ExtensionSet is the set of all defined private extensions
+ }
+ -- Unsupported private extensions shall be discarded if received.
+
+PCS-Extensions ::= SEQUENCE {
+ ...}
+
+SLR-Arg-PCS-Extensions ::= SEQUENCE {
+ ...,
+ na-ESRK-Request [0] NULL OPTIONAL }
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-LCS-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-LCS-DataTypes.asn
new file mode 100644
index 000000000..2434b89f9
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-LCS-DataTypes.asn
@@ -0,0 +1,657 @@
+-- $Id: MAP-LCS-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- MAP-LCS-DataTypes.asn
+--
+-- Taken from 3GPP TS 29.002 V8.9.0 (2009-04)
+--
+-- 17.7.13 Location service data types
+--
+
+MAP-LCS-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-LCS-DataTypes (25) version11 (11)}
+
+DEFINITIONS
+IMPLICIT TAGS
+::=
+BEGIN
+
+EXPORTS
+ RoutingInfoForLCS-Arg,
+ RoutingInfoForLCS-Res,
+ ProvideSubscriberLocation-Arg,
+ ProvideSubscriberLocation-Res,
+ SubscriberLocationReport-Arg,
+ SubscriberLocationReport-Res,
+LocationType,
+DeferredLocationEventType,
+LCSClientName,
+LCS-QoS,
+Horizontal-Accuracy,
+ResponseTime,
+Ext-GeographicalInformation,
+VelocityEstimate,
+SupportedGADShapes,
+Add-GeographicalInformation,
+LCSRequestorID,
+LCS-ReferenceNumber,
+LCSCodeword,
+AreaEventInfo,
+ReportingPLMNList,
+PeriodicLDRInfo,
+SequenceNumber
+;
+
+IMPORTS
+ AddressString,
+ ISDN-AddressString,
+ IMEI,
+ IMSI,
+ LMSI,
+ SubscriberIdentity,
+ AgeOfLocationInformation,
+ LCSClientExternalID,
+ LCSClientInternalID,
+LCSServiceTypeID,
+CellGlobalIdOrServiceAreaIdOrLAI,
+PLMN-Id
+FROM MAP-CommonDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
+
+ ExtensionContainer,
+ SLR-ArgExtensionContainer
+FROM MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+
+ USSD-DataCodingScheme,
+USSD-String
+FROM MAP-SS-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0) gsm-Network (1) modules (3)
+ map-SS-DataTypes (14) version11 (11)}
+
+ APN,
+ GSN-Address,
+ SupportedLCS-CapabilitySets
+FROM MAP-MS-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-MS-DataTypes (11) version11 (11)}
+
+ Additional-Number
+FROM MAP-SM-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SM-DataTypes (16) version11 (11)}
+;
+
+
+RoutingInfoForLCS-Arg ::= SEQUENCE {
+ mlcNumber [0] ISDN-AddressString,
+ targetMS [1] SubscriberIdentity,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...}
+
+RoutingInfoForLCS-Res ::= SEQUENCE {
+ targetMS [0] SubscriberIdentity,
+ lcsLocationInfo [1] LCSLocationInfo,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...,
+ v-gmlc-Address [3] GSN-Address OPTIONAL,
+ h-gmlc-Address [4] GSN-Address OPTIONAL,
+ ppr-Address [5] GSN-Address OPTIONAL,
+ additional-v-gmlc-Address [6] GSN-Address OPTIONAL }
+
+LCSLocationInfo ::= SEQUENCE {
+ networkNode-Number ISDN-AddressString,
+ -- NetworkNode-number can be either msc-number or sgsn-number
+ lmsi [0] LMSI OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ... ,
+ gprsNodeIndicator [2] NULL OPTIONAL,
+ -- gprsNodeIndicator is set only if the SGSN number is sent as the Network Node Number
+ additional-Number [3] Additional-Number OPTIONAL,
+ supportedLCS-CapabilitySets [4] SupportedLCS-CapabilitySets OPTIONAL,
+ additional-LCS-CapabilitySets [5] SupportedLCS-CapabilitySets OPTIONAL
+ }
+
+ProvideSubscriberLocation-Arg ::= SEQUENCE {
+ locationType LocationType,
+ mlc-Number ISDN-AddressString,
+ lcs-ClientID [0] LCS-ClientID OPTIONAL,
+ privacyOverride [1] NULL OPTIONAL,
+ imsi [2] IMSI OPTIONAL,
+ msisdn [3] ISDN-AddressString OPTIONAL,
+ lmsi [4] LMSI OPTIONAL,
+ imei [5] IMEI OPTIONAL,
+ lcs-Priority [6] LCS-Priority OPTIONAL,
+ lcs-QoS [7] LCS-QoS OPTIONAL,
+ extensionContainer [8] ExtensionContainer OPTIONAL,
+ ... ,
+ supportedGADShapes [9] SupportedGADShapes OPTIONAL,
+ lcs-ReferenceNumber [10] LCS-ReferenceNumber OPTIONAL,
+ lcsServiceTypeID [11] LCSServiceTypeID OPTIONAL,
+ lcsCodeword [12] LCSCodeword OPTIONAL,
+ lcs-PrivacyCheck [13] LCS-PrivacyCheck OPTIONAL,
+ areaEventInfo [14] AreaEventInfo OPTIONAL,
+ h-gmlc-Address [15] GSN-Address OPTIONAL,
+ mo-lrShortCircuitIndicator [16] NULL OPTIONAL,
+ periodicLDRInfo [17] PeriodicLDRInfo OPTIONAL,
+ reportingPLMNList [18] ReportingPLMNList OPTIONAL }
+
+ -- one of imsi or msisdn is mandatory
+ -- If a location estimate type indicates activate deferred location or cancel deferred
+ -- location, a lcs-Reference number shall be included.
+
+LocationType ::= SEQUENCE {
+ locationEstimateType [0] LocationEstimateType,
+ ...,
+ deferredLocationEventType [1] DeferredLocationEventType OPTIONAL }
+
+LocationEstimateType ::= ENUMERATED {
+ currentLocation (0),
+ currentOrLastKnownLocation (1),
+ initialLocation (2),
+ ...,
+ activateDeferredLocation (3),
+ cancelDeferredLocation (4) ,
+ notificationVerificationOnly (5) }
+-- exception handling:
+-- a ProvideSubscriberLocation-Arg containing an unrecognized LocationEstimateType
+-- shall be rejected by the receiver with a return error cause of unexpected data value
+
+DeferredLocationEventType ::= BIT STRING {
+ msAvailable (0) ,
+ enteringIntoArea (1),
+ leavingFromArea (2),
+ beingInsideArea (3) ,
+ periodicLDR (4) } (SIZE (1..16))
+-- beingInsideArea is always treated as oneTimeEvent regardless of the possible value
+-- of occurrenceInfo inside areaEventInfo.
+-- exception handling:
+-- a ProvideSubscriberLocation-Arg containing other values than listed above in
+-- DeferredLocationEventType shall be rejected by the receiver with a return error cause of
+-- unexpected data value.
+
+LCS-ClientID ::= SEQUENCE {
+ lcsClientType [0] LCSClientType,
+ lcsClientExternalID [1] LCSClientExternalID OPTIONAL,
+ lcsClientDialedByMS [2] AddressString OPTIONAL,
+ lcsClientInternalID [3] LCSClientInternalID OPTIONAL,
+ lcsClientName [4] LCSClientName OPTIONAL,
+ ...,
+ lcsAPN [5] APN OPTIONAL,
+ lcsRequestorID [6] LCSRequestorID OPTIONAL }
+
+LCSClientType ::= ENUMERATED {
+ emergencyServices (0),
+ valueAddedServices (1),
+ plmnOperatorServices (2),
+ lawfulInterceptServices (3),
+ ... }
+ -- exception handling:
+ -- unrecognized values may be ignored if the LCS client uses the privacy override
+ -- otherwise, an unrecognized value shall be treated as unexpected data by a receiver
+ -- a return error shall then be returned if received in a MAP invoke
+
+LCSClientName ::= SEQUENCE {
+ dataCodingScheme [0] USSD-DataCodingScheme,
+ nameString [2] NameString,
+ ...,
+ lcs-FormatIndicator [3] LCS-FormatIndicator OPTIONAL }
+
+-- The USSD-DataCodingScheme shall indicate use of the default alphabet through the
+-- following encoding
+-- bit 7 6 5 4 3 2 1 0
+-- 0 0 0 0 1 1 1 1
+
+NameString ::= USSD-String (SIZE (1..maxNameStringLength))
+
+maxNameStringLength INTEGER ::= 63
+
+LCSRequestorID ::= SEQUENCE {
+ dataCodingScheme [0] USSD-DataCodingScheme,
+ requestorIDString [1] RequestorIDString,
+ ...,
+ lcs-FormatIndicator [2] LCS-FormatIndicator OPTIONAL }
+
+RequestorIDString ::= USSD-String (SIZE (1..maxRequestorIDStringLength))
+
+maxRequestorIDStringLength INTEGER ::= 63
+
+LCS-FormatIndicator ::= ENUMERATED {
+ logicalName (0),
+ e-mailAddress (1),
+ msisdn (2),
+ url (3),
+ sipUrl (4),
+ ... }
+
+LCS-Priority ::= OCTET STRING (SIZE (1))
+ -- 0 = highest priority
+ -- 1 = normal priority
+ -- all other values treated as 1
+
+LCS-QoS ::= SEQUENCE {
+ horizontal-accuracy [0] Horizontal-Accuracy OPTIONAL,
+ verticalCoordinateRequest [1] NULL OPTIONAL,
+ vertical-accuracy [2] Vertical-Accuracy OPTIONAL, responseTime [3] ResponseTime OPTIONAL,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ...,
+ velocityRequest [5] NULL OPTIONAL
+}
+
+Horizontal-Accuracy ::= OCTET STRING (SIZE (1))
+ -- bit 8 = 0
+ -- bits 7-1 = 7 bit Uncertainty Code defined in 3GPP TS 23.032. The horizontal location
+ -- error should be less than the error indicated by the uncertainty code with 67%
+ -- confidence.
+
+Vertical-Accuracy ::= OCTET STRING (SIZE (1))
+ -- bit 8 = 0
+ -- bits 7-1 = 7 bit Vertical Uncertainty Code defined in 3GPP TS 23.032.
+ -- The vertical location error should be less than the error indicated
+ -- by the uncertainty code with 67% confidence.
+
+ResponseTime ::= SEQUENCE {
+ responseTimeCategory ResponseTimeCategory,
+ ...}
+-- note: an expandable SEQUENCE simplifies later addition of a numeric response time.
+
+ResponseTimeCategory ::= ENUMERATED {
+ lowdelay (0),
+ delaytolerant (1),
+ ... }
+-- exception handling:
+-- an unrecognized value shall be treated the same as value 1 (delaytolerant)
+
+SupportedGADShapes ::= BIT STRING {
+ ellipsoidPoint (0),
+ ellipsoidPointWithUncertaintyCircle (1),
+ ellipsoidPointWithUncertaintyEllipse (2),
+ polygon (3),
+ ellipsoidPointWithAltitude (4),
+ ellipsoidPointWithAltitudeAndUncertaintyElipsoid (5),
+ ellipsoidArc (6) } (SIZE (7..16))
+-- A node shall mark in the BIT STRING all Shapes defined in 3GPP TS 23.032 it supports.
+-- exception handling: bits 7 to 15 shall be ignored if received.
+
+LCS-ReferenceNumber::= OCTET STRING (SIZE(1))
+
+LCSCodeword ::= SEQUENCE {
+ dataCodingScheme [0] USSD-DataCodingScheme,
+ lcsCodewordString [1] LCSCodewordString,
+ ...}
+
+LCSCodewordString ::= USSD-String (SIZE (1..maxLCSCodewordStringLength))
+
+maxLCSCodewordStringLength INTEGER ::= 20
+
+LCS-PrivacyCheck ::= SEQUENCE {
+ callSessionUnrelated [0] PrivacyCheckRelatedAction,
+ callSessionRelated [1] PrivacyCheckRelatedAction OPTIONAL,
+ ...}
+
+PrivacyCheckRelatedAction ::= ENUMERATED {
+ allowedWithoutNotification (0),
+ allowedWithNotification (1),
+ allowedIfNoResponse (2),
+ restrictedIfNoResponse (3),
+ notAllowed (4),
+ ...}
+-- exception handling:
+-- a ProvideSubscriberLocation-Arg containing an unrecognized PrivacyCheckRelatedAction
+-- shall be rejected by the receiver with a return error cause of unexpected data value
+
+AreaEventInfo ::= SEQUENCE {
+ areaDefinition [0] AreaDefinition,
+ occurrenceInfo [1] OccurrenceInfo OPTIONAL,
+ intervalTime [2] IntervalTime OPTIONAL,
+ ...}
+
+AreaDefinition ::= SEQUENCE {
+ areaList [0] AreaList,
+ ...}
+
+AreaList ::= SEQUENCE SIZE (1..maxNumOfAreas) OF Area
+
+maxNumOfAreas INTEGER ::= 10
+
+Area ::= SEQUENCE {
+ areaType [0] AreaType,
+ areaIdentification [1] AreaIdentification,
+ ...}
+
+AreaType ::= ENUMERATED {
+ countryCode (0),
+ plmnId (1),
+ locationAreaId (2),
+ routingAreaId (3),
+ cellGlobalId (4),
+ ...,
+ utranCellId (5) }
+
+AreaIdentification ::= OCTET STRING (SIZE (2..7))
+ -- The internal structure is defined as follows:
+ -- octet 1 bits 4321 Mobile Country Code 1st digit
+ -- bits 8765 Mobile Country Code 2nd digit
+ -- octet 2 bits 4321 Mobile Country Code 3rd digit
+ -- bits 8765 Mobile Network Code 3rd digit if 3 digit MNC included
+ -- or filler (1111)
+ -- octet 3 bits 4321 Mobile Network Code 1st digit
+ -- bits 8765 Mobile Network Code 2nd digit
+ -- octets 4 and 5 Location Area Code (LAC) for Local Area Id,
+ -- Routing Area Id and Cell Global Id
+ -- octet 6 Routing Area Code (RAC) for Routing Area Id
+ -- octets 6 and 7 Cell Identity (CI) for Cell Global Id
+ -- octets 4 until 7 Utran Cell Identity (UC-Id) for Utran Cell Id
+
+OccurrenceInfo ::= ENUMERATED {
+ oneTimeEvent (0),
+ multipleTimeEvent (1),
+ ...}
+
+IntervalTime ::= INTEGER (1..32767)
+ -- minimum interval time between area reports in seconds
+
+PeriodicLDRInfo ::= SEQUENCE {
+ reportingAmount ReportingAmount,
+ reportingInterval ReportingInterval,
+ ...}
+-- reportingInterval x reportingAmount shall not exceed 8639999 (99 days, 23 hours,
+-- 59 minutes and 59 seconds) for compatibility with OMA MLP and RLP
+
+ReportingAmount ::= INTEGER (1..maxReportingAmount)
+
+maxReportingAmount INTEGER ::= 8639999
+
+ReportingInterval ::= INTEGER (1..maxReportingInterval)
+-- ReportingInterval is in seconds
+
+maxReportingInterval INTEGER ::= 8639999
+
+ReportingPLMNList::= SEQUENCE {
+ plmn-ListPrioritized [0] NULL OPTIONAL,
+ plmn-List [1] PLMNList,
+ ...}
+
+PLMNList::= SEQUENCE SIZE (1..maxNumOfReportingPLMN) OF
+ ReportingPLMN
+
+maxNumOfReportingPLMN INTEGER ::= 20
+
+ReportingPLMN::= SEQUENCE {
+ plmn-Id [0] PLMN-Id,
+ ran-Technology [1] RAN-Technology OPTIONAL,
+ ran-PeriodicLocationSupport [2] NULL OPTIONAL,
+ ...}
+
+RAN-Technology ::= ENUMERATED {
+ gsm (0),
+ umts (1),
+ ...}
+
+ProvideSubscriberLocation-Res ::= SEQUENCE {
+ locationEstimate Ext-GeographicalInformation,
+ ageOfLocationEstimate [0] AgeOfLocationInformation OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ... ,
+ add-LocationEstimate [2] Add-GeographicalInformation OPTIONAL,
+ deferredmt-lrResponseIndicator [3] NULL OPTIONAL,
+ geranPositioningData [4] PositioningDataInformation OPTIONAL,
+ utranPositioningData [5] UtranPositioningDataInfo OPTIONAL,
+ cellIdOrSai [6] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
+ sai-Present [7] NULL OPTIONAL,
+ accuracyFulfilmentIndicator [8] AccuracyFulfilmentIndicator OPTIONAL,
+ velocityEstimate [9] VelocityEstimate OPTIONAL,
+ mo-lrShortCircuitIndicator [10] NULL OPTIONAL }
+
+-- if deferredmt-lrResponseIndicator is set, locationEstimate is ignored.
+
+-- the add-LocationEstimate parameter shall not be sent to a node that did not indicate the
+-- geographic shapes supported in the ProvideSubscriberLocation-Arg
+-- The locationEstimate and the add-locationEstimate parameters shall not be sent if
+-- the supportedGADShapes parameter has been received in ProvideSubscriberLocation-Arg
+-- and the shape encoded in locationEstimate or add-LocationEstimate is not marked
+-- as supported in supportedGADShapes. In such a case ProvideSubscriberLocation
+-- shall be rejected with error FacilityNotSupported with additional indication
+-- shapeOfLocationEstimateNotSupported.
+-- sai-Present indicates that the cellIdOrSai parameter contains a Service Area Identity.
+
+AccuracyFulfilmentIndicator ::= ENUMERATED {
+ requestedAccuracyFulfilled (0),
+ requestedAccuracyNotFulfilled (1),
+ ... }
+
+Ext-GeographicalInformation ::= OCTET STRING (SIZE (1..maxExt-GeographicalInformation))
+ -- Refers to geographical Information defined in 3GPP TS 23.032.
+ -- This is composed of 1 or more octets with an internal structure according to
+ -- 3GPP TS 23.032
+ -- Octet 1: Type of shape, only the following shapes in 3GPP TS 23.032 are allowed:
+ -- (a) Ellipsoid point with uncertainty circle
+ -- (b) Ellipsoid point with uncertainty ellipse
+ -- (c) Ellipsoid point with altitude and uncertainty ellipsoid
+ -- (d) Ellipsoid Arc
+ -- (e) Ellipsoid Point
+ -- Any other value in octet 1 shall be treated as invalid
+ -- Octets 2 to 8 for case (a) – Ellipsoid point with uncertainty circle
+ -- Degrees of Latitude 3 octets
+ -- Degrees of Longitude 3 octets
+ -- Uncertainty code 1 octet
+ -- Octets 2 to 11 for case (b) – Ellipsoid point with uncertainty ellipse:
+ -- Degrees of Latitude 3 octets
+ -- Degrees of Longitude 3 octets
+ -- Uncertainty semi-major axis 1 octet
+ -- Uncertainty semi-minor axis 1 octet
+ -- Angle of major axis 1 octet
+ -- Confidence 1 octet
+ -- Octets 2 to 14 for case (c) – Ellipsoid point with altitude and uncertainty ellipsoid
+ -- Degrees of Latitude 3 octets
+ -- Degrees of Longitude 3 octets
+ -- Altitude 2 octets
+ -- Uncertainty semi-major axis 1 octet
+ -- Uncertainty semi-minor axis 1 octet
+ -- Angle of major axis 1 octet
+ -- Uncertainty altitude 1 octet
+ -- Confidence 1 octet
+ -- Octets 2 to 13 for case (d) – Ellipsoid Arc
+ -- Degrees of Latitude 3 octets
+ -- Degrees of Longitude 3 octets
+ -- Inner radius 2 octets
+ -- Uncertainty radius 1 octet
+ -- Offset angle 1 octet
+ -- Included angle 1 octet
+ -- Confidence 1 octet
+ -- Octets 2 to 7 for case (e) – Ellipsoid Point
+ -- Degrees of Latitude 3 octets
+ -- Degrees of Longitude 3 octets
+
+ --
+ -- An Ext-GeographicalInformation parameter comprising more than one octet and
+ -- containing any other shape or an incorrect number of octets or coding according
+ -- to 3GPP TS 23.032 shall be treated as invalid data by a receiver.
+ --
+ -- An Ext-GeographicalInformation parameter comprising one octet shall be discarded
+ -- by the receiver if an Add-GeographicalInformation parameter is received
+ -- in the same message.
+ --
+ -- An Ext-GeographicalInformation parameter comprising one octet shall be treated as
+ -- invalid data by the receiver if an Add-GeographicalInformation parameter is not
+ -- received in the same message.
+
+maxExt-GeographicalInformation INTEGER ::= 20
+ -- the maximum length allows for further shapes in 3GPP TS 23.032 to be included in later
+ -- versions of 3GPP TS 29.002
+
+VelocityEstimate ::= OCTET STRING (SIZE (4..7))
+ -- Refers to Velocity description defined in 3GPP TS 23.032.
+ -- This is composed of 4 or more octets with an internal structure according to
+ -- 3GPP TS 23.032
+ -- Octet 1: Type of velocity, only the following types in 3GPP TS 23.032 are allowed:
+ -- (a) Horizontal Velocity
+ -- (b) Horizontal with Vertical Velocity
+ -- (c) Horizontal Velocity with Uncertainty
+ -- (d) Horizontal with Vertical Velocity and Uncertainty
+ -- For types Horizontal with Vertical Velocity and Horizontal with Vertical Velocity
+ -- and Uncertainty, the direction of the Vertical Speed is also included in Octet 1
+ -- Any other value in octet 1 shall be treated as invalid
+ -- Octets 2 to 4 for case (a) Horizontal velocity:
+ -- Bearing 1 octet
+ -- Horizontal Speed 2 octets
+ -- Octets 2 to 5 for case (b) – Horizontal with Vertical Velocity:
+ -- Bearing 1 octet
+ -- Horizontal Speed 2 octets
+ -- Vertical Speed 1 octet
+ -- Octets 2 to 5 for case (c) – Horizontal velocity with Uncertainty:
+ -- Bearing 1 octet
+ -- Horizontal Speed 2 octets
+ -- Uncertainty Speed 1 octet
+ -- Octets 2 to 7 for case (d) – Horizontal with Vertical Velocity and Uncertainty:
+ -- Bearing 1 octet
+ -- Horizontal Speed 2 octets
+ -- Vertical Speed 1 octet
+ -- Horizontal Uncertainty Speed 1 octet
+ -- Vertical Uncertainty Speed 1 octet
+
+PositioningDataInformation ::= OCTET STRING (SIZE (2..maxPositioningDataInformation))
+ -- Refers to the Positioning Data defined in 3GPP TS 49.031.
+ -- This is composed of 2 or more octets with an internal structure according to
+ -- 3GPP TS 49.031.
+
+maxPositioningDataInformation INTEGER ::= 10
+ --
+
+UtranPositioningDataInfo ::= OCTET STRING (SIZE (3..maxUtranPositioningDataInfo))
+ -- Refers to the Position Data defined in 3GPP TS 25.413.
+ -- This is composed of the positioningDataDiscriminator and the positioningDataSet
+ -- included in positionData as defined in 3GPP TS 25.413.
+
+maxUtranPositioningDataInfo INTEGER ::= 11
+ --
+
+Add-GeographicalInformation ::= OCTET STRING (SIZE (1..maxAdd-GeographicalInformation))
+ -- Refers to geographical Information defined in 3GPP TS 23.032.
+ -- This is composed of 1 or more octets with an internal structure according to
+ -- 3GPP TS 23.032
+ -- Octet 1: Type of shape, all the shapes defined in 3GPP TS 23.032 are allowed:
+ -- Octets 2 to n (where n is the total number of octets necessary to encode the shape
+ -- according to 3GPP TS 23.032) are used to encode the shape itself in accordance with the
+ -- encoding defined in 3GPP TS 23.032
+ --
+ -- An Add-GeographicalInformation parameter, whether valid or invalid, received
+ -- together with a valid Ext-GeographicalInformation parameter in the same message
+ -- shall be discarded.
+ --
+ -- An Add-GeographicalInformation parameter containing any shape not defined in
+ -- 3GPP TS 23.032 or an incorrect number of octets or coding according to
+ -- 3GPP TS 23.032 shall be treated as invalid data by a receiver if not received
+ -- together with a valid Ext-GeographicalInformation parameter in the same message.
+
+maxAdd-GeographicalInformation INTEGER ::= 91
+ -- the maximum length allows support for all the shapes currently defined in 3GPP TS 23.032
+
+SubscriberLocationReport-Arg ::= SEQUENCE {
+ lcs-Event LCS-Event,
+ lcs-ClientID LCS-ClientID,
+ lcsLocationInfo LCSLocationInfo,
+ msisdn [0] ISDN-AddressString OPTIONAL,
+ imsi [1] IMSI OPTIONAL,
+ imei [2] IMEI OPTIONAL,
+ na-ESRD [3] ISDN-AddressString OPTIONAL,
+ na-ESRK [4] ISDN-AddressString OPTIONAL,
+ locationEstimate [5] Ext-GeographicalInformation OPTIONAL,
+ ageOfLocationEstimate [6] AgeOfLocationInformation OPTIONAL,
+ slr-ArgExtensionContainer [7] SLR-ArgExtensionContainer OPTIONAL,
+ ... ,
+ add-LocationEstimate [8] Add-GeographicalInformation OPTIONAL,
+ deferredmt-lrData [9] Deferredmt-lrData OPTIONAL,
+ lcs-ReferenceNumber [10] LCS-ReferenceNumber OPTIONAL,
+ geranPositioningData [11] PositioningDataInformation OPTIONAL,
+ utranPositioningData [12] UtranPositioningDataInfo OPTIONAL,
+ cellIdOrSai [13] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
+ h-gmlc-Address [14] GSN-Address OPTIONAL,
+ lcsServiceTypeID [15] LCSServiceTypeID OPTIONAL,
+ sai-Present [17] NULL OPTIONAL,
+ pseudonymIndicator [18] NULL OPTIONAL,
+ accuracyFulfilmentIndicator [19] AccuracyFulfilmentIndicator OPTIONAL,
+ velocityEstimate [20] VelocityEstimate OPTIONAL,
+ sequenceNumber [21] SequenceNumber OPTIONAL,
+ periodicLDRInfo [22] PeriodicLDRInfo OPTIONAL,
+ mo-lrShortCircuitIndicator [23] NULL OPTIONAL }
+
+ -- one of msisdn or imsi is mandatory
+ -- a location estimate that is valid for the locationEstimate parameter should
+ -- be transferred in this parameter in preference to the add-LocationEstimate.
+ -- the deferredmt-lrData parameter shall be included if and only if the lcs-Event
+ -- indicates a deferredmt-lrResponse.
+ -- if the lcs-Event indicates a deferredmt-lrResponse then the locationEstimate
+ -- and the add-locationEstimate parameters shall not be sent if the
+ -- supportedGADShapes parameter had been received in ProvideSubscriberLocation-Arg
+ -- and the shape encoded in locationEstimate or add-LocationEstimate was not marked
+ -- as supported in supportedGADShapes. In such a case terminationCause
+ -- in deferredmt-lrData shall be present with value
+ -- shapeOfLocationEstimateNotSupported.
+ -- If a lcs event indicates deferred mt-lr response, the lcs-Reference number shall be
+ -- included.
+ -- sai-Present indicates that the cellIdOrSai parameter contains a Service Area Identity.
+
+Deferredmt-lrData ::= SEQUENCE {
+ deferredLocationEventType DeferredLocationEventType,
+ terminationCause [0] TerminationCause OPTIONAL,
+ lcsLocationInfo [1] LCSLocationInfo OPTIONAL,
+ ...}
+ -- lcsLocationInfo may be included only if a terminationCause is present
+ -- indicating mt-lrRestart.
+
+LCS-Event ::= ENUMERATED {
+ emergencyCallOrigination (0),
+ emergencyCallRelease (1),
+ mo-lr (2),
+ ...,
+ deferredmt-lrResponse (3) ,
+ deferredmo-lrTTTPInitiation (4) }
+ -- deferredmt-lrResponse is applicable to the delivery of a location estimate
+ -- for an LDR initiated earlier by either the network (via an MT-LR activate deferred
+ -- location) or the UE (via a deferred MO-LR TTTP initiation)
+ -- exception handling:
+ -- a SubscriberLocationReport-Arg containing an unrecognized LCS-Event
+ -- shall be rejected by a receiver with a return error cause of unexpected data value
+
+TerminationCause ::= ENUMERATED {
+ normal (0),
+ errorundefined (1),
+ internalTimeout (2),
+ congestion (3),
+ mt-lrRestart (4),
+ privacyViolation (5),
+ ...,
+ shapeOfLocationEstimateNotSupported (6) ,
+ subscriberTermination (7),
+ uETermination (8),
+ networkTermination (9) }
+-- mt-lrRestart shall be used to trigger the GMLC to restart the location procedure,
+-- either because the sending node knows that the terminal has moved under coverage
+-- of another MSC or SGSN (e.g. Send Identification received), or because the subscriber
+-- has been deregistered due to a Cancel Location received from HLR.
+--
+-- exception handling
+-- an unrecognized value shall be treated the same as value 1 (errorundefined)
+
+SequenceNumber ::= INTEGER (1..maxReportingAmount)
+
+SubscriberLocationReport-Res ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ na-ESRK [0] ISDN-AddressString OPTIONAL,
+ na-ESRD [1] ISDN-AddressString OPTIONAL,
+ h-gmlc-Address [2] GSN-Address OPTIONAL,
+ mo-lrShortCircuitIndicator [3] NULL OPTIONAL,
+ reportingPLMNList [4] ReportingPLMNList OPTIONAL,
+ lcs-ReferenceNumber [5] LCS-ReferenceNumber OPTIONAL }
+
+-- na-ESRK and na-ESRD are mutually exclusive
+--
+-- exception handling
+-- receipt of both na-ESRK and na-ESRD shall be treated the same as a return error
+
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-MS-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-MS-DataTypes.asn
new file mode 100644
index 000000000..9c12a028a
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-MS-DataTypes.asn
@@ -0,0 +1,2780 @@
+-- $Id: MAP-MS-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+-- 17.7.1 Mobile Service data types
+
+MAP-MS-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-MS-DataTypes (11) version11 (11)}
+
+DEFINITIONS
+
+IMPLICIT TAGS
+
+::=
+
+BEGIN
+
+EXPORTS
+
+ -- location registration types
+ UpdateLocationArg,
+ UpdateLocationRes,
+ CancelLocationArg,
+ CancelLocationRes,
+ PurgeMS-Arg,
+ PurgeMS-Res,
+ SendIdentificationArg,
+ SendIdentificationRes,
+ UpdateGprsLocationArg,
+ UpdateGprsLocationRes,
+ IST-SupportIndicator,
+ SupportedLCS-CapabilitySets,
+
+ -- gprs location registration types
+ GSN-Address,
+
+ -- handover types
+ ForwardAccessSignalling-Arg,
+ PrepareHO-Arg,
+ PrepareHO-Res,
+ PrepareSubsequentHO-Arg,
+ PrepareSubsequentHO-Res,
+ ProcessAccessSignalling-Arg,
+ SendEndSignal-Arg,
+ SendEndSignal-Res,
+
+ -- authentication management types
+ SendAuthenticationInfoArg,
+ SendAuthenticationInfoRes,
+ AuthenticationFailureReportArg,
+AuthenticationFailureReportRes,
+
+ -- security management types
+ Kc,
+ Cksn,
+
+ -- equipment management types
+ CheckIMEI-Arg,
+ CheckIMEI-Res,
+
+ -- subscriber management types
+ InsertSubscriberDataArg,
+ InsertSubscriberDataRes,
+ LSAIdentity,
+ DeleteSubscriberDataArg,
+ DeleteSubscriberDataRes,
+ Ext-QoS-Subscribed,
+ Ext2-QoS-Subscribed,
+ Ext3-QoS-Subscribed,
+ SubscriberData,
+ ODB-Data,
+ SubscriberStatus,
+ ZoneCodeList,
+ maxNumOfZoneCodes,
+ O-CSI,
+D-CSI,
+ O-BcsmCamelTDPCriteriaList,
+ T-BCSM-CAMEL-TDP-CriteriaList,
+ SS-CSI,
+ ServiceKey,
+ DefaultCallHandling,
+ CamelCapabilityHandling,
+ BasicServiceCriteria,
+ SupportedCamelPhases,
+ OfferedCamel4CSIs,
+ OfferedCamel4Functionalities,
+ maxNumOfCamelTDPData,
+ CUG-Index,
+ CUG-Info,
+ CUG-Interlock,
+ InterCUG-Restrictions,
+ IntraCUG-Options,
+ NotificationToMSUser,
+ QoS-Subscribed,
+IST-AlertTimerValue,
+ T-CSI,
+ T-BcsmTriggerDetectionPoint,
+APN,
+AdditionalInfo,
+
+ -- fault recovery types
+ ResetArg,
+ RestoreDataArg,
+ RestoreDataRes,
+
+-- provide subscriber info types
+GeographicalInformation,
+MS-Classmark2,
+GPRSMSClass,
+
+ -- subscriber information enquiry types
+ ProvideSubscriberInfoArg,
+ ProvideSubscriberInfoRes,
+ SubscriberInfo,
+ LocationInformation,
+ LocationInformationGPRS,
+ RAIdentity,
+ SubscriberState,
+ GPRSChargingID,
+MNPInfoRes,
+ RouteingNumber,
+
+ -- any time information enquiry types
+ AnyTimeInterrogationArg,
+ AnyTimeInterrogationRes,
+
+ -- any time information handling types
+ AnyTimeSubscriptionInterrogationArg,
+ AnyTimeSubscriptionInterrogationRes,
+ AnyTimeModificationArg,
+ AnyTimeModificationRes,
+
+ -- subscriber data modification notification types
+ NoteSubscriberDataModifiedArg,
+ NoteSubscriberDataModifiedRes,
+
+ -- gprs location information retrieval types
+ SendRoutingInfoForGprsArg,
+ SendRoutingInfoForGprsRes,
+
+ -- failure reporting types
+ FailureReportArg,
+ FailureReportRes,
+
+ -- gprs notification types
+ NoteMsPresentForGprsArg,
+ NoteMsPresentForGprsRes,
+
+ -- Mobility Management types
+NoteMM-EventArg,
+ NoteMM-EventRes,
+ NumberPortabilityStatus,
+ PagingArea,
+
+ -- VGCS / VBS types types
+GroupId,
+Long-GroupId,
+AdditionalSubscriptions
+
+;
+
+IMPORTS
+ maxNumOfSS,
+ SS-SubscriptionOption,
+ SS-List,
+ SS-ForBS-Code,
+ Password
+FROM MAP-SS-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SS-DataTypes (14) version11 (11)}
+
+ SS-Code
+FROM MAP-SS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
+
+ Ext-BearerServiceCode
+FROM MAP-BS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-BS-Code (20) version11 (11)}
+
+ Ext-TeleserviceCode
+FROM MAP-TS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-TS-Code (19) version11 (11)}
+
+ AddressString,
+ISDN-AddressString,
+ ISDN-SubaddressString,
+ FTN-AddressString,
+ AccessNetworkSignalInfo,
+ IMSI,
+ IMEI,
+ TMSI,
+ HLR-List,
+ LMSI,
+ Identity,
+ GlobalCellId,
+ CellGlobalIdOrServiceAreaIdOrLAI,
+ Ext-BasicServiceCode,
+ NAEA-PreferredCI,
+ EMLPP-Info,
+ MC-SS-Info,
+ SubscriberIdentity,
+ AgeOfLocationInformation,
+ LCSClientExternalID,
+ LCSClientInternalID,
+ Ext-SS-Status,
+ LCSServiceTypeID,
+ ASCI-CallReference,
+ TBCD-STRING,
+ LAIFixedLength,
+ PLMN-Id,
+EMLPP-Priority
+FROM MAP-CommonDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
+
+ ExtensionContainer
+FROM MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+
+ AbsentSubscriberDiagnosticSM
+FROM MAP-ER-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ER-DataTypes (17) version11 (11)}
+
+ TracePropagationList
+FROM MAP-OM-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-OM-DataTypes (12) version11 (11)}
+
+;
+
+-- location registration types
+
+UpdateLocationArg ::= SEQUENCE {
+ imsi IMSI,
+ msc-Number [1] ISDN-AddressString,
+ vlr-Number ISDN-AddressString,
+ lmsi [10] LMSI OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ vlr-Capability [6] VLR-Capability OPTIONAL,
+ informPreviousNetworkEntity [11] NULL OPTIONAL,
+ cs-LCS-NotSupportedByUE [12] NULL OPTIONAL,
+ v-gmlc-Address [2] GSN-Address OPTIONAL,
+ add-info [13] ADD-Info OPTIONAL,
+ pagingArea [14] PagingArea OPTIONAL,
+ skipSubscriberDataUpdate [15] NULL OPTIONAL
+ -- The skipSubscriberDataUpdate parameter in the UpdateLocationArg and the ADD-Info
+ -- structures carry the same semantic.
+ }
+
+VLR-Capability ::= SEQUENCE{
+ supportedCamelPhases [0] SupportedCamelPhases OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ solsaSupportIndicator [2] NULL OPTIONAL,
+ istSupportIndicator [1] IST-SupportIndicator OPTIONAL,
+ superChargerSupportedInServingNetworkEntity [3] SuperChargerInfo OPTIONAL,
+ longFTN-Supported [4] NULL OPTIONAL,
+ supportedLCS-CapabilitySets [5] SupportedLCS-CapabilitySets OPTIONAL,
+ offeredCamel4CSIs [6] OfferedCamel4CSIs OPTIONAL,
+ supportedRAT-TypesIndicator [7] SupportedRAT-Types OPTIONAL,
+ longGroupID-Supported [8] NULL OPTIONAL }
+
+SupportedRAT-Types::= BIT STRING {
+ utran (0),
+ geran (1),
+ gan (2),
+ i-hspa-evolution (3),
+ e-utran (4)} (SIZE (2..8))
+ -- exception handling: bits 5 to 7 shall be ignored if received and not understood
+
+
+
+SuperChargerInfo ::= CHOICE {
+ sendSubscriberData [0] NULL,
+ subscriberDataStored [1] AgeIndicator }
+
+AgeIndicator ::= OCTET STRING (SIZE (1..6))
+ -- The internal structure of this parameter is implementation specific.
+
+IST-SupportIndicator ::= ENUMERATED {
+ basicISTSupported (0),
+ istCommandSupported (1),
+ ...}
+-- exception handling:
+-- reception of values > 1 shall be mapped to ' istCommandSupported '
+
+SupportedLCS-CapabilitySets ::= BIT STRING {
+ lcsCapabilitySet1 (0),
+ lcsCapabilitySet2 (1),
+ lcsCapabilitySet3 (2),
+ lcsCapabilitySet4 (3) ,
+ lcsCapabilitySet5 (4) } (SIZE (2..16))
+-- Core network signalling capability set1 indicates LCS Release98 or Release99 version.
+-- Core network signalling capability set2 indicates LCS Release4.
+-- Core network signalling capability set3 indicates LCS Release5.
+-- Core network signalling capability set4 indicates LCS Release6.
+-- Core network signalling capability set5 indicates LCS Release7 or later version.
+-- A node shall mark in the BIT STRING all LCS capability sets it supports.
+-- If no bit is set then the sending node does not support LCS.
+-- If the parameter is not sent by an VLR then the VLR may support at most capability set1.
+-- If the parameter is not sent by an SGSN then no support for LCS is assumed.
+-- An SGSN is not allowed to indicate support of capability set1.
+-- Other bits than listed above shall be discarded.
+
+UpdateLocationRes ::= SEQUENCE {
+ hlr-Number ISDN-AddressString,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ add-Capability NULL OPTIONAL,
+ pagingArea-Capability [0]NULL OPTIONAL }
+
+ADD-Info ::= SEQUENCE {
+ imeisv [0] IMEI,
+ skipSubscriberDataUpdate [1] NULL OPTIONAL,
+ -- The skipSubscriberDataUpdate parameter in the UpdateLocationArg and the ADD-Info
+ -- structures carry the same semantic.
+ ...}
+
+
+PagingArea ::= SEQUENCE SIZE (1..5) OF LocationArea
+
+
+LocationArea ::= CHOICE {
+ laiFixedLength [0] LAIFixedLength,
+ lac [1] LAC}
+
+
+LAC ::= OCTET STRING (SIZE (2))
+ -- Refers to Location Area Code of the Location Area Identification defined in
+ -- 3GPP TS 23.003 [17].
+ -- Location Area Code according to 3GPP TS 24.008 [35]
+
+CancelLocationArg ::= [3] SEQUENCE {
+ identity Identity,
+ cancellationType CancellationType OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ typeOfUpdate [0] TypeOfUpdate OPTIONAL }
+
+TypeOfUpdate ::= ENUMERATED {
+ sgsn-change (0),
+ mme-change (1),
+ ...}
+ -- TypeOfUpdate shall be absent if CancellationType is different from updateProcedure
+
+CancellationType ::= ENUMERATED {
+ updateProcedure (0),
+ subscriptionWithdraw (1),
+ ...}
+ -- The HLR shall not send values other than listed above
+
+CancelLocationRes ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+PurgeMS-Arg ::= [3] SEQUENCE {
+ imsi IMSI,
+ vlr-Number [0] ISDN-AddressString OPTIONAL,
+ sgsn-Number [1] ISDN-AddressString OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+PurgeMS-Res ::= SEQUENCE {
+ freezeTMSI [0] NULL OPTIONAL,
+ freezeP-TMSI [1] NULL OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ freezeM-TMSI [2] NULL OPTIONAL }
+
+SendIdentificationArg ::= SEQUENCE {
+ tmsi TMSI,
+ numberOfRequestedVectors NumberOfRequestedVectors OPTIONAL,
+ -- within a dialogue numberOfRequestedVectors shall be present in
+ -- the first service request and shall not be present in subsequent service requests.
+ -- If received in a subsequent service request it shall be discarded.
+ segmentationProhibited NULL OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ msc-Number ISDN-AddressString OPTIONAL,
+ previous-LAI [0] LAIFixedLength OPTIONAL,
+ hopCounter [1] HopCounter OPTIONAL }
+
+HopCounter ::= INTEGER (0..3)
+
+SendIdentificationRes ::= [3] SEQUENCE {
+ imsi IMSI OPTIONAL,
+ -- IMSI shall be present in the first (or only) service response of a dialogue.
+ -- If multiple service requests are present in a dialogue then IMSI
+ -- shall not be present in any service response other than the first one.
+ authenticationSetList AuthenticationSetList OPTIONAL,
+ currentSecurityContext [2]CurrentSecurityContext OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...}
+
+-- authentication management types
+
+AuthenticationSetList ::= CHOICE {
+ tripletList [0] TripletList,
+ quintupletList [1] QuintupletList }
+
+TripletList ::= SEQUENCE SIZE (1..5) OF
+ AuthenticationTriplet
+
+QuintupletList ::= SEQUENCE SIZE (1..5) OF
+ AuthenticationQuintuplet
+
+AuthenticationTriplet ::= SEQUENCE {
+ rand RAND,
+ sres SRES,
+ kc Kc,
+ ...}
+
+AuthenticationQuintuplet ::= SEQUENCE {
+ rand RAND,
+ xres XRES,
+ ck CK,
+ ik IK,
+ autn AUTN,
+ ...}
+
+CurrentSecurityContext ::= CHOICE {
+ gsm-SecurityContextData [0] GSM-SecurityContextData,
+ umts-SecurityContextData [1] UMTS-SecurityContextData }
+
+GSM-SecurityContextData ::= SEQUENCE {
+ kc Kc,
+ cksn Cksn,
+ ... }
+
+UMTS-SecurityContextData ::= SEQUENCE {
+ ck CK,
+ ik IK,
+ ksi KSI,
+ ... }
+
+RAND ::= OCTET STRING (SIZE (16))
+
+SRES ::= OCTET STRING (SIZE (4))
+
+Kc ::= OCTET STRING (SIZE (8))
+
+XRES ::= OCTET STRING (SIZE (4..16))
+
+CK ::= OCTET STRING (SIZE (16))
+
+IK ::= OCTET STRING (SIZE (16))
+
+AUTN ::= OCTET STRING (SIZE (16))
+
+AUTS ::= OCTET STRING (SIZE (14))
+
+Cksn ::= OCTET STRING (SIZE (1))
+ -- The internal structure is defined in 3GPP TS 24.008
+
+KSI ::= OCTET STRING (SIZE (1))
+ -- The internal structure is defined in 3GPP TS 24.008
+
+AuthenticationFailureReportArg ::= SEQUENCE {
+ imsi IMSI,
+ failureCause FailureCause,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ re-attempt BOOLEAN OPTIONAL,
+ accessType AccessType OPTIONAL,
+ rand RAND OPTIONAL,
+ vlr-Number [0] ISDN-AddressString OPTIONAL,
+ sgsn-Number [1] ISDN-AddressString OPTIONAL }
+
+AccessType ::= ENUMERATED {
+ call (0),
+ emergencyCall (1),
+ locationUpdating (2),
+ supplementaryService (3),
+ shortMessage (4),
+ gprsAttach (5),
+ routingAreaUpdating (6),
+ serviceRequest (7),
+ pdpContextActivation (8),
+ pdpContextDeactivation (9),
+ ...,
+ gprsDetach (10)}
+ -- exception handling:
+ -- received values greater than 10 shall be ignored.
+
+AuthenticationFailureReportRes ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+FailureCause ::= ENUMERATED {
+ wrongUserResponse (0),
+ wrongNetworkSignature (1)}
+
+-- gprs location registration types
+
+UpdateGprsLocationArg ::= SEQUENCE {
+ imsi IMSI,
+ sgsn-Number ISDN-AddressString,
+ sgsn-Address GSN-Address,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ sgsn-Capability [0] SGSN-Capability OPTIONAL,
+ informPreviousNetworkEntity [1] NULL OPTIONAL,
+ ps-LCS-NotSupportedByUE [2] NULL OPTIONAL,
+ v-gmlc-Address [3] GSN-Address OPTIONAL,
+ add-info [4] ADD-Info OPTIONAL,
+ eps-info [5] EPS-Info OPTIONAL,
+ servingNodeTypeIndicator [6] NULL OPTIONAL,
+ skipSubscriberDataUpdate [7] NULL OPTIONAL,
+ usedRAT-Type [8] Used-RAT-Type OPTIONAL
+ }
+
+Used-RAT-Type::= ENUMERATED {
+ utran (0),
+ geran (1),
+ gan (2),
+ i-hspa-evolution (3),
+ e-utran (4),
+ ...}
+
+EPS-Info ::= CHOICE{
+ pdn-gw-update [0] PDN-GW-Update,
+ isr-Information [1] ISR-Information }
+
+PDN-GW-Update ::= SEQUENCE{
+ apn [0] APN OPTIONAL,
+ pdn-gw-Identity [1] PDN-GW-Identity OPTIONAL,
+ contextId [2] ContextId OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ... }
+
+ISR-Information::= BIT STRING {
+ updateMME (0),
+ cancelSGSN (1)} (SIZE (2..8))
+ -- exception handling: reception of unknown bit assignments in the
+ -- ISR-Information data type shall be discarded by the receiver
+
+SGSN-Capability ::= SEQUENCE{
+ solsaSupportIndicator NULL OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ... ,
+ superChargerSupportedInServingNetworkEntity [2] SuperChargerInfo OPTIONAL ,
+ gprsEnhancementsSupportIndicator [3] NULL OPTIONAL,
+ supportedCamelPhases [4] SupportedCamelPhases OPTIONAL,
+ supportedLCS-CapabilitySets [5] SupportedLCS-CapabilitySets OPTIONAL,
+ offeredCamel4CSIs [6] OfferedCamel4CSIs OPTIONAL,
+ smsCallBarringSupportIndicator [7] NULL OPTIONAL, supportedRAT-TypesIndicator [8] SupportedRAT-Types OPTIONAL,
+ supportedFeatures [9] SupportedFeatures OPTIONAL }
+
+SupportedFeatures::= BIT STRING {
+ odb-all (0),
+ odb-HPLMN-APN (1),
+ odb-VPLMN-APN (2),
+ regSub (3)} (SIZE (4..8))
+
+GSN-Address ::= OCTET STRING (SIZE (5..17))
+ -- Octets are coded according to TS 3GPP TS 23.003 [17]
+
+UpdateGprsLocationRes ::= SEQUENCE {
+ hlr-Number ISDN-AddressString,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ add-Capability NULL OPTIONAL,
+ sgsn-mmeSeparationSupported [0] NULL OPTIONAL }
+
+-- handover types
+
+ForwardAccessSignalling-Arg ::= [3] SEQUENCE {
+ an-APDU AccessNetworkSignalInfo,
+ integrityProtectionInfo [0] IntegrityProtectionInformation OPTIONAL,
+ encryptionInfo [1] EncryptionInformation OPTIONAL,
+ keyStatus [2] KeyStatus OPTIONAL,
+ allowedGSM-Algorithms [4] AllowedGSM-Algorithms OPTIONAL,
+ allowedUMTS-Algorithms [5] AllowedUMTS-Algorithms OPTIONAL,
+ radioResourceInformation [6] RadioResourceInformation OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...,
+ radioResourceList [7] RadioResourceList OPTIONAL,
+ bssmap-ServiceHandover [9] BSSMAP-ServiceHandover OPTIONAL,
+ ranap-ServiceHandover [8] RANAP-ServiceHandover OPTIONAL,
+ bssmap-ServiceHandoverList [10] BSSMAP-ServiceHandoverList OPTIONAL,
+ currentlyUsedCodec [11] Codec OPTIONAL,
+ iuSupportedCodecsList [12] SupportedCodecsList OPTIONAL,
+ rab-ConfigurationIndicator [13] NULL OPTIONAL,
+ iuSelectedCodec [14] Codec OPTIONAL,
+ alternativeChannelType [15] RadioResourceInformation OPTIONAL,
+ tracePropagationList [17] TracePropagationList OPTIONAL }
+
+AllowedGSM-Algorithms ::= OCTET STRING (SIZE (1))
+ -- internal structure is coded as Algorithm identifier octet from
+ -- Permitted Algorithms defined in 3GPP TS 48.008
+ -- A node shall mark all GSM algorithms that are allowed in MSC-B
+
+AllowedUMTS-Algorithms ::= SEQUENCE {
+ integrityProtectionAlgorithms [0] PermittedIntegrityProtectionAlgorithms OPTIONAL,
+ encryptionAlgorithms [1] PermittedEncryptionAlgorithms OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...}
+
+PermittedIntegrityProtectionAlgorithms ::=
+ OCTET STRING (SIZE (1..maxPermittedIntegrityProtectionAlgorithmsLength))
+ -- Octets contain a complete PermittedIntegrityProtectionAlgorithms data type
+ -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
+ -- mandated by 3GPP TS 25.413.
+ -- Padding bits are included, if needed, in the least significant bits of the
+ -- last octet of the octet string.
+
+
+maxPermittedIntegrityProtectionAlgorithmsLength INTEGER ::= 9
+
+PermittedEncryptionAlgorithms ::=
+ OCTET STRING (SIZE (1..maxPermittedEncryptionAlgorithmsLength))
+ -- Octets contain a complete PermittedEncryptionAlgorithms data type
+ -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
+ -- mandated by 3GPP TS 25.413
+ -- Padding bits are included, if needed, in the least significant bits of the
+ -- last octet of the octet string.
+
+
+maxPermittedEncryptionAlgorithmsLength INTEGER ::= 9
+
+KeyStatus ::= ENUMERATED {
+ old (0),
+ new (1),
+ ...}
+ -- exception handling:
+ -- received values in range 2-31 shall be treated as "old"
+ -- received values greater than 31 shall be treated as "new"
+
+PrepareHO-Arg ::= [3] SEQUENCE {
+ targetCellId [0] GlobalCellId OPTIONAL,
+ ho-NumberNotRequired NULL OPTIONAL,
+ targetRNCId [1] RNCId OPTIONAL,
+ an-APDU [2] AccessNetworkSignalInfo OPTIONAL,
+ multipleBearerRequested [3] NULL OPTIONAL,
+ imsi [4] IMSI OPTIONAL,
+ integrityProtectionInfo [5] IntegrityProtectionInformation OPTIONAL,
+ encryptionInfo [6] EncryptionInformation OPTIONAL,
+ radioResourceInformation [7] RadioResourceInformation OPTIONAL,
+ allowedGSM-Algorithms [9] AllowedGSM-Algorithms OPTIONAL,
+ allowedUMTS-Algorithms [10] AllowedUMTS-Algorithms OPTIONAL,
+ radioResourceList [11] RadioResourceList OPTIONAL,
+ extensionContainer [8] ExtensionContainer OPTIONAL,
+ ... ,
+ rab-Id [12] RAB-Id OPTIONAL,
+ bssmap-ServiceHandover [13] BSSMAP-ServiceHandover OPTIONAL,
+ ranap-ServiceHandover [14] RANAP-ServiceHandover OPTIONAL,
+ bssmap-ServiceHandoverList [15] BSSMAP-ServiceHandoverList OPTIONAL,
+ asciCallReference [20] ASCI-CallReference OPTIONAL,
+ geran-classmark [16] GERAN-Classmark OPTIONAL,
+ iuCurrentlyUsedCodec [17] Codec OPTIONAL,
+ iuSupportedCodecsList [18] SupportedCodecsList OPTIONAL,
+ rab-ConfigurationIndicator [19] NULL OPTIONAL,
+ uesbi-Iu [21] UESBI-Iu OPTIONAL,
+ imeisv [22] IMEI OPTIONAL,
+ alternativeChannelType [23] RadioResourceInformation OPTIONAL,
+ tracePropagationList [25] TracePropagationList OPTIONAL }
+
+BSSMAP-ServiceHandoverList ::= SEQUENCE SIZE (1.. maxNumOfServiceHandovers) OF
+ BSSMAP-ServiceHandoverInfo
+
+BSSMAP-ServiceHandoverInfo ::= SEQUENCE {
+ bssmap-ServiceHandover BSSMAP-ServiceHandover,
+ rab-Id RAB-Id,
+ -- RAB Identity is needed to relate the service handovers with the radio access bearers.
+ ...}
+
+maxNumOfServiceHandovers INTEGER ::= 7
+
+BSSMAP-ServiceHandover ::= OCTET STRING (SIZE (1))
+ -- Octets are coded according the Service Handover information element in
+ -- 3GPP TS 48.008.
+
+RANAP-ServiceHandover ::= OCTET STRING (SIZE (1))
+ -- Octet contains a complete Service-Handover data type
+ -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
+ -- mandated by 3GPP TS 25.413
+ -- Padding bits are included in the least significant bits.
+
+
+RadioResourceList ::= SEQUENCE SIZE (1.. maxNumOfRadioResources) OF
+ RadioResource
+
+RadioResource ::= SEQUENCE {
+ radioResourceInformation RadioResourceInformation,
+ rab-Id RAB-Id,
+ -- RAB Identity is needed to relate the radio resources with the radio access bearers.
+ ...}
+
+maxNumOfRadioResources INTEGER ::= 7
+
+PrepareHO-Res ::= [3] SEQUENCE {
+ handoverNumber [0] ISDN-AddressString OPTIONAL,
+ relocationNumberList [1] RelocationNumberList OPTIONAL,
+ an-APDU [2] AccessNetworkSignalInfo OPTIONAL,
+ multicallBearerInfo [3] MulticallBearerInfo OPTIONAL,
+ multipleBearerNotSupported NULL OPTIONAL,
+ selectedUMTS-Algorithms [5] SelectedUMTS-Algorithms OPTIONAL,
+ chosenRadioResourceInformation [6] ChosenRadioResourceInformation OPTIONAL,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ...,
+ iuSelectedCodec [7] Codec OPTIONAL,
+ iuAvailableCodecsList [8] CodecList OPTIONAL }
+
+SelectedUMTS-Algorithms ::= SEQUENCE {
+ integrityProtectionAlgorithm [0] ChosenIntegrityProtectionAlgorithm OPTIONAL,
+ encryptionAlgorithm [1] ChosenEncryptionAlgorithm OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...}
+
+ChosenIntegrityProtectionAlgorithm ::= OCTET STRING (SIZE (1))
+ -- Octet contains a complete IntegrityProtectionAlgorithm data type
+ -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
+ -- mandated by 3GPP TS 25.413
+ -- Padding bits are included in the least significant bits.
+
+ChosenEncryptionAlgorithm ::= OCTET STRING (SIZE (1))
+ -- Octet contains a complete EncryptionAlgorithm data type
+ -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
+ -- mandated by 3GPP TS 25.413
+ -- Padding bits are included in the least significant bits.
+
+ChosenRadioResourceInformation ::= SEQUENCE {
+ chosenChannelInfo [0] ChosenChannelInfo OPTIONAL,
+ chosenSpeechVersion [1] ChosenSpeechVersion OPTIONAL,
+ ...}
+
+ChosenChannelInfo ::= OCTET STRING (SIZE (1))
+ -- Octets are coded according the Chosen Channel information element in 3GPP TS 48.008
+
+ChosenSpeechVersion ::= OCTET STRING (SIZE (1))
+ -- Octets are coded according the Speech Version (chosen) information element in 3GPP TS
+ -- 48.008
+
+PrepareSubsequentHO-Arg ::= [3] SEQUENCE {
+ targetCellId [0] GlobalCellId OPTIONAL,
+ targetMSC-Number [1] ISDN-AddressString,
+ targetRNCId [2] RNCId OPTIONAL,
+ an-APDU [3] AccessNetworkSignalInfo OPTIONAL,
+ selectedRab-Id [4] RAB-Id OPTIONAL,
+ extensionContainer [5] ExtensionContainer OPTIONAL,
+ ...,
+ geran-classmark [6] GERAN-Classmark OPTIONAL,
+ rab-ConfigurationIndicator [7] NULL OPTIONAL }
+
+PrepareSubsequentHO-Res ::= [3] SEQUENCE {
+ an-APDU AccessNetworkSignalInfo,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+ProcessAccessSignalling-Arg ::= [3] SEQUENCE {
+ an-APDU AccessNetworkSignalInfo,
+ selectedUMTS-Algorithms [1] SelectedUMTS-Algorithms OPTIONAL,
+ selectedGSM-Algorithm [2] SelectedGSM-Algorithm OPTIONAL,
+ chosenRadioResourceInformation [3] ChosenRadioResourceInformation OPTIONAL,
+ selectedRab-Id [4] RAB-Id OPTIONAL,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...,
+ iUSelectedCodec [5] Codec OPTIONAL,
+ iuAvailableCodecsList [6] CodecList OPTIONAL }
+
+SupportedCodecsList ::= SEQUENCE {
+ utranCodecList [0] CodecList OPTIONAL,
+ geranCodecList [1] CodecList OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...}
+
+CodecList ::= SEQUENCE {
+ codec1 [1] Codec,
+ codec2 [2] Codec OPTIONAL,
+ codec3 [3] Codec OPTIONAL,
+ codec4 [4] Codec OPTIONAL,
+ codec5 [5] Codec OPTIONAL,
+ codec6 [6] Codec OPTIONAL,
+ codec7 [7] Codec OPTIONAL,
+ codec8 [8] Codec OPTIONAL,
+ extensionContainer [9] ExtensionContainer OPTIONAL,
+ ...}
+ -- Codecs are sent in priority order where codec1 has highest priority
+
+Codec ::= OCTET STRING (SIZE (1..4))
+
+ -- The internal structure is defined as follows:
+ -- octet 1 Coded as Codec Identification code in 3GPP TS 26.103
+ -- octets 2,3,4 Parameters for the Codec as defined in 3GPP TS
+ -- 26.103, if available, length depending on the codec
+
+GERAN-Classmark ::= OCTET STRING (SIZE (2..87))
+ -- Octets are coded according the GERAN Classmark information element in 3GPP TS 48.008
+
+SelectedGSM-Algorithm ::= OCTET STRING (SIZE (1))
+ -- internal structure is coded as Algorithm identifier octet from Chosen Encryption
+ -- Algorithm defined in 3GPP TS 48.008
+ -- A node shall mark only the selected GSM algorithm
+
+SendEndSignal-Arg ::= [3] SEQUENCE {
+ an-APDU AccessNetworkSignalInfo,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+SendEndSignal-Res ::= SEQUENCE {
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+RNCId ::= OCTET STRING (SIZE (7))
+ -- The internal structure is defined as follows:
+ -- octet 1 bits 4321 Mobile Country Code 1st digit
+ -- bits 8765 Mobile Country Code 2nd digit
+ -- octet 2 bits 4321 Mobile Country Code 3rd digit
+ -- bits 8765 Mobile Network Code 3rd digit
+ -- or filler (1111) for 2 digit MNCs
+ -- octet 3 bits 4321 Mobile Network Code 1st digit
+ -- bits 8765 Mobile Network Code 2nd digit
+ -- octets 4 and 5 Location Area Code according to 3GPP TS 24.008
+ -- octets 6 and 7 RNC Id value according to 3GPP TS 25.413
+
+RelocationNumberList ::= SEQUENCE SIZE (1..maxNumOfRelocationNumber) OF
+ RelocationNumber
+
+MulticallBearerInfo ::= INTEGER (1..maxNumOfRelocationNumber)
+
+RelocationNumber ::= SEQUENCE {
+ handoverNumber ISDN-AddressString,
+ rab-Id RAB-Id,
+ -- RAB Identity is needed to relate the calls with the radio access bearers.
+ ...}
+
+RAB-Id ::= INTEGER (1..maxNrOfRABs)
+
+maxNrOfRABs INTEGER ::= 255
+
+maxNumOfRelocationNumber INTEGER ::= 7
+
+RadioResourceInformation ::= OCTET STRING (SIZE (3..13))
+ -- Octets are coded according the Channel Type information element in 3GPP TS 48.008
+
+IntegrityProtectionInformation ::= OCTET STRING (SIZE (18..maxNumOfIntegrityInfo))
+ -- Octets contain a complete IntegrityProtectionInformation data type
+ -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
+ -- mandated by 3GPP TS 25.413
+ -- Padding bits are included, if needed, in the least significant bits of the
+ -- last octet of the octet string.
+
+maxNumOfIntegrityInfo INTEGER ::= 100
+
+EncryptionInformation ::= OCTET STRING (SIZE (18..maxNumOfEncryptionInfo))
+ -- Octets contain a complete EncryptionInformation data type
+ -- as defined in 3GPP TS 25.413, encoded according to the encoding scheme
+ -- mandated by 3GPP TS 25.413
+ -- Padding bits are included, if needed, in the least significant bits of the
+ -- last octet of the octet string.
+
+maxNumOfEncryptionInfo INTEGER ::= 100
+
+-- authentication management types
+
+SendAuthenticationInfoArg ::= SEQUENCE {
+ imsi [0] IMSI,
+ numberOfRequestedVectors NumberOfRequestedVectors,
+ segmentationProhibited NULL OPTIONAL,
+ immediateResponsePreferred [1] NULL OPTIONAL,
+ re-synchronisationInfo Re-synchronisationInfo OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...,
+ requestingNodeType [3] RequestingNodeType OPTIONAL,
+ requestingPLMN-Id [4] PLMN-Id OPTIONAL,
+ numberOfRequestedAdditional-Vectors [5] NumberOfRequestedVectors OPTIONAL,
+ additionalVectorsAreForEPS [6] NULL OPTIONAL }
+
+
+NumberOfRequestedVectors ::= INTEGER (1..5)
+
+Re-synchronisationInfo ::= SEQUENCE {
+ rand RAND,
+ auts AUTS,
+ ...}
+
+SendAuthenticationInfoRes ::= [3] SEQUENCE {
+ authenticationSetList AuthenticationSetList OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ eps-AuthenticationSetList [2] EPS-AuthenticationSetList OPTIONAL }
+
+EPS-AuthenticationSetList ::= SEQUENCE SIZE (1..5) OF
+ EPC-AV
+
+EPC-AV ::= SEQUENCE {
+ rand RAND,
+ xres XRES,
+ autn AUTN,
+ kasme KASME,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+KASME ::= OCTET STRING (SIZE (16))
+
+RequestingNodeType ::= ENUMERATED {
+ vlr (0),
+ sgsn (1),
+ ...,
+ s-cscf (2),
+ bsf (3),
+ gan-aaa-server (4),
+ wlan-aaa-server (5),
+ mme (16),
+ mme-sgsn (17)
+ }
+ -- the values 2, 3, 4 and 5 shall not be used on the MAP-D or Gr interfaces
+ -- exception handling:
+ -- received values in the range (6-15) shall be treated as "vlr"
+ -- received values greater than 17 shall be treated as "sgsn"
+
+-- equipment management types
+
+CheckIMEI-Arg ::= SEQUENCE {
+ imei IMEI,
+ requestedEquipmentInfo RequestedEquipmentInfo,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+CheckIMEI-Res ::= SEQUENCE {
+ equipmentStatus EquipmentStatus OPTIONAL,
+ bmuef UESBI-Iu OPTIONAL,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+RequestedEquipmentInfo::= BIT STRING {
+ equipmentStatus (0),
+ bmuef (1)} (SIZE (2..8))
+ -- exception handling: reception of unknown bit assignments in the
+ -- RequestedEquipmentInfo data type shall be discarded by the receiver
+
+UESBI-Iu ::= SEQUENCE {
+ uesbi-IuA [0] UESBI-IuA OPTIONAL,
+ uesbi-IuB [1] UESBI-IuB OPTIONAL,
+ ...}
+
+UESBI-IuA ::= BIT STRING (SIZE(1..128))
+-- See 3GPP TS 25.413
+
+UESBI-IuB ::= BIT STRING (SIZE(1..128))
+-- See 3GPP TS 25.413
+
+EquipmentStatus ::= ENUMERATED {
+ whiteListed (0),
+ blackListed (1),
+ greyListed (2)}
+
+-- subscriber management types
+
+InsertSubscriberDataArg ::= SEQUENCE {
+ imsi [0] IMSI OPTIONAL,
+ COMPONENTS OF SubscriberData,
+ extensionContainer [14] ExtensionContainer OPTIONAL,
+ ... ,
+ naea-PreferredCI [15] NAEA-PreferredCI OPTIONAL,
+ -- naea-PreferredCI is included at the discretion of the HLR operator.
+ gprsSubscriptionData [16] GPRSSubscriptionData OPTIONAL,
+ roamingRestrictedInSgsnDueToUnsupportedFeature [23] NULL
+ OPTIONAL,
+ networkAccessMode [24] NetworkAccessMode OPTIONAL,
+ lsaInformation [25] LSAInformation OPTIONAL,
+ lmu-Indicator [21] NULL OPTIONAL,
+ lcsInformation [22] LCSInformation OPTIONAL,
+ istAlertTimer [26] IST-AlertTimerValue OPTIONAL,
+ superChargerSupportedInHLR [27] AgeIndicator OPTIONAL,
+ mc-SS-Info [28] MC-SS-Info OPTIONAL,
+ cs-AllocationRetentionPriority [29] CS-AllocationRetentionPriority OPTIONAL,
+ sgsn-CAMEL-SubscriptionInfo [17] SGSN-CAMEL-SubscriptionInfo OPTIONAL,
+ chargingCharacteristics [18] ChargingCharacteristics OPTIONAL,
+ accessRestrictionData [19] AccessRestrictionData OPTIONAL,
+ ics-Indicator [20] BOOLEAN OPTIONAL,
+ eps-SubscriptionData [31] EPS-SubscriptionData OPTIONAL,
+ csg-SubscriptionDataList [32] CSG-SubscriptionDataList OPTIONAL }
+ -- If the Network Access Mode parameter is sent, it shall be present only in
+ -- the first sequence if seqmentation is used
+
+CSG-SubscriptionDataList ::= SEQUENCE SIZE (1..50) OF
+ CSG-SubscriptionData
+
+CSG-SubscriptionData ::= SEQUENCE {
+ csg-Id CSG-Id,
+ expirationDate Time OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+CSG-Id ::= BIT STRING (SIZE (27))
+ -- coded according to 3GPP TS 23.003 [17].
+
+Time ::= OCTET STRING (SIZE (4))
+ -- Octets are coded according to IETF RFC 3588 [139]
+
+
+EPS-SubscriptionData ::= SEQUENCE {
+ apn-oi-Replacement [0] APN-OI-Replacement OPTIONAL,
+ rfsp-id [2] RFSP-ID OPTIONAL,
+ ambr [3] AMBR OPTIONAL,
+ apn-ConfigurationProfile [4] APN-ConfigurationProfile OPTIONAL,
+ stn-sr [6] ISDN-AddressString OPTIONAL,
+ extensionContainer [5] ExtensionContainer OPTIONAL,
+ ... }
+
+APN-OI-Replacement ::= OCTET STRING (SIZE (9..100))
+ -- Octets are coded as APN Operator Identifier according to TS 3GPP TS 23.003 [17]
+
+RFSP-ID ::= INTEGER (1..256)
+
+APN-ConfigurationProfile ::= SEQUENCE {
+ defaultContext ContextId,
+ completeDataListIncluded NULL OPTIONAL,
+ -- If segmentation is used, completeDataListIncluded may only be present in the
+ -- first segment of APN-ConfigurationProfile.
+ epsDataList [1] EPS-DataList,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ... }
+
+EPS-DataList ::= SEQUENCE SIZE (1..maxNumOfAPN-Configurations) OF
+ APN-Configuration
+
+
+maxNumOfAPN-Configurations INTEGER ::= 50
+
+
+APN-Configuration ::= SEQUENCE {
+ contextId [0] ContextId,
+ servedPartyIP-Address [1] PDP-Address OPTIONAL,
+ apn [2] APN,
+ eps-qos-Subscribed [3] EPS-QoS-Subscribed,
+ pdn-gw-Identity [4] PDN-GW-Identity OPTIONAL,
+ pdn-gw-AllocationType [5] PDN-GW-AllocationType OPTIONAL,
+ vplmnAddressAllowed [6] NULL OPTIONAL,
+ chargingCharacteristics [7] ChargingCharacteristics OPTIONAL,
+ ambr [8] AMBR OPTIONAL,
+ specificAPNInfoList [9] SpecificAPNInfoList OPTIONAL, extensionContainer [10] ExtensionContainer OPTIONAL,
+ ... }
+
+EPS-QoS-Subscribed ::= SEQUENCE {
+ qos-Class-Identifier [0] QoS-Class-Identifier,
+ allocation-Retention-Priority [1] Allocation-Retention-Priority,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ... }
+
+AMBR ::= SEQUENCE {
+ max-RequestedBandwidth-UL [0] Bandwidth,
+ max-RequestedBandwidth-DL [1] Bandwidth,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ... }
+
+
+SpecificAPNInfoList ::= SEQUENCE SIZE (1..maxNumOfSpecificAPNInfos) OF
+ SpecificAPNInfo
+
+maxNumOfSpecificAPNInfos INTEGER ::= 50
+
+SpecificAPNInfo ::= SEQUENCE {
+ apn [0] APN,
+ pdn-gw-Identity [1] PDN-GW-Identity,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ... }
+
+Bandwidth ::= INTEGER
+ -- bits per second
+
+QoS-Class-Identifier ::= INTEGER (1..9)
+ -- values are defined in 3GPP TS 29.212
+
+
+
+Allocation-Retention-Priority ::= SEQUENCE {
+ priority-level [0] INTEGER,
+ pre-emption-capability [1] BOOLEAN OPTIONAL,
+ pre-emption-vulnerability [2] BOOLEAN OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ... }
+
+PDN-GW-Identity ::= SEQUENCE {
+ pdn-gw-ipv4-Address [0] PDP-Address OPTIONAL,
+ pdn-gw-ipv6-Address [1] PDP-Address OPTIONAL,
+ pdn-gw-name [2] FQDN OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ... }
+
+FQDN ::= OCTET STRING (SIZE (9..100))
+
+
+PDN-GW-AllocationType ::= ENUMERATED {
+ static (0),
+ dynamic (1)}
+
+
+AccessRestrictionData ::= BIT STRING {
+ utranNotAllowed (0),
+ geranNotAllowed (1),
+ ganNotAllowed (2),
+ i-hspa-evolutionNotAllowed (3),
+ e-utranNotAllowed (4),
+ ho-toNon3GPP-AccessNotAllowed (5) } (SIZE (2..8))
+ -- exception handling:
+ -- access restriction data related to an access type not supported by a node
+ -- shall be ignored
+ -- bits 6 to 7 shall be ignored if received and not understood
+
+
+CS-AllocationRetentionPriority ::= OCTET STRING (SIZE (1))
+ -- This data type encodes each priority level defined in TS 23.107 as the binary value
+ -- of the priority level.
+
+IST-AlertTimerValue ::= INTEGER (15..255)
+
+LCSInformation ::= SEQUENCE {
+ gmlc-List [0] GMLC-List OPTIONAL,
+ lcs-PrivacyExceptionList [1] LCS-PrivacyExceptionList OPTIONAL,
+ molr-List [2] MOLR-List OPTIONAL,
+ ...,
+ add-lcs-PrivacyExceptionList [3] LCS-PrivacyExceptionList OPTIONAL }
+ -- add-lcs-PrivacyExceptionList may be sent only if lcs-PrivacyExceptionList is
+ -- present and contains four instances of LCS-PrivacyClass. If the mentioned condition
+ -- is not satisfied the receiving node shall discard add-lcs-PrivacyExceptionList.
+ -- If an LCS-PrivacyClass is received both in lcs-PrivacyExceptionList and in
+ -- add-lcs-PrivacyExceptionList with the same SS-Code, then the error unexpected
+ -- data value shall be returned.
+
+GMLC-List ::= SEQUENCE SIZE (1..maxNumOfGMLC) OF
+ ISDN-AddressString
+ -- if segmentation is used, the complete GMLC-List shall be sent in one segment
+
+maxNumOfGMLC INTEGER ::= 5
+
+NetworkAccessMode ::= ENUMERATED {
+ packetAndCircuit (0),
+ onlyCircuit (1),
+ onlyPacket (2),
+ ...}
+ -- if unknown values are received in NetworkAccessMode
+ -- they shall be discarded.
+
+GPRSDataList ::= SEQUENCE SIZE (1..maxNumOfPDP-Contexts) OF
+ PDP-Context
+
+maxNumOfPDP-Contexts INTEGER ::= 50
+
+PDP-Context ::= SEQUENCE {
+ pdp-ContextId ContextId,
+ pdp-Type [16] PDP-Type,
+ pdp-Address [17] PDP-Address OPTIONAL,
+ qos-Subscribed [18] QoS-Subscribed,
+ vplmnAddressAllowed [19] NULL OPTIONAL,
+ apn [20] APN,
+ extensionContainer [21] ExtensionContainer OPTIONAL,
+ ... ,
+ ext-QoS-Subscribed [0] Ext-QoS-Subscribed OPTIONAL,
+ pdp-ChargingCharacteristics [1] ChargingCharacteristics OPTIONAL,
+ ext2-QoS-Subscribed [2] Ext2-QoS-Subscribed OPTIONAL,
+ -- ext2-QoS-Subscribed may be present only if ext-QoS-Subscribed is present.
+ ext3-QoS-Subscribed [3] Ext3-QoS-Subscribed OPTIONAL
+ -- ext3-QoS-Subscribed may be present only if ext2-QoS-Subscribed is present.
+ }
+
+ContextId ::= INTEGER (1..maxNumOfPDP-Contexts)
+
+GPRSSubscriptionData ::= SEQUENCE {
+ completeDataListIncluded NULL OPTIONAL,
+ -- If segmentation is used, completeDataListIncluded may only be present in the
+ -- first segment of GPRSSubscriptionData.
+ gprsDataList [1] GPRSDataList,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ... }
+
+SGSN-CAMEL-SubscriptionInfo ::= SEQUENCE {
+ gprs-CSI [0] GPRS-CSI OPTIONAL,
+ mo-sms-CSI [1] SMS-CSI OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...,
+ mt-sms-CSI [3] SMS-CSI OPTIONAL,
+ mt-smsCAMELTDP-CriteriaList [4] MT-smsCAMELTDP-CriteriaList OPTIONAL,
+ mg-csi [5] MG-CSI OPTIONAL
+ }
+
+GPRS-CSI ::= SEQUENCE {
+ gprs-CamelTDPDataList [0] GPRS-CamelTDPDataList OPTIONAL,
+ camelCapabilityHandling [1] CamelCapabilityHandling OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ notificationToCSE [3] NULL OPTIONAL,
+ csi-Active [4] NULL OPTIONAL,
+ ...}
+-- notificationToCSE and csi-Active shall not be present when GPRS-CSI is sent to SGSN.
+-- They may only be included in ATSI/ATM ack/NSDC message.
+-- GPRS-CamelTDPData and camelCapabilityHandling shall be present in
+-- the GPRS-CSI sequence.
+-- If GPRS-CSI is segmented, gprs-CamelTDPDataList and camelCapabilityHandling shall be
+-- present in the first segment
+
+GPRS-CamelTDPDataList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
+ GPRS-CamelTDPData
+-- GPRS-CamelTDPDataList shall not contain more than one instance of
+-- GPRS-CamelTDPData containing the same value for gprs-TriggerDetectionPoint.
+
+GPRS-CamelTDPData ::= SEQUENCE {
+ gprs-TriggerDetectionPoint [0] GPRS-TriggerDetectionPoint,
+ serviceKey [1] ServiceKey,
+ gsmSCF-Address [2] ISDN-AddressString,
+ defaultSessionHandling [3] DefaultGPRS-Handling,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ...
+ }
+
+DefaultGPRS-Handling ::= ENUMERATED {
+ continueTransaction (0) ,
+ releaseTransaction (1) ,
+ ...}
+-- exception handling:
+-- reception of values in range 2-31 shall be treated as "continueTransaction"
+-- reception of values greater than 31 shall be treated as "releaseTransaction"
+
+GPRS-TriggerDetectionPoint ::= ENUMERATED {
+ attach (1),
+ attachChangeOfPosition (2),
+ pdp-ContextEstablishment (11),
+ pdp-ContextEstablishmentAcknowledgement (12),
+ pdp-ContextChangeOfPosition (14),
+ ... }
+-- exception handling:
+-- For GPRS-CamelTDPData sequences containing this parameter with any
+-- other value than the ones listed the receiver shall ignore the whole
+-- GPRS-CamelTDPDatasequence.
+
+APN ::= OCTET STRING (SIZE (2..63))
+ -- Octets are coded according to TS 3GPP TS 23.003 [17]
+
+PDP-Type ::= OCTET STRING (SIZE (2))
+ -- Octets are coded according to TS 3GPP TS 29.060 [105]
+
+PDP-Address ::= OCTET STRING (SIZE (1..16))
+ -- Octets are coded according to TS 3GPP TS 29.060 [105]
+
+ -- The possible size values are:
+ -- 1-7 octets X.25 address type
+ -- 4 octets IPv4 address type
+ -- 16 octets Ipv6 address type
+
+QoS-Subscribed ::= OCTET STRING (SIZE (3))
+ -- Octets are coded according to TS 3GPP TS 24.008 [35] Quality of Service Octets
+ -- 3-5.
+
+Ext-QoS-Subscribed ::= OCTET STRING (SIZE (1..9))
+ -- OCTET 1:
+ -- Allocation/Retention Priority (This octet encodes each priority level defined in
+ -- 23.107 as the binary value of the priority level, declaration in 29.060)
+ -- Octets 2-9 are coded according to 3GPP TS 24.008 [35] Quality of Service Octets
+ -- 6-13.
+
+Ext2-QoS-Subscribed ::= OCTET STRING (SIZE (1..3))
+ -- Octets 1-3 are coded according to 3GPP TS 24.008 [35] Quality of Service Octets 14-16.
+ -- If Quality of Service information is structured with 14 octet length, then
+ -- Octet 1 is coded according to 3GPP TS 24.008 [35] Quality of Service Octet 14.
+
+Ext3-QoS-Subscribed ::= OCTET STRING (SIZE (1..2))
+ -- Octets 1-2 are coded according to 3GPP TS 24.008 [35] Quality of Service Octets 17-18.
+
+ChargingCharacteristics ::= OCTET STRING (SIZE (2))
+ -- Octets are coded according to 3GPP TS 32.215.
+
+LSAOnlyAccessIndicator ::= ENUMERATED {
+ accessOutsideLSAsAllowed (0),
+ accessOutsideLSAsRestricted (1)}
+
+LSADataList ::= SEQUENCE SIZE (1..maxNumOfLSAs) OF
+ LSAData
+
+maxNumOfLSAs INTEGER ::= 20
+
+LSAData ::= SEQUENCE {
+ lsaIdentity [0] LSAIdentity,
+ lsaAttributes [1] LSAAttributes,
+ lsaActiveModeIndicator [2] NULL OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...}
+
+LSAInformation ::= SEQUENCE {
+ completeDataListIncluded NULL OPTIONAL,
+
+ -- If segmentation is used, completeDataListIncluded may only be present in the
+ -- first segment.
+ lsaOnlyAccessIndicator [1] LSAOnlyAccessIndicator OPTIONAL,
+ lsaDataList [2] LSADataList OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...}
+
+LSAIdentity ::= OCTET STRING (SIZE (3))
+ -- Octets are coded according to TS 3GPP TS 23.003 [17]
+
+LSAAttributes ::= OCTET STRING (SIZE (1))
+ -- Octets are coded according to TS 3GPP TS 48.008 [49]
+
+SubscriberData ::= SEQUENCE {
+ msisdn [1] ISDN-AddressString OPTIONAL,
+ category [2] Category OPTIONAL,
+ subscriberStatus [3] SubscriberStatus OPTIONAL,
+ bearerServiceList [4] BearerServiceList OPTIONAL,
+ -- The exception handling for reception of unsupported / not allocated
+ -- bearerServiceCodes is defined in section 8.8.1
+ teleserviceList [6] TeleserviceList OPTIONAL,
+ -- The exception handling for reception of unsupported / not allocated
+ -- teleserviceCodes is defined in section 8.8.1
+ provisionedSS [7] Ext-SS-InfoList OPTIONAL,
+ odb-Data [8] ODB-Data OPTIONAL,
+ roamingRestrictionDueToUnsupportedFeature [9] NULL OPTIONAL,
+ regionalSubscriptionData [10] ZoneCodeList OPTIONAL,
+ vbsSubscriptionData [11] VBSDataList OPTIONAL,
+ vgcsSubscriptionData [12] VGCSDataList OPTIONAL,
+ vlrCamelSubscriptionInfo [13] VlrCamelSubscriptionInfo OPTIONAL
+ }
+
+Category ::= OCTET STRING (SIZE (1))
+ -- The internal structure is defined in ITU-T Rec Q.763.
+
+SubscriberStatus ::= ENUMERATED {
+ serviceGranted (0),
+ operatorDeterminedBarring (1)}
+
+BearerServiceList ::= SEQUENCE SIZE (1..maxNumOfBearerServices) OF
+ Ext-BearerServiceCode
+
+maxNumOfBearerServices INTEGER ::= 50
+
+TeleserviceList ::= SEQUENCE SIZE (1..maxNumOfTeleservices) OF
+ Ext-TeleserviceCode
+
+maxNumOfTeleservices INTEGER ::= 20
+
+ODB-Data ::= SEQUENCE {
+ odb-GeneralData ODB-GeneralData,
+ odb-HPLMN-Data ODB-HPLMN-Data OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+ODB-GeneralData ::= BIT STRING {
+ allOG-CallsBarred (0),
+ internationalOGCallsBarred (1),
+ internationalOGCallsNotToHPLMN-CountryBarred (2),
+ interzonalOGCallsBarred (6),
+ interzonalOGCallsNotToHPLMN-CountryBarred (7),
+ interzonalOGCallsAndInternationalOGCallsNotToHPLMN-CountryBarred (8),
+ premiumRateInformationOGCallsBarred (3),
+ premiumRateEntertainementOGCallsBarred (4),
+ ss-AccessBarred (5),
+ allECT-Barred (9),
+ chargeableECT-Barred (10),
+ internationalECT-Barred (11),
+ interzonalECT-Barred (12),
+ doublyChargeableECT-Barred (13),
+ multipleECT-Barred (14),
+ allPacketOrientedServicesBarred (15),
+ roamerAccessToHPLMN-AP-Barred (16),
+ roamerAccessToVPLMN-AP-Barred (17),
+ roamingOutsidePLMNOG-CallsBarred (18),
+ allIC-CallsBarred (19),
+ roamingOutsidePLMNIC-CallsBarred (20),
+ roamingOutsidePLMNICountryIC-CallsBarred (21),
+ roamingOutsidePLMN-Barred (22),
+ roamingOutsidePLMN-CountryBarred (23),
+ registrationAllCF-Barred (24),
+ registrationCFNotToHPLMN-Barred (25),
+ registrationInterzonalCF-Barred (26),
+ registrationInterzonalCFNotToHPLMN-Barred (27),
+ registrationInternationalCF-Barred (28)} (SIZE (15..32))
+ -- exception handling: reception of unknown bit assignments in the
+ -- ODB-GeneralData type shall be treated like unsupported ODB-GeneralData
+ -- When the ODB-GeneralData type is removed from the HLR for a given subscriber,
+ -- in NoteSubscriberDataModified operation sent toward the gsmSCF
+ -- all bits shall be set to "O".
+
+ODB-HPLMN-Data ::= BIT STRING {
+ plmn-SpecificBarringType1 (0),
+ plmn-SpecificBarringType2 (1),
+ plmn-SpecificBarringType3 (2),
+ plmn-SpecificBarringType4 (3)} (SIZE (4..32))
+ -- exception handling: reception of unknown bit assignments in the
+ -- ODB-HPLMN-Data type shall be treated like unsupported ODB-HPLMN-Data
+ -- When the ODB-HPLMN-Data type is removed from the HLR for a given subscriber,
+ -- in NoteSubscriberDataModified operation sent toward the gsmSCF
+ -- all bits shall be set to "O".
+
+Ext-SS-InfoList ::= SEQUENCE SIZE (1..maxNumOfSS) OF
+ Ext-SS-Info
+
+Ext-SS-Info ::= CHOICE {
+ forwardingInfo [0] Ext-ForwInfo,
+ callBarringInfo [1] Ext-CallBarInfo,
+ cug-Info [2] CUG-Info,
+ ss-Data [3] Ext-SS-Data,
+ emlpp-Info [4] EMLPP-Info}
+
+Ext-ForwInfo ::= SEQUENCE {
+ ss-Code SS-Code,
+ forwardingFeatureList Ext-ForwFeatureList,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+Ext-ForwFeatureList ::= SEQUENCE SIZE (1..maxNumOfExt-BasicServiceGroups) OF
+ Ext-ForwFeature
+
+Ext-ForwFeature ::= SEQUENCE {
+ basicService Ext-BasicServiceCode OPTIONAL,
+ ss-Status [4] Ext-SS-Status,
+ forwardedToNumber [5] ISDN-AddressString OPTIONAL,
+ -- When this data type is sent from an HLR which supports CAMEL Phase 2
+ -- to a VLR that supports CAMEL Phase 2 the VLR shall not check the
+ -- format of the number
+ forwardedToSubaddress [8] ISDN-SubaddressString OPTIONAL,
+ forwardingOptions [6] Ext-ForwOptions OPTIONAL,
+ noReplyConditionTime [7] Ext-NoRepCondTime OPTIONAL,
+ extensionContainer [9] ExtensionContainer OPTIONAL,
+ ...,
+ longForwardedToNumber [10] FTN-AddressString OPTIONAL }
+
+Ext-ForwOptions ::= OCTET STRING (SIZE (1..5))
+
+ -- OCTET 1:
+
+ -- bit 8: notification to forwarding party
+ -- 0 no notification
+ -- 1 notification
+
+ -- bit 7: redirecting presentation
+ -- 0 no presentation
+ -- 1 presentation
+
+ -- bit 6: notification to calling party
+ -- 0 no notification
+ -- 1 notification
+
+ -- bit 5: 0 (unused)
+
+ -- bits 43: forwarding reason
+ -- 00 ms not reachable
+ -- 01 ms busy
+ -- 10 no reply
+ -- 11 unconditional
+
+ -- bits 21: 00 (unused)
+
+ -- OCTETS 2-5: reserved for future use. They shall be discarded if
+ -- received and not understood.
+
+Ext-NoRepCondTime ::= INTEGER (1..100)
+ -- Only values 5-30 are used.
+ -- Values in the ranges 1-4 and 31-100 are reserved for future use
+ -- If received:
+ -- values 1-4 shall be mapped on to value 5
+ -- values 31-100 shall be mapped on to value 30
+
+Ext-CallBarInfo ::= SEQUENCE {
+ ss-Code SS-Code,
+ callBarringFeatureList Ext-CallBarFeatureList,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+Ext-CallBarFeatureList ::= SEQUENCE SIZE (1..maxNumOfExt-BasicServiceGroups) OF
+ Ext-CallBarringFeature
+
+Ext-CallBarringFeature ::= SEQUENCE {
+ basicService Ext-BasicServiceCode OPTIONAL,
+ ss-Status [4] Ext-SS-Status,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+CUG-Info ::= SEQUENCE {
+ cug-SubscriptionList CUG-SubscriptionList,
+ cug-FeatureList CUG-FeatureList OPTIONAL,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+CUG-SubscriptionList ::= SEQUENCE SIZE (0..maxNumOfCUG) OF
+ CUG-Subscription
+
+CUG-Subscription ::= SEQUENCE {
+ cug-Index CUG-Index,
+ cug-Interlock CUG-Interlock,
+ intraCUG-Options IntraCUG-Options,
+ basicServiceGroupList Ext-BasicServiceGroupList OPTIONAL,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+CUG-Index ::= INTEGER (0..32767)
+ -- The internal structure is defined in ETS 300 138.
+
+CUG-Interlock ::= OCTET STRING (SIZE (4))
+
+IntraCUG-Options ::= ENUMERATED {
+ noCUG-Restrictions (0),
+ cugIC-CallBarred (1),
+ cugOG-CallBarred (2)}
+
+maxNumOfCUG INTEGER ::= 10
+
+CUG-FeatureList ::= SEQUENCE SIZE (1..maxNumOfExt-BasicServiceGroups) OF
+ CUG-Feature
+
+Ext-BasicServiceGroupList ::= SEQUENCE SIZE (1..maxNumOfExt-BasicServiceGroups) OF
+ Ext-BasicServiceCode
+
+maxNumOfExt-BasicServiceGroups INTEGER ::= 32
+
+CUG-Feature ::= SEQUENCE {
+ basicService Ext-BasicServiceCode OPTIONAL,
+ preferentialCUG-Indicator CUG-Index OPTIONAL,
+ interCUG-Restrictions InterCUG-Restrictions,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+InterCUG-Restrictions ::= OCTET STRING (SIZE (1))
+
+ -- bits 876543: 000000 (unused)
+ -- Exception handling:
+ -- bits 876543 shall be ignored if received and not understood
+
+ -- bits 21
+ -- 00 CUG only facilities
+ -- 01 CUG with outgoing access
+ -- 10 CUG with incoming access
+ -- 11 CUG with both outgoing and incoming access
+
+Ext-SS-Data ::= SEQUENCE {
+ ss-Code SS-Code,
+ ss-Status [4] Ext-SS-Status,
+ ss-SubscriptionOption SS-SubscriptionOption OPTIONAL,
+ basicServiceGroupList Ext-BasicServiceGroupList OPTIONAL,
+ extensionContainer [5] ExtensionContainer OPTIONAL,
+ ...}
+
+LCS-PrivacyExceptionList ::= SEQUENCE SIZE (1..maxNumOfPrivacyClass) OF
+ LCS-PrivacyClass
+
+maxNumOfPrivacyClass INTEGER ::= 4
+
+LCS-PrivacyClass ::= SEQUENCE {
+ ss-Code SS-Code,
+ ss-Status Ext-SS-Status,
+ notificationToMSUser [0] NotificationToMSUser OPTIONAL,
+ -- notificationToMSUser may be sent only for SS-codes callSessionRelated
+ -- and callSessionUnrelated. If not received for SS-codes callSessionRelated
+ -- and callSessionUnrelated,
+ -- the default values according to 3GPP TS 23.271 shall be assumed.
+ externalClientList [1] ExternalClientList OPTIONAL,
+ -- externalClientList may be sent only for SS-code callSessionUnrelated to a
+ -- visited node that does not support LCS Release 4 or later versions.
+ -- externalClientList may be sent only for SS-codes callSessionUnrelated and
+ -- callSessionRelated to a visited node that supports LCS Release 4 or later versions.
+ plmnClientList [2] PLMNClientList OPTIONAL,
+ -- plmnClientList may be sent only for SS-code plmnoperator.
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...,
+ ext-externalClientList [4] Ext-ExternalClientList OPTIONAL,
+ -- Ext-externalClientList may be sent only if the visited node supports LCS Release 4 or
+ -- later versions, the user did specify more than 5 clients, and White Book SCCP is used.
+ serviceTypeList [5] ServiceTypeList OPTIONAL
+ -- serviceTypeList may be sent only for SS-code serviceType and if the visited node
+ -- supports LCS Release 5 or later versions.
+ --
+ -- if segmentation is used, the complete LCS-PrivacyClass shall be sent in one segment
+}
+
+ExternalClientList ::= SEQUENCE SIZE (0..maxNumOfExternalClient) OF
+ ExternalClient
+
+maxNumOfExternalClient INTEGER ::= 5
+
+PLMNClientList ::= SEQUENCE SIZE (1..maxNumOfPLMNClient) OF
+ LCSClientInternalID
+
+maxNumOfPLMNClient INTEGER ::= 5
+
+Ext-ExternalClientList ::= SEQUENCE SIZE (1..maxNumOfExt-ExternalClient) OF
+ ExternalClient
+
+maxNumOfExt-ExternalClient INTEGER ::= 35
+
+ExternalClient ::= SEQUENCE {
+ clientIdentity LCSClientExternalID,
+ gmlc-Restriction [0] GMLC-Restriction OPTIONAL,
+ notificationToMSUser [1] NotificationToMSUser OPTIONAL,
+ -- If notificationToMSUser is not received, the default value according to
+ -- 3GPP TS 23.271 shall be assumed.
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ... }
+
+GMLC-Restriction ::= ENUMERATED {
+ gmlc-List (0),
+ home-Country (1) ,
+ ... }
+-- exception handling:
+-- At reception of any other value than the ones listed the receiver shall ignore
+-- GMLC-Restriction.
+
+NotificationToMSUser ::= ENUMERATED {
+ notifyLocationAllowed (0),
+ notifyAndVerify-LocationAllowedIfNoResponse (1),
+ notifyAndVerify-LocationNotAllowedIfNoResponse (2),
+ ...,
+ locationNotAllowed (3) }
+-- exception handling:
+-- At reception of any other value than the ones listed the receiver shall ignore
+-- NotificationToMSUser.
+
+ServiceTypeList ::= SEQUENCE SIZE (1..maxNumOfServiceType) OF
+ ServiceType
+
+maxNumOfServiceType INTEGER ::= 32
+
+ServiceType ::= SEQUENCE {
+ serviceTypeIdentity LCSServiceTypeID,
+ gmlc-Restriction [0] GMLC-Restriction OPTIONAL,
+ notificationToMSUser [1] NotificationToMSUser OPTIONAL,
+ -- If notificationToMSUser is not received, the default value according to
+ -- 3GPP TS 23.271 shall be assumed.
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ... }
+
+MOLR-List ::= SEQUENCE SIZE (1..maxNumOfMOLR-Class) OF
+ MOLR-Class
+
+maxNumOfMOLR-Class INTEGER ::= 3
+
+MOLR-Class ::= SEQUENCE {
+ ss-Code SS-Code,
+ ss-Status Ext-SS-Status,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+ZoneCodeList ::= SEQUENCE SIZE (1..maxNumOfZoneCodes)
+ OF ZoneCode
+
+ZoneCode ::= OCTET STRING (SIZE (2))
+ -- internal structure is defined in TS 3GPP TS 23.003 [17]
+
+maxNumOfZoneCodes INTEGER ::= 10
+
+InsertSubscriberDataRes ::= SEQUENCE {
+ teleserviceList [1] TeleserviceList OPTIONAL,
+ bearerServiceList [2] BearerServiceList OPTIONAL,
+ ss-List [3] SS-List OPTIONAL,
+ odb-GeneralData [4] ODB-GeneralData OPTIONAL,
+ regionalSubscriptionResponse [5] RegionalSubscriptionResponse OPTIONAL,
+ supportedCamelPhases [6] SupportedCamelPhases OPTIONAL,
+ extensionContainer [7] ExtensionContainer OPTIONAL,
+ ... ,
+ offeredCamel4CSIs [8] OfferedCamel4CSIs OPTIONAL,
+ supportedFeatures [9] SupportedFeatures OPTIONAL }
+
+RegionalSubscriptionResponse ::= ENUMERATED {
+ networkNode-AreaRestricted (0),
+ tooManyZoneCodes (1),
+ zoneCodesConflict (2),
+ regionalSubscNotSupported (3)}
+
+DeleteSubscriberDataArg ::= SEQUENCE {
+ imsi [0] IMSI,
+ basicServiceList [1] BasicServiceList OPTIONAL,
+ -- The exception handling for reception of unsupported/not allocated
+ -- basicServiceCodes is defined in section 6.8.2
+ ss-List [2] SS-List OPTIONAL,
+ roamingRestrictionDueToUnsupportedFeature [4] NULL OPTIONAL,
+ regionalSubscriptionIdentifier [5] ZoneCode OPTIONAL,
+ vbsGroupIndication [7] NULL OPTIONAL,
+ vgcsGroupIndication [8] NULL OPTIONAL,
+ camelSubscriptionInfoWithdraw [9] NULL OPTIONAL,
+ extensionContainer [6] ExtensionContainer OPTIONAL,
+ ...,
+ gprsSubscriptionDataWithdraw [10] GPRSSubscriptionDataWithdraw OPTIONAL,
+ roamingRestrictedInSgsnDueToUnsuppportedFeature [11] NULL OPTIONAL,
+ lsaInformationWithdraw [12] LSAInformationWithdraw OPTIONAL,
+ gmlc-ListWithdraw [13] NULL OPTIONAL,
+ istInformationWithdraw [14] NULL OPTIONAL,
+ specificCSI-Withdraw [15] SpecificCSI-Withdraw OPTIONAL,
+ chargingCharacteristicsWithdraw [16] NULL OPTIONAL,
+ stn-srWithdraw [17] NULL OPTIONAL,
+ epsSubscriptionDataWithdraw [18] EPS-SubscriptionDataWithdraw OPTIONAL,
+ apn-oi-replacementWithdraw [19] NULL OPTIONAL,
+ csg-SubscriptionDeleted [20] NULL OPTIONAL }
+
+SpecificCSI-Withdraw ::= BIT STRING {
+ o-csi (0),
+ ss-csi (1),
+ tif-csi (2),
+ d-csi (3),
+ vt-csi (4),
+ mo-sms-csi (5),
+ m-csi (6),
+ gprs-csi (7),
+ t-csi (8),
+ mt-sms-csi (9),
+ mg-csi (10),
+ o-IM-CSI (11),
+ d-IM-CSI (12),
+ vt-IM-CSI (13) } (SIZE(8..32))
+-- exception handling:
+-- bits 11 to 31 shall be ignored if received by a non-IP Multimedia Core Network entity.
+-- bits 0-10 and 14-31 shall be ignored if received by an IP Multimedia Core Network entity.
+-- bits 11-13 are only applicable in an IP Multimedia Core Network.
+-- Bit 8 and bits 11-13 are only applicable for the NoteSubscriberDataModified operation.
+
+GPRSSubscriptionDataWithdraw ::= CHOICE {
+ allGPRSData NULL,
+ contextIdList ContextIdList}
+
+EPS-SubscriptionDataWithdraw ::= CHOICE {
+ allEPS-Data NULL,
+ contextIdList ContextIdList}
+
+ContextIdList ::= SEQUENCE SIZE (1..maxNumOfPDP-Contexts) OF
+ ContextId
+
+LSAInformationWithdraw ::= CHOICE {
+ allLSAData NULL,
+ lsaIdentityList LSAIdentityList }
+
+LSAIdentityList ::= SEQUENCE SIZE (1..maxNumOfLSAs) OF
+ LSAIdentity
+
+BasicServiceList ::= SEQUENCE SIZE (1..maxNumOfBasicServices) OF
+ Ext-BasicServiceCode
+
+maxNumOfBasicServices INTEGER ::= 70
+
+DeleteSubscriberDataRes ::= SEQUENCE {
+ regionalSubscriptionResponse [0] RegionalSubscriptionResponse OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+VlrCamelSubscriptionInfo ::= SEQUENCE {
+ o-CSI [0] O-CSI OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ...,
+ ss-CSI [2] SS-CSI OPTIONAL,
+ o-BcsmCamelTDP-CriteriaList [4] O-BcsmCamelTDPCriteriaList OPTIONAL,
+ tif-CSI [3] NULL OPTIONAL,
+ m-CSI [5] M-CSI OPTIONAL,
+ mo-sms-CSI [6] SMS-CSI OPTIONAL,
+ vt-CSI [7] T-CSI OPTIONAL,
+ t-BCSM-CAMEL-TDP-CriteriaList [8] T-BCSM-CAMEL-TDP-CriteriaList OPTIONAL,
+ d-CSI [9] D-CSI OPTIONAL,
+ mt-sms-CSI [10] SMS-CSI OPTIONAL,
+ mt-smsCAMELTDP-CriteriaList [11] MT-smsCAMELTDP-CriteriaList OPTIONAL
+ }
+
+MT-smsCAMELTDP-CriteriaList ::= SEQUENCE SIZE (1.. maxNumOfCamelTDPData) OF
+ MT-smsCAMELTDP-Criteria
+
+MT-smsCAMELTDP-Criteria ::= SEQUENCE {
+ sms-TriggerDetectionPoint SMS-TriggerDetectionPoint,
+ tpdu-TypeCriterion [0] TPDU-TypeCriterion OPTIONAL,
+ ... }
+
+TPDU-TypeCriterion ::= SEQUENCE SIZE (1..maxNumOfTPDUTypes) OF
+ MT-SMS-TPDU-Type
+
+
+maxNumOfTPDUTypes INTEGER ::= 5
+
+MT-SMS-TPDU-Type ::= ENUMERATED {
+ sms-DELIVER (0),
+ sms-SUBMIT-REPORT (1),
+ sms-STATUS-REPORT (2),
+ ... }
+
+-- exception handling:
+-- For TPDU-TypeCriterion sequences containing this parameter with any
+-- other value than the ones listed above the receiver shall ignore
+-- the whole TPDU-TypeCriterion sequence.
+-- In CAMEL phase 4, sms-SUBMIT-REPORT shall not be used and a received TPDU-TypeCriterion
+-- sequence containing sms-SUBMIT-REPORT shall be wholly ignored.
+
+D-CSI ::= SEQUENCE {
+ dp-AnalysedInfoCriteriaList [0] DP-AnalysedInfoCriteriaList OPTIONAL,
+ camelCapabilityHandling [1] CamelCapabilityHandling OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ notificationToCSE [3] NULL OPTIONAL,
+ csi-Active [4] NULL OPTIONAL,
+ ...}
+-- notificationToCSE and csi-Active shall not be present when D-CSI is sent to VLR/GMSC.
+-- They may only be included in ATSI/ATM ack/NSDC message.
+-- DP-AnalysedInfoCriteria and camelCapabilityHandling shall be present in
+-- the D-CSI sequence.
+-- If D-CSI is segmented, then the first segment shall contain dp-AnalysedInfoCriteriaList
+-- and camelCapabilityHandling. Subsequent segments shall not contain
+-- camelCapabilityHandling, but may contain dp-AnalysedInfoCriteriaList.
+
+DP-AnalysedInfoCriteriaList ::= SEQUENCE SIZE (1..maxNumOfDP-AnalysedInfoCriteria) OF
+ DP-AnalysedInfoCriterium
+
+maxNumOfDP-AnalysedInfoCriteria INTEGER ::= 10
+
+DP-AnalysedInfoCriterium ::= SEQUENCE {
+ dialledNumber ISDN-AddressString,
+ serviceKey ServiceKey,
+ gsmSCF-Address ISDN-AddressString,
+ defaultCallHandling DefaultCallHandling,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+SS-CSI ::= SEQUENCE {
+ ss-CamelData SS-CamelData,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ notificationToCSE [0] NULL OPTIONAL,
+ csi-Active [1] NULL OPTIONAL
+-- notificationToCSE and csi-Active shall not be present when SS-CSI is sent to VLR.
+-- They may only be included in ATSI/ATM ack/NSDC message.
+}
+
+SS-CamelData ::= SEQUENCE {
+ ss-EventList SS-EventList,
+ gsmSCF-Address ISDN-AddressString,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+SS-EventList ::= SEQUENCE SIZE (1..maxNumOfCamelSSEvents) OF SS-Code
+ -- Actions for the following SS-Code values are defined in CAMEL Phase 3:
+ -- ect SS-Code ::= '00110001'B
+ -- multiPTY SS-Code ::= '01010001'B
+ -- cd SS-Code ::= '00100100'B
+ -- ccbs SS-Code ::= '01000100'B
+ -- all other SS codes shall be ignored
+ -- When SS-CSI is sent to the VLR, it shall not contain a marking for ccbs.
+ -- If the VLR receives SS-CSI containing a marking for ccbs, the VLR shall discard the
+ -- ccbs marking in SS-CSI.
+
+maxNumOfCamelSSEvents INTEGER ::= 10
+
+O-CSI ::= SEQUENCE {
+ o-BcsmCamelTDPDataList O-BcsmCamelTDPDataList,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ camelCapabilityHandling [0] CamelCapabilityHandling OPTIONAL,
+ notificationToCSE [1] NULL OPTIONAL,
+ csiActive [2] NULL OPTIONAL}
+-- notificationtoCSE and csiActive shall not be present when O-CSI is sent to VLR/GMSC.
+-- They may only be included in ATSI/ATM ack/NSDC message.
+-- O-CSI shall not be segmented.
+
+O-BcsmCamelTDPDataList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
+ O-BcsmCamelTDPData
+ -- O-BcsmCamelTDPDataList shall not contain more than one instance of
+ -- O-BcsmCamelTDPData containing the same value for o-BcsmTriggerDetectionPoint.
+ -- For CAMEL Phase 2, this means that only one instance of O-BcsmCamelTDPData is allowed
+ -- with o-BcsmTriggerDetectionPoint being equal to DP2.
+
+maxNumOfCamelTDPData INTEGER ::= 10
+
+O-BcsmCamelTDPData ::= SEQUENCE {
+ o-BcsmTriggerDetectionPoint O-BcsmTriggerDetectionPoint,
+ serviceKey ServiceKey,
+ gsmSCF-Address [0] ISDN-AddressString,
+ defaultCallHandling [1] DefaultCallHandling,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...
+ }
+
+ServiceKey ::= INTEGER (0..2147483647)
+
+O-BcsmTriggerDetectionPoint ::= ENUMERATED {
+ collectedInfo (2),
+ ...,
+ routeSelectFailure (4) }
+ -- exception handling:
+ -- For O-BcsmCamelTDPData sequences containing this parameter with any
+ -- other value than the ones listed the receiver shall ignore the whole
+ -- O-BcsmCamelTDPDatasequence.
+ -- For O-BcsmCamelTDP-Criteria sequences containing this parameter with any
+ -- other value than the ones listed the receiver shall ignore the whole
+ -- O-BcsmCamelTDP-Criteria sequence.
+
+O-BcsmCamelTDPCriteriaList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
+ O-BcsmCamelTDP-Criteria
+
+T-BCSM-CAMEL-TDP-CriteriaList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
+ T-BCSM-CAMEL-TDP-Criteria
+
+O-BcsmCamelTDP-Criteria ::= SEQUENCE {
+ o-BcsmTriggerDetectionPoint O-BcsmTriggerDetectionPoint,
+ destinationNumberCriteria [0] DestinationNumberCriteria OPTIONAL,
+ basicServiceCriteria [1] BasicServiceCriteria OPTIONAL,
+ callTypeCriteria [2] CallTypeCriteria OPTIONAL,
+ ...,
+ o-CauseValueCriteria [3] O-CauseValueCriteria OPTIONAL,
+ extensionContainer [4] ExtensionContainer OPTIONAL }
+
+T-BCSM-CAMEL-TDP-Criteria ::= SEQUENCE {
+ t-BCSM-TriggerDetectionPoint T-BcsmTriggerDetectionPoint,
+ basicServiceCriteria [0] BasicServiceCriteria OPTIONAL,
+ t-CauseValueCriteria [1] T-CauseValueCriteria OPTIONAL,
+ ... }
+
+DestinationNumberCriteria ::= SEQUENCE {
+ matchType [0] MatchType,
+ destinationNumberList [1] DestinationNumberList OPTIONAL,
+ destinationNumberLengthList [2] DestinationNumberLengthList OPTIONAL,
+ -- one or both of destinationNumberList and destinationNumberLengthList
+ -- shall be present
+ ...}
+
+DestinationNumberList ::= SEQUENCE SIZE (1..maxNumOfCamelDestinationNumbers) OF
+ ISDN-AddressString
+ -- The receiving entity shall not check the format of a number in
+ -- the dialled number list
+
+DestinationNumberLengthList ::= SEQUENCE SIZE (1..maxNumOfCamelDestinationNumberLengths) OF
+ INTEGER(1..maxNumOfISDN-AddressDigits)
+
+BasicServiceCriteria ::= SEQUENCE SIZE(1..maxNumOfCamelBasicServiceCriteria) OF
+ Ext-BasicServiceCode
+
+maxNumOfISDN-AddressDigits INTEGER ::= 15
+
+maxNumOfCamelDestinationNumbers INTEGER ::= 10
+
+maxNumOfCamelDestinationNumberLengths INTEGER ::= 3
+
+maxNumOfCamelBasicServiceCriteria INTEGER ::= 5
+
+CallTypeCriteria ::= ENUMERATED {
+ forwarded (0),
+ notForwarded (1)}
+
+MatchType ::= ENUMERATED {
+ inhibiting (0),
+ enabling (1)}
+
+O-CauseValueCriteria ::= SEQUENCE SIZE(1..maxNumOfCAMEL-O-CauseValueCriteria) OF
+ CauseValue
+
+T-CauseValueCriteria ::= SEQUENCE SIZE(1..maxNumOfCAMEL-T-CauseValueCriteria) OF
+ CauseValue
+
+maxNumOfCAMEL-O-CauseValueCriteria INTEGER ::= 5
+
+maxNumOfCAMEL-T-CauseValueCriteria INTEGER ::= 5
+
+CauseValue ::= OCTET STRING (SIZE(1))
+-- Type extracted from Cause parameter in ITU-T Recommendation Q.763.
+-- For the use of cause value refer to ITU-T Recommendation Q.850.
+
+DefaultCallHandling ::= ENUMERATED {
+ continueCall (0) ,
+ releaseCall (1) ,
+ ...}
+ -- exception handling:
+ -- reception of values in range 2-31 shall be treated as "continueCall"
+ -- reception of values greater than 31 shall be treated as "releaseCall"
+
+CamelCapabilityHandling ::= INTEGER(1..16)
+ -- value 1 = CAMEL phase 1,
+ -- value 2 = CAMEL phase 2,
+ -- value 3 = CAMEL Phase 3,
+ -- value 4 = CAMEL phase 4:
+ -- reception of values greater than 4 shall be treated as CAMEL phase 4.
+
+SupportedCamelPhases ::= BIT STRING {
+ phase1 (0),
+ phase2 (1),
+ phase3 (2),
+ phase4 (3)} (SIZE (1..16))
+-- A node shall mark in the BIT STRING all CAMEL Phases it supports.
+-- Other values than listed above shall be discarded.
+
+OfferedCamel4CSIs ::= BIT STRING {
+ o-csi (0),
+ d-csi (1),
+ vt-csi (2),
+ t-csi (3),
+ mt-sms-csi (4),
+ mg-csi (5),
+ psi-enhancements (6)
+} (SIZE (7..16))
+-- A node supporting Camel phase 4 shall mark in the BIT STRING all Camel4 CSIs
+-- it offers.
+-- Other values than listed above shall be discarded.
+
+OfferedCamel4Functionalities ::= BIT STRING {
+ initiateCallAttempt (0),
+ splitLeg (1),
+ moveLeg (2),
+ disconnectLeg (3),
+ entityReleased (4),
+ dfc-WithArgument (5),
+ playTone (6),
+ dtmf-MidCall (7),
+ chargingIndicator (8),
+ alertingDP (9),
+ locationAtAlerting (10),
+ changeOfPositionDP (11),
+ or-Interactions (12),
+ warningToneEnhancements (13),
+ cf-Enhancements (14),
+ subscribedEnhancedDialledServices (15),
+ servingNetworkEnhancedDialledServices (16),
+ criteriaForChangeOfPositionDP (17),
+ serviceChangeDP (18),
+ collectInformation (19)
+} (SIZE (15..64))
+-- A node supporting Camel phase 4 shall mark in the BIT STRING all CAMEL4
+-- functionalities it offers.
+-- Other values than listed above shall be discarded.
+
+SMS-CSI ::= SEQUENCE {
+ sms-CAMEL-TDP-DataList [0] SMS-CAMEL-TDP-DataList OPTIONAL,
+ camelCapabilityHandling [1] CamelCapabilityHandling OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ notificationToCSE [3] NULL OPTIONAL,
+ csi-Active [4] NULL OPTIONAL,
+ ...}
+-- notificationToCSE and csi-Active shall not be present
+-- when MO-SMS-CSI or MT-SMS-CSI is sent to VLR or SGSN.
+-- They may only be included in ATSI/ATM ack/NSDC message.
+-- SMS-CAMEL-TDP-Data and camelCapabilityHandling shall be present in
+-- the SMS-CSI sequence.
+-- If SMS-CSI is segmented, sms-CAMEL-TDP-DataList and camelCapabilityHandling shall be
+-- present in the first segment
+
+SMS-CAMEL-TDP-DataList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
+ SMS-CAMEL-TDP-Data
+-- SMS-CAMEL-TDP-DataList shall not contain more than one instance of
+-- SMS-CAMEL-TDP-Data containing the same value for sms-TriggerDetectionPoint.
+
+SMS-CAMEL-TDP-Data ::= SEQUENCE {
+ sms-TriggerDetectionPoint [0] SMS-TriggerDetectionPoint,
+ serviceKey [1] ServiceKey,
+ gsmSCF-Address [2] ISDN-AddressString,
+ defaultSMS-Handling [3] DefaultSMS-Handling,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ...
+ }
+
+SMS-TriggerDetectionPoint ::= ENUMERATED {
+ sms-CollectedInfo (1),
+ ...,
+ sms-DeliveryRequest (2)
+ }
+-- exception handling:
+-- For SMS-CAMEL-TDP-Data and MT-smsCAMELTDP-Criteria sequences containing this
+-- parameter with any other value than the ones listed the receiver shall ignore
+-- the whole sequence.
+--
+-- If this parameter is received with any other value than sms-CollectedInfo
+-- in an SMS-CAMEL-TDP-Data sequence contained in mo-sms-CSI, then the receiver shall
+-- ignore the whole SMS-CAMEL-TDP-Data sequence.
+--
+-- If this parameter is received with any other value than sms-DeliveryRequest
+-- in an SMS-CAMEL-TDP-Data sequence contained in mt-sms-CSI then the receiver shall
+-- ignore the whole SMS-CAMEL-TDP-Data sequence.
+--
+-- If this parameter is received with any other value than sms-DeliveryRequest
+-- in an MT-smsCAMELTDP-Criteria sequence then the receiver shall
+-- ignore the whole MT-smsCAMELTDP-Criteria sequence.
+
+DefaultSMS-Handling ::= ENUMERATED {
+ continueTransaction (0) ,
+ releaseTransaction (1) ,
+ ...}
+-- exception handling:
+-- reception of values in range 2-31 shall be treated as "continueTransaction"
+-- reception of values greater than 31 shall be treated as "releaseTransaction"
+
+M-CSI ::= SEQUENCE {
+ mobilityTriggers MobilityTriggers,
+ serviceKey ServiceKey,
+ gsmSCF-Address [0] ISDN-AddressString,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ notificationToCSE [2] NULL OPTIONAL,
+ csi-Active [3] NULL OPTIONAL,
+ ...}
+-- notificationToCSE and csi-Active shall not be present when M-CSI is sent to VLR.
+-- They may only be included in ATSI/ATM ack/NSDC message.
+
+MG-CSI ::= SEQUENCE {
+ mobilityTriggers MobilityTriggers,
+ serviceKey ServiceKey,
+ gsmSCF-Address [0] ISDN-AddressString,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ notificationToCSE [2] NULL OPTIONAL,
+ csi-Active [3] NULL OPTIONAL,
+ ...}
+-- notificationToCSE and csi-Active shall not be present when MG-CSI is sent to SGSN.
+-- They may only be included in ATSI/ATM ack/NSDC message.
+
+MobilityTriggers ::= SEQUENCE SIZE (1..maxNumOfMobilityTriggers) OF
+ MM-Code
+
+maxNumOfMobilityTriggers INTEGER ::= 10
+
+MM-Code ::= OCTET STRING (SIZE (1))
+-- This type is used to indicate a Mobility Management event.
+-- Actions for the following MM-Code values are defined in CAMEL Phase 4:
+--
+-- CS domain MM events:
+-- Location-update-in-same-VLR MM-Code ::= '00000000'B
+-- Location-update-to-other-VLR MM-Code ::= '00000001'B
+-- IMSI-Attach MM-Code ::= '00000010'B
+-- MS-initiated-IMSI-Detach MM-Code ::= '00000011'B
+-- Network-initiated-IMSI-Detach MM-Code ::= '00000100'B
+--
+-- PS domain MM events:
+-- Routeing-Area-update-in-same-SGSN MM-Code ::= '10000000'B
+-- Routeing-Area-update-to-other-SGSN-update-from-new-SGSN
+-- MM-Code ::= '10000001'B
+-- Routeing-Area-update-to-other-SGSN-disconnect-by-detach
+-- MM-Code ::= '10000010'B
+-- GPRS-Attach MM-Code ::= '10000011'B
+-- MS-initiated-GPRS-Detach MM-Code ::= '10000100'B
+-- Network-initiated-GPRS-Detach MM-Code ::= '10000101'B
+-- Network-initiated-transfer-to-MS-not-reachable-for-paging
+-- MM-Code ::= '10000110'B
+--
+-- If the MSC receives any other MM-code than the ones listed above for the
+-- CS domain, then the MSC shall ignore that MM-code.
+-- If the SGSN receives any other MM-code than the ones listed above for the
+-- PS domain, then the SGSN shall ignore that MM-code.
+
+T-CSI ::= SEQUENCE {
+ t-BcsmCamelTDPDataList T-BcsmCamelTDPDataList,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ camelCapabilityHandling [0] CamelCapabilityHandling OPTIONAL,
+ notificationToCSE [1] NULL OPTIONAL,
+ csi-Active [2] NULL OPTIONAL}
+-- notificationToCSE and csi-Active shall not be present when VT-CSI/T-CSI is sent
+-- to VLR/GMSC.
+-- They may only be included in ATSI/ATM ack/NSDC message.
+-- T-CSI shall not be segmented.
+
+T-BcsmCamelTDPDataList ::= SEQUENCE SIZE (1..maxNumOfCamelTDPData) OF
+ T-BcsmCamelTDPData
+ --- T-BcsmCamelTDPDataList shall not contain more than one instance of
+ --- T-BcsmCamelTDPData containing the same value for t-BcsmTriggerDetectionPoint.
+ --- For CAMEL Phase 2, this means that only one instance of T-BcsmCamelTDPData is allowed
+ --- with t-BcsmTriggerDetectionPoint being equal to DP12.
+ --- For CAMEL Phase 3, more TDP’s are allowed.
+
+T-BcsmCamelTDPData ::= SEQUENCE {
+ t-BcsmTriggerDetectionPoint T-BcsmTriggerDetectionPoint,
+ serviceKey ServiceKey,
+ gsmSCF-Address [0] ISDN-AddressString,
+ defaultCallHandling [1] DefaultCallHandling,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...}
+
+T-BcsmTriggerDetectionPoint ::= ENUMERATED {
+ termAttemptAuthorized (12),
+ ... ,
+ tBusy (13),
+ tNoAnswer (14)}
+ -- exception handling:
+ -- For T-BcsmCamelTDPData sequences containing this parameter with any other
+ -- value than the ones listed above, the receiver shall ignore the whole
+ -- T-BcsmCamelTDPData sequence.
+
+-- gprs location information retrieval types
+
+SendRoutingInfoForGprsArg ::= SEQUENCE {
+ imsi [0] IMSI,
+ ggsn-Address [1] GSN-Address OPTIONAL,
+ ggsn-Number [2] ISDN-AddressString,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...}
+
+SendRoutingInfoForGprsRes ::= SEQUENCE {
+ sgsn-Address [0] GSN-Address,
+ ggsn-Address [1] GSN-Address OPTIONAL,
+ mobileNotReachableReason [2] AbsentSubscriberDiagnosticSM OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...}
+
+-- failure report types
+
+FailureReportArg ::= SEQUENCE {
+ imsi [0] IMSI,
+ ggsn-Number [1] ISDN-AddressString ,
+ ggsn-Address [2] GSN-Address OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...}
+
+FailureReportRes ::= SEQUENCE {
+ ggsn-Address [0] GSN-Address OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ...}
+
+-- gprs notification types
+
+NoteMsPresentForGprsArg ::= SEQUENCE {
+ imsi [0] IMSI,
+ sgsn-Address [1] GSN-Address,
+ ggsn-Address [2] GSN-Address OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...}
+
+NoteMsPresentForGprsRes ::= SEQUENCE {
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+-- fault recovery types
+
+ResetArg ::= SEQUENCE {
+ hlr-Number ISDN-AddressString,
+ hlr-List HLR-List OPTIONAL,
+ ...}
+
+RestoreDataArg ::= SEQUENCE {
+ imsi IMSI,
+ lmsi LMSI OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ vlr-Capability [6] VLR-Capability OPTIONAL }
+
+RestoreDataRes ::= SEQUENCE {
+ hlr-Number ISDN-AddressString,
+ msNotReachable NULL OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+-- VBS/VGCS types
+VBSDataList ::= SEQUENCE SIZE (1..maxNumOfVBSGroupIds) OF
+ VoiceBroadcastData
+
+VGCSDataList ::= SEQUENCE SIZE (1..maxNumOfVGCSGroupIds) OF
+ VoiceGroupCallData
+
+maxNumOfVBSGroupIds INTEGER ::= 50
+
+maxNumOfVGCSGroupIds INTEGER ::= 50
+
+VoiceGroupCallData ::= SEQUENCE {
+ groupId GroupId,
+ -- groupId shall be filled with six TBCD fillers (1111)if the longGroupId is present
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ additionalSubscriptions AdditionalSubscriptions OPTIONAL,
+ additionalInfo [0] AdditionalInfo OPTIONAL,
+ longGroupId [1] Long-GroupId OPTIONAL }
+
+ -- VoiceGroupCallData containing a longGroupId shall not be sent to VLRs that did not
+ -- indicate support of long Group IDs within the Update Location or Restore Data
+ -- request message
+
+AdditionalInfo ::= BIT STRING (SIZE (1..136))
+-- Refers to Additional Info as specified in 3GPP TS 43.068
+
+AdditionalSubscriptions ::= BIT STRING {
+ privilegedUplinkRequest (0),
+ emergencyUplinkRequest (1),
+ emergencyReset (2)} (SIZE (3..8))
+-- Other bits than listed above shall be discarded.
+
+VoiceBroadcastData ::= SEQUENCE {
+ groupid GroupId,
+ -- groupId shall be filled with six TBCD fillers (1111)if the longGroupId is present
+ broadcastInitEntitlement NULL OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ longGroupId [0] Long-GroupId OPTIONAL }
+
+-- VoiceBroadcastData containing a longGroupId shall not be sent to VLRs that did not
+-- indicate support of long Group IDs within the Update Location or Restore Data
+ -- request message
+
+GroupId ::= TBCD-STRING (SIZE (3))
+ -- When Group-Id is less than six characters in length, the TBCD filler (1111)
+ -- is used to fill unused half octets.
+ -- Refers to the Group Identification as specified in 3GPP TS 23.003
+ -- and 3GPP TS 43.068/ 43.069
+
+Long-GroupId ::= TBCD-STRING (SIZE (4))
+ -- When Long-Group-Id is less than eight characters in length, the TBCD filler (1111)
+ -- is used to fill unused half octets.
+ -- Refers to the Group Identification as specified in 3GPP TS 23.003
+ -- and 3GPP TS 43.068/ 43.069
+
+
+-- provide subscriber info types
+
+ProvideSubscriberInfoArg ::= SEQUENCE {
+ imsi [0] IMSI,
+ lmsi [1] LMSI OPTIONAL,
+ requestedInfo [2] RequestedInfo,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...,
+ callPriority [4] EMLPP-Priority OPTIONAL
+ }
+
+ProvideSubscriberInfoRes ::= SEQUENCE {
+ subscriberInfo SubscriberInfo,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+SubscriberInfo ::= SEQUENCE {
+ locationInformation [0] LocationInformation OPTIONAL,
+ subscriberState [1] SubscriberState OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ... ,
+ locationInformationGPRS [3] LocationInformationGPRS OPTIONAL,
+ ps-SubscriberState [4] PS-SubscriberState OPTIONAL,
+ imei [5] IMEI OPTIONAL,
+ ms-Classmark2 [6] MS-Classmark2 OPTIONAL,
+ gprs-MS-Class [7] GPRSMSClass OPTIONAL,
+ mnpInfoRes [8] MNPInfoRes OPTIONAL }
+
+-- If the HLR receives locationInformation, subscriberState or ms-Classmark2 from an SGSN
+-- it shall discard them.
+-- If the HLR receives locationInformationGPRS, ps-SubscriberState or gprs-MS-Class from
+-- a VLR it shall discard them.
+-- If the HLR receives parameters which it has not requested, it shall discard them.
+
+MNPInfoRes ::= SEQUENCE {
+ routeingNumber [0] RouteingNumber OPTIONAL,
+ imsi [1] IMSI OPTIONAL,
+ msisdn [2] ISDN-AddressString OPTIONAL,
+ numberPortabilityStatus [3] NumberPortabilityStatus OPTIONAL,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ... }
+-- The IMSI parameter contains a generic IMSI, i.e. it is not tied necessarily to the
+-- Subscriber. MCC and MNC values in this IMSI shall point to the Subscription Network of
+-- the Subscriber. See 3GPP TS 23.066 [108].
+
+RouteingNumber ::= TBCD-STRING (SIZE (1..5))
+
+
+NumberPortabilityStatus ::= ENUMERATED {
+ notKnownToBePorted (0),
+ ownNumberPortedOut (1),
+ foreignNumberPortedToForeignNetwork (2),
+ ...,
+ ownNumberNotPortedOut (4),
+ foreignNumberPortedIn (5)
+ }
+ -- exception handling:
+ -- reception of other values than the ones listed the receiver shall ignore the
+ -- whole NumberPortabilityStatus;
+ -- ownNumberNotPortedOut or foreignNumberPortedIn may only be included in Any Time
+ -- Interrogation message.
+
+MS-Classmark2 ::= OCTET STRING (SIZE (3))
+ -- This parameter carries the value part of the MS Classmark 2 IE defined in
+ -- 3GPP TS 24.008 [35].
+
+GPRSMSClass ::= SEQUENCE {
+ mSNetworkCapability [0] MSNetworkCapability,
+ mSRadioAccessCapability [1] MSRadioAccessCapability OPTIONAL
+ }
+
+MSNetworkCapability ::= OCTET STRING (SIZE (1..8))
+ -- This parameter carries the value part of the MS Network Capability IE defined in
+ -- 3GPP TS 24.008 [35].
+
+MSRadioAccessCapability ::= OCTET STRING (SIZE (1..50))
+ -- This parameter carries the value part of the MS Radio Access Capability IE defined in
+ -- 3GPP TS 24.008 [35].
+
+RequestedInfo ::= SEQUENCE {
+ locationInformation [0] NULL OPTIONAL,
+ subscriberState [1] NULL OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...,
+ currentLocation [3] NULL OPTIONAL,
+ requestedDomain [4] DomainType OPTIONAL,
+ imei [6] NULL OPTIONAL,
+ ms-classmark [5] NULL OPTIONAL,
+ mnpRequestedInfo [7] NULL OPTIONAL }
+
+-- currentLocation shall be absent if locationInformation is absent
+
+DomainType ::= ENUMERATED {
+ cs-Domain (0),
+ ps-Domain (1),
+ ...}
+-- exception handling:
+-- reception of values > 1 shall be mapped to 'cs-Domain'
+
+LocationInformation ::= SEQUENCE {
+ ageOfLocationInformation AgeOfLocationInformation OPTIONAL,
+ geographicalInformation [0] GeographicalInformation OPTIONAL,
+ vlr-number [1] ISDN-AddressString OPTIONAL,
+ locationNumber [2] LocationNumber OPTIONAL,
+ cellGlobalIdOrServiceAreaIdOrLAI [3] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ... ,
+ selectedLSA-Id [5] LSAIdentity OPTIONAL,
+ msc-Number [6] ISDN-AddressString OPTIONAL,
+ geodeticInformation [7] GeodeticInformation OPTIONAL,
+ currentLocationRetrieved [8] NULL OPTIONAL,
+ sai-Present [9] NULL OPTIONAL }
+-- sai-Present indicates that the cellGlobalIdOrServiceAreaIdOrLAI parameter contains
+-- a Service Area Identity.
+-- currentLocationRetrieved shall be present
+-- if the location information were retrieved after a successfull paging.
+
+LocationInformationGPRS ::= SEQUENCE {
+ cellGlobalIdOrServiceAreaIdOrLAI [0] CellGlobalIdOrServiceAreaIdOrLAI OPTIONAL,
+ routeingAreaIdentity [1] RAIdentity OPTIONAL,
+ geographicalInformation [2] GeographicalInformation OPTIONAL,
+ sgsn-Number [3] ISDN-AddressString OPTIONAL,
+ selectedLSAIdentity [4] LSAIdentity OPTIONAL,
+ extensionContainer [5] ExtensionContainer OPTIONAL,
+ ...,
+ sai-Present [6] NULL OPTIONAL,
+ geodeticInformation [7] GeodeticInformation OPTIONAL,
+ currentLocationRetrieved [8] NULL OPTIONAL,
+ ageOfLocationInformation [9] AgeOfLocationInformation OPTIONAL }
+-- sai-Present indicates that the cellGlobalIdOrServiceAreaIdOrLAI parameter contains
+-- a Service Area Identity.
+-- currentLocationRetrieved shall be present if the location information
+-- was retrieved after successful paging.
+
+RAIdentity ::= OCTET STRING (SIZE (6))
+-- Routing Area Identity is coded in accordance with 3GPP TS 29.060 [105].
+-- It shall contain the value part defined in 3GPP TS 29.060 only. I.e. the 3GPP TS 29.060
+-- type identifier octet shall not be included.
+
+
+GeographicalInformation ::= OCTET STRING (SIZE (8))
+-- Refers to geographical Information defined in 3GPP TS 23.032.
+-- Only the description of an ellipsoid point with uncertainty circle
+-- as specified in 3GPP TS 23.032 is allowed to be used
+-- The internal structure according to 3GPP TS 23.032 is as follows:
+-- Type of shape (ellipsoid point with uncertainty circle) 1 octet
+-- Degrees of Latitude 3 octets
+-- Degrees of Longitude 3 octets
+-- Uncertainty code 1 octet
+
+GeodeticInformation ::= OCTET STRING (SIZE (10))
+-- Refers to Calling Geodetic Location defined in Q.763 (1999).
+-- Only the description of an ellipsoid point with uncertainty circle
+-- as specified in Q.763 (1999) is allowed to be used
+-- The internal structure according to Q.763 (1999) is as follows:
+-- Screening and presentation indicators 1 octet
+-- Type of shape (ellipsoid point with uncertainty circle) 1 octet
+-- Degrees of Latitude 3 octets
+-- Degrees of Longitude 3 octets
+-- Uncertainty code 1 octet
+-- Confidence 1 octet
+
+LocationNumber ::= OCTET STRING (SIZE (2..10))
+ -- the internal structure is defined in ITU-T Rec Q.763
+
+SubscriberState ::= CHOICE {
+ assumedIdle [0] NULL,
+ camelBusy [1] NULL,
+ netDetNotReachable NotReachableReason,
+ notProvidedFromVLR [2] NULL}
+
+PS-SubscriberState ::= CHOICE {
+ notProvidedFromSGSN [0] NULL,
+ ps-Detached [1] NULL,
+ ps-AttachedNotReachableForPaging [2] NULL,
+ ps-AttachedReachableForPaging [3] NULL,
+ ps-PDP-ActiveNotReachableForPaging [4] PDP-ContextInfoList,
+ ps-PDP-ActiveReachableForPaging [5] PDP-ContextInfoList,
+ netDetNotReachable NotReachableReason }
+
+PDP-ContextInfoList ::= SEQUENCE SIZE (1..maxNumOfPDP-Contexts) OF
+ PDP-ContextInfo
+
+PDP-ContextInfo ::= SEQUENCE {
+ pdp-ContextIdentifier [0] ContextId,
+ pdp-ContextActive [1] NULL OPTIONAL,
+ pdp-Type [2] PDP-Type,
+ pdp-Address [3] PDP-Address OPTIONAL,
+ apn-Subscribed [4] APN OPTIONAL,
+ apn-InUse [5] APN OPTIONAL,
+ nsapi [6] NSAPI OPTIONAL,
+ transactionId [7] TransactionId OPTIONAL,
+ teid-ForGnAndGp [8] TEID OPTIONAL,
+ teid-ForIu [9] TEID OPTIONAL,
+ ggsn-Address [10] GSN-Address OPTIONAL,
+ qos-Subscribed [11] Ext-QoS-Subscribed OPTIONAL,
+ qos-Requested [12] Ext-QoS-Subscribed OPTIONAL,
+ qos-Negotiated [13] Ext-QoS-Subscribed OPTIONAL,
+ chargingId [14] GPRSChargingID OPTIONAL,
+ chargingCharacteristics [15] ChargingCharacteristics OPTIONAL,
+ rnc-Address [16] GSN-Address OPTIONAL,
+ extensionContainer [17] ExtensionContainer OPTIONAL,
+ ...,
+ qos2-Subscribed [18] Ext2-QoS-Subscribed OPTIONAL,
+ -- qos2-Subscribed may be present only if qos-Subscribed is present.
+ qos2-Requested [19] Ext2-QoS-Subscribed OPTIONAL,
+ -- qos2-Requested may be present only if qos-Requested is present.
+ qos2-Negotiated [20] Ext2-QoS-Subscribed OPTIONAL,
+ -- qos2-Negotiated may be present only if qos-Negotiated is present.
+ qos3-Subscribed [21] Ext3-QoS-Subscribed OPTIONAL,
+ -- qos3-Subscribed may be present only if qos2-Subscribed is present.
+ qos3-Requested [22] Ext3-QoS-Subscribed OPTIONAL,
+ -- qos3-Requested may be present only if qos2-Requested is present.
+ qos3-Negotiated [23] Ext3-QoS-Subscribed OPTIONAL
+ -- qos3-Negotiated may be present only if qos2-Negotiated is present.
+}
+
+NSAPI ::= INTEGER (0..15)
+-- This type is used to indicate the Network layer Service Access Point
+
+TransactionId ::= OCTET STRING (SIZE (1..2))
+-- This type carries the value part of the transaction identifier which is used in the
+-- session management messages on the access interface. The encoding is defined in
+-- 3GPP TS 24.008
+
+TEID ::= OCTET STRING (SIZE (4))
+-- This type carries the value part of the Tunnel Endpoint Identifier which is used to
+-- distinguish between different tunnels between the same pair of entities which communicate
+-- using the GPRS Tunnelling Protocol The encoding is defined in 3GPP TS 29.060.
+
+GPRSChargingID ::= OCTET STRING (SIZE (4))
+-- The Charging ID is a unique four octet value generated by the GGSN when
+-- a PDP Context is activated. A Charging ID is generated for each activated context.
+-- The encoding is defined in 3GPP TS 29.060.
+
+NotReachableReason ::= ENUMERATED {
+ msPurged (0),
+ imsiDetached (1),
+ restrictedArea (2),
+ notRegistered (3)}
+
+-- any time interrogation info types
+
+AnyTimeInterrogationArg ::= SEQUENCE {
+ subscriberIdentity [0] SubscriberIdentity,
+ requestedInfo [1] RequestedInfo,
+ gsmSCF-Address [3] ISDN-AddressString,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...}
+
+AnyTimeInterrogationRes ::= SEQUENCE {
+ subscriberInfo SubscriberInfo,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+-- any time information handling types
+
+AnyTimeSubscriptionInterrogationArg ::= SEQUENCE {
+ subscriberIdentity [0] SubscriberIdentity,
+ requestedSubscriptionInfo [1] RequestedSubscriptionInfo,
+ gsmSCF-Address [2] ISDN-AddressString,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ longFTN-Supported [4] NULL OPTIONAL,
+ ...}
+
+AnyTimeSubscriptionInterrogationRes ::= SEQUENCE {
+ callForwardingData [1] CallForwardingData OPTIONAL,
+ callBarringData [2] CallBarringData OPTIONAL,
+ odb-Info [3] ODB-Info OPTIONAL,
+ camel-SubscriptionInfo [4] CAMEL-SubscriptionInfo OPTIONAL,
+ supportedVLR-CAMEL-Phases [5] SupportedCamelPhases OPTIONAL,
+ supportedSGSN-CAMEL-Phases [6] SupportedCamelPhases OPTIONAL,
+ extensionContainer [7] ExtensionContainer OPTIONAL,
+ ... ,
+ offeredCamel4CSIsInVLR [8] OfferedCamel4CSIs OPTIONAL,
+ offeredCamel4CSIsInSGSN [9] OfferedCamel4CSIs OPTIONAL,
+ msisdn-BS-List [10] MSISDN-BS-List OPTIONAL }
+
+RequestedSubscriptionInfo ::= SEQUENCE {
+ requestedSS-Info [1] SS-ForBS-Code OPTIONAL,
+ odb [2] NULL OPTIONAL,
+ requestedCAMEL-SubscriptionInfo [3] RequestedCAMEL-SubscriptionInfo OPTIONAL,
+ supportedVLR-CAMEL-Phases [4] NULL OPTIONAL,
+ supportedSGSN-CAMEL-Phases [5] NULL OPTIONAL,
+ extensionContainer [6] ExtensionContainer OPTIONAL,
+ ...,
+ additionalRequestedCAMEL-SubscriptionInfo
+ [7] AdditionalRequestedCAMEL-SubscriptionInfo
+ OPTIONAL,
+ msisdn-BS-List [8] NULL OPTIONAL }
+
+MSISDN-BS-List ::= SEQUENCE SIZE (1..maxNumOfMSISDN) OF
+ MSISDN-BS
+
+maxNumOfMSISDN INTEGER ::= 50
+
+
+MSISDN-BS ::= SEQUENCE {
+ msisdn ISDN-AddressString,
+ basicServiceList [0] BasicServiceList OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ...}
+
+RequestedCAMEL-SubscriptionInfo ::= ENUMERATED {
+ o-CSI (0),
+ t-CSI (1),
+ vt-CSI (2),
+ tif-CSI (3),
+ gprs-CSI (4),
+ mo-sms-CSI (5),
+ ss-CSI (6),
+ m-CSI (7),
+ d-csi (8)}
+
+AdditionalRequestedCAMEL-SubscriptionInfo ::= ENUMERATED {
+ mt-sms-CSI (0),
+ mg-csi (1),
+ o-IM-CSI (2),
+ d-IM-CSI (3),
+ vt-IM-CSI (4),
+ ...}
+-- exception handling: unknown values shall be discarded by the receiver.
+
+CallForwardingData ::= SEQUENCE {
+ forwardingFeatureList Ext-ForwFeatureList,
+ notificationToCSE NULL OPTIONAL,
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+CallBarringData ::= SEQUENCE {
+ callBarringFeatureList Ext-CallBarFeatureList,
+ password Password OPTIONAL,
+ wrongPasswordAttemptsCounter WrongPasswordAttemptsCounter OPTIONAL,
+ notificationToCSE NULL OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+WrongPasswordAttemptsCounter ::= INTEGER (0..4)
+
+ODB-Info ::= SEQUENCE {
+ odb-Data ODB-Data,
+ notificationToCSE NULL OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+CAMEL-SubscriptionInfo ::= SEQUENCE {
+ o-CSI [0] O-CSI OPTIONAL,
+ o-BcsmCamelTDP-CriteriaList [1] O-BcsmCamelTDPCriteriaList OPTIONAL,
+ d-CSI [2] D-CSI OPTIONAL,
+ t-CSI [3] T-CSI OPTIONAL,
+ t-BCSM-CAMEL-TDP-CriteriaList [4] T-BCSM-CAMEL-TDP-CriteriaList OPTIONAL,
+ vt-CSI [5] T-CSI OPTIONAL,
+ vt-BCSM-CAMEL-TDP-CriteriaList [6] T-BCSM-CAMEL-TDP-CriteriaList OPTIONAL,
+ tif-CSI [7] NULL OPTIONAL,
+ tif-CSI-NotificationToCSE [8] NULL OPTIONAL,
+ gprs-CSI [9] GPRS-CSI OPTIONAL,
+ mo-sms-CSI [10] SMS-CSI OPTIONAL,
+ ss-CSI [11] SS-CSI OPTIONAL,
+ m-CSI [12] M-CSI OPTIONAL,
+ extensionContainer [13] ExtensionContainer OPTIONAL,
+ ...,
+ specificCSIDeletedList [14] SpecificCSI-Withdraw OPTIONAL,
+ mt-sms-CSI [15] SMS-CSI OPTIONAL,
+ mt-smsCAMELTDP-CriteriaList [16] MT-smsCAMELTDP-CriteriaList OPTIONAL,
+ mg-csi [17] MG-CSI OPTIONAL,
+ o-IM-CSI [18] O-CSI OPTIONAL,
+ o-IM-BcsmCamelTDP-CriteriaList [19] O-BcsmCamelTDPCriteriaList OPTIONAL,
+ d-IM-CSI [20] D-CSI OPTIONAL,
+ vt-IM-CSI [21] T-CSI OPTIONAL,
+ vt-IM-BCSM-CAMEL-TDP-CriteriaList [22] T-BCSM-CAMEL-TDP-CriteriaList OPTIONAL
+ }
+
+AnyTimeModificationArg ::= SEQUENCE {
+ subscriberIdentity [0] SubscriberIdentity,
+ gsmSCF-Address [1] ISDN-AddressString,
+ modificationRequestFor-CF-Info [2] ModificationRequestFor-CF-Info OPTIONAL,
+ modificationRequestFor-CB-Info [3] ModificationRequestFor-CB-Info OPTIONAL,
+ modificationRequestFor-CSI [4] ModificationRequestFor-CSI OPTIONAL,
+ extensionContainer [5] ExtensionContainer OPTIONAL,
+ longFTN-Supported [6] NULL OPTIONAL,
+ ...,
+ modificationRequestFor-ODB-data [7] ModificationRequestFor-ODB-data OPTIONAL,
+ modificationRequestFor-IP-SM-GW-Data [8] ModificationRequestFor-IP-SM-GW-Data OPTIONAL }
+
+AnyTimeModificationRes ::= SEQUENCE {
+ ss-InfoFor-CSE [0] Ext-SS-InfoFor-CSE OPTIONAL,
+ camel-SubscriptionInfo [1] CAMEL-SubscriptionInfo OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...,
+ odb-Info [3] ODB-Info OPTIONAL }
+
+ModificationRequestFor-CF-Info ::= SEQUENCE {
+ ss-Code [0] SS-Code,
+ basicService [1] Ext-BasicServiceCode OPTIONAL,
+ ss-Status [2] Ext-SS-Status OPTIONAL,
+ forwardedToNumber [3] AddressString OPTIONAL,
+ forwardedToSubaddress [4] ISDN-SubaddressString OPTIONAL,
+ noReplyConditionTime [5] Ext-NoRepCondTime OPTIONAL,
+ modifyNotificationToCSE [6] ModificationInstruction OPTIONAL,
+ extensionContainer [7] ExtensionContainer OPTIONAL,
+ ...}
+
+ModificationRequestFor-CB-Info ::= SEQUENCE {
+ ss-Code [0] SS-Code,
+ basicService [1] Ext-BasicServiceCode OPTIONAL,
+ ss-Status [2] Ext-SS-Status OPTIONAL,
+ password [3] Password OPTIONAL,
+ wrongPasswordAttemptsCounter [4] WrongPasswordAttemptsCounter OPTIONAL,
+ modifyNotificationToCSE [5] ModificationInstruction OPTIONAL,
+ extensionContainer [6] ExtensionContainer OPTIONAL,
+ ...}
+
+ModificationRequestFor-ODB-data ::= SEQUENCE {
+ odb-data [0] ODB-Data OPTIONAL,
+ modifyNotificationToCSE [1] ModificationInstruction OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...}
+
+ModificationRequestFor-CSI ::= SEQUENCE {
+ requestedCamel-SubscriptionInfo [0] RequestedCAMEL-SubscriptionInfo,
+ modifyNotificationToCSE [1] ModificationInstruction OPTIONAL,
+ modifyCSI-State [2] ModificationInstruction OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...,
+ additionalRequestedCAMEL-SubscriptionInfo
+ [4] AdditionalRequestedCAMEL-SubscriptionInfo
+ OPTIONAL }
+-- requestedCamel-SubscriptionInfo shall be discarded if
+-- additionalRequestedCAMEL-SubscriptionInfo is received
+
+ModificationRequestFor-IP-SM-GW-Data ::= SEQUENCE {
+ modifyRegistrationStatus [0] ModificationInstruction OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ...}
+
+ModificationInstruction ::= ENUMERATED {
+ deactivate (0),
+ activate (1)}
+
+-- subscriber data modification notification types
+
+NoteSubscriberDataModifiedArg ::= SEQUENCE {
+ imsi IMSI,
+ msisdn ISDN-AddressString,
+ forwardingInfoFor-CSE [0] Ext-ForwardingInfoFor-CSE OPTIONAL,
+ callBarringInfoFor-CSE [1] Ext-CallBarringInfoFor-CSE OPTIONAL,
+ odb-Info [2] ODB-Info OPTIONAL,
+ camel-SubscriptionInfo [3] CAMEL-SubscriptionInfo OPTIONAL,
+ allInformationSent [4] NULL OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+NoteSubscriberDataModifiedRes ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+-- mobility management event notificatioon info types
+
+NoteMM-EventArg::= SEQUENCE {
+ serviceKey ServiceKey,
+ eventMet [0] MM-Code,
+ imsi [1] IMSI,
+ msisdn [2] ISDN-AddressString,
+ locationInformation [3] LocationInformation OPTIONAL,
+ supportedCAMELPhases [5] SupportedCamelPhases OPTIONAL,
+ extensionContainer [6] ExtensionContainer OPTIONAL,
+ ...,
+ locationInformationGPRS [7] LocationInformationGPRS OPTIONAL,
+ offeredCamel4Functionalities [8] OfferedCamel4Functionalities OPTIONAL
+}
+
+NoteMM-EventRes ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+Ext-SS-InfoFor-CSE ::= CHOICE {
+ forwardingInfoFor-CSE [0] Ext-ForwardingInfoFor-CSE,
+ callBarringInfoFor-CSE [1] Ext-CallBarringInfoFor-CSE
+ }
+
+Ext-ForwardingInfoFor-CSE ::= SEQUENCE {
+ ss-Code [0] SS-Code,
+ forwardingFeatureList [1] Ext-ForwFeatureList,
+ notificationToCSE [2] NULL OPTIONAL,
+ extensionContainer [3] ExtensionContainer OPTIONAL,
+ ...}
+
+Ext-CallBarringInfoFor-CSE ::= SEQUENCE {
+ ss-Code [0] SS-Code,
+ callBarringFeatureList [1] Ext-CallBarFeatureList,
+ password [2] Password OPTIONAL,
+ wrongPasswordAttemptsCounter [3] WrongPasswordAttemptsCounter OPTIONAL,
+ notificationToCSE [4] NULL OPTIONAL,
+ extensionContainer [5] ExtensionContainer OPTIONAL,
+ ...}
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-OM-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-OM-DataTypes.asn
new file mode 100644
index 000000000..024dd6f9b
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-OM-DataTypes.asn
@@ -0,0 +1,216 @@
+-- $Id: MAP-OM-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- 17.7.2 Operation and maintenance data types
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+
+MAP-OM-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-OM-DataTypes (12) version11 (11)}
+
+DEFINITIONS
+
+IMPLICIT TAGS
+
+::=
+
+BEGIN
+
+EXPORTS
+ ActivateTraceModeArg,
+ ActivateTraceModeRes,
+ DeactivateTraceModeArg,
+ DeactivateTraceModeRes,
+ TracePropagationList
+;
+
+IMPORTS
+ AddressString,
+ IMSI
+FROM MAP-CommonDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
+
+ ExtensionContainer
+FROM MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+
+;
+
+ActivateTraceModeArg ::= SEQUENCE {
+ imsi [0] IMSI OPTIONAL,
+ traceReference [1] TraceReference,
+ traceType [2] TraceType,
+ omc-Id [3] AddressString OPTIONAL,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ...,
+ traceReference2 [5] TraceReference2 OPTIONAL,
+ traceDepthList [6] TraceDepthList OPTIONAL,
+ traceNE-TypeList [7] TraceNE-TypeList OPTIONAL,
+ traceInterfaceList [8] TraceInterfaceList OPTIONAL,
+ traceEventList [9] TraceEventList OPTIONAL
+ }
+
+TraceReference ::= OCTET STRING (SIZE (1..2))
+
+TraceReference2 ::= OCTET STRING (SIZE (3))
+
+TraceRecordingSessionReference ::= OCTET STRING (SIZE (2))
+
+TraceType ::= INTEGER
+ (0..255)
+ -- Trace types are fully defined in 3GPP TS 52.008. [61]
+
+TraceDepthList ::= SEQUENCE {
+ msc-s-TraceDepth [0] TraceDepth OPTIONAL,
+ mgw-TraceDepth [1] TraceDepth OPTIONAL,
+ sgsn-TraceDepth [2] TraceDepth OPTIONAL,
+ ggsn-TraceDepth [3] TraceDepth OPTIONAL,
+ rnc-TraceDepth [4] TraceDepth OPTIONAL,
+ bmsc-TraceDepth [5] TraceDepth OPTIONAL,
+ ...}
+
+TraceDepth ::= ENUMERATED {
+ minimum (0),
+ medium (1),
+ maximum (2),
+ ...}
+-- The value medium is applicable only for RNC. For other network elements, if value medium
+-- is received, value minimum shall be applied.
+
+TraceNE-TypeList ::= BIT STRING {
+ msc-s (0),
+ mgw (1),
+ sgsn (2),
+ ggsn (3),
+ rnc (4),
+ bm-sc (5)} (SIZE (6..16))
+-- Other bits than listed above shall be discarded.
+
+TraceInterfaceList ::= SEQUENCE {
+ msc-s-List [0] MSC-S-InterfaceList OPTIONAL,
+ mgw-List [1] MGW-InterfaceList OPTIONAL,
+ sgsn-List [2] SGSN-InterfaceList OPTIONAL,
+ ggsn-List [3] GGSN-InterfaceList OPTIONAL,
+ rnc-List [4] RNC-InterfaceList OPTIONAL,
+ bmsc-List [5] BMSC-InterfaceList OPTIONAL,
+ ...}
+
+MSC-S-InterfaceList ::= BIT STRING {
+ a (0),
+ iu (1),
+ mc (2),
+ map-g (3),
+ map-b (4),
+ map-e (5),
+ map-f (6),
+ cap (7),
+ map-d (8),
+ map-c (9)} (SIZE (10..16))
+-- Other bits than listed above shall be discarded.
+
+MGW-InterfaceList ::= BIT STRING {
+ mc (0),
+ nb-up (1),
+ iu-up (2)} (SIZE (3..8))
+-- Other bits than listed above shall be discarded.
+
+SGSN-InterfaceList ::= BIT STRING {
+ gb (0),
+ iu (1),
+ gn (2),
+ map-gr (3),
+ map-gd (4),
+ map-gf (5),
+ gs (6),
+ ge (7)} (SIZE (8..16))
+-- Other bits than listed above shall be discarded.
+
+GGSN-InterfaceList ::= BIT STRING {
+ gn (0),
+ gi (1),
+ gmb (2)} (SIZE (3..8))
+-- Other bits than listed above shall be discarded.
+
+RNC-InterfaceList ::= BIT STRING {
+ iu (0),
+ iur (1),
+ iub (2),
+ uu (3)} (SIZE (4..8))
+-- Other bits than listed above shall be discarded.
+
+BMSC-InterfaceList ::= BIT STRING {
+ gmb (0)} (SIZE (1..8))
+-- Other bits than listed above shall be discarded.
+
+TraceEventList ::= SEQUENCE {
+ msc-s-List [0] MSC-S-EventList OPTIONAL,
+ mgw-List [1] MGW-EventList OPTIONAL,
+ sgsn-List [2] SGSN-EventList OPTIONAL,
+ ggsn-List [3] GGSN-EventList OPTIONAL,
+ bmsc-List [4] BMSC-EventList OPTIONAL,
+ ...}
+
+MSC-S-EventList ::= BIT STRING {
+ mo-mtCall (0),
+ mo-mt-sms (1),
+ lu-imsiAttach-imsiDetach (2),
+ handovers (3),
+ ss (4)} (SIZE (5..16))
+-- Other bits than listed above shall be discarded.
+
+MGW-EventList ::= BIT STRING {
+ context (0)} (SIZE (1..8))
+-- Other bits than listed above shall be discarded.
+
+SGSN-EventList ::= BIT STRING {
+ pdpContext (0),
+ mo-mt-sms (1),
+ rau-gprsAttach-gprsDetach (2),
+ mbmsContext (3)} (SIZE (4..16))
+-- Other bits than listed above shall be discarded.
+
+GGSN-EventList ::= BIT STRING {
+ pdpContext (0),
+ mbmsContext (1)} (SIZE (2..8))
+-- Other bits than listed above shall be discarded.
+
+BMSC-EventList ::= BIT STRING {
+ mbmsMulticastServiceActivation (0)} (SIZE (1..8))
+-- Other bits than listed above shall be discarded.
+
+
+TracePropagationList ::= SEQUENCE {
+ traceReference [0] TraceReference OPTIONAL,
+ traceType [1] TraceType OPTIONAL,
+ traceReference2 [2] TraceReference2 OPTIONAL,
+ traceRecordingSessionReference [3] TraceRecordingSessionReference OPTIONAL,
+ rnc-TraceDepth [4] TraceDepth OPTIONAL,
+ rnc-InterfaceList [5] RNC-InterfaceList OPTIONAL,
+ msc-s-TraceDepth [6] TraceDepth OPTIONAL,
+ msc-s-InterfaceList [7] MSC-S-InterfaceList OPTIONAL,
+ msc-s-EventList [8] MSC-S-EventList OPTIONAL,
+ mgw-TraceDepth [9] TraceDepth OPTIONAL,
+ mgw-InterfaceList [10] MGW-InterfaceList OPTIONAL,
+ mgw-EventList [11] MGW-EventList OPTIONAL,
+ ...}
+
+ActivateTraceModeRes ::= SEQUENCE {
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...,
+ traceSupportIndicator [1] NULL OPTIONAL
+ }
+
+DeactivateTraceModeArg ::= SEQUENCE {
+ imsi [0] IMSI OPTIONAL,
+ traceReference [1] TraceReference,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...,
+ traceReference2 [3] TraceReference2 OPTIONAL
+ }
+
+DeactivateTraceModeRes ::= SEQUENCE {
+ extensionContainer [0] ExtensionContainer OPTIONAL,
+ ...}
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-SM-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-SM-DataTypes.asn
new file mode 100644
index 000000000..0ef941f2b
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-SM-DataTypes.asn
@@ -0,0 +1,270 @@
+-- $Id: MAP-SM-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+-- 17.7.6 Short message data types
+
+MAP-SM-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SM-DataTypes (16) version11 (11)}
+
+DEFINITIONS
+
+IMPLICIT TAGS
+
+::=
+
+BEGIN
+
+EXPORTS
+ RoutingInfoForSM-Arg,
+ RoutingInfoForSM-Res,
+ MO-ForwardSM-Arg,
+ MO-ForwardSM-Res,
+ MT-ForwardSM-Arg,
+ MT-ForwardSM-Res,
+ ReportSM-DeliveryStatusArg,
+ ReportSM-DeliveryStatusRes,
+ AlertServiceCentreArg,
+ InformServiceCentreArg,
+ ReadyForSM-Arg,
+ ReadyForSM-Res,
+ SM-DeliveryOutcome,
+ AlertReason,
+ Additional-Number,
+ MT-ForwardSM-VGCS-Arg,
+ MT-ForwardSM-VGCS-Res
+;
+
+IMPORTS
+ AddressString,
+ ISDN-AddressString,
+ SignalInfo,
+ IMSI,
+ LMSI,
+ ASCI-CallReference
+
+FROM MAP-CommonDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
+
+ AbsentSubscriberDiagnosticSM
+FROM MAP-ER-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ER-DataTypes (17) version11 (11)}
+
+ ExtensionContainer
+FROM MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+;
+
+
+RoutingInfoForSM-Arg ::= SEQUENCE {
+ msisdn [0] ISDN-AddressString,
+ sm-RP-PRI [1] BOOLEAN,
+ serviceCentreAddress [2] AddressString,
+ extensionContainer [6] ExtensionContainer OPTIONAL,
+ ... ,
+ gprsSupportIndicator [7] NULL OPTIONAL,
+ -- gprsSupportIndicator is set only if the SMS-GMSC supports
+ -- receiving of two numbers from the HLR
+ sm-RP-MTI [8] SM-RP-MTI OPTIONAL,
+ sm-RP-SMEA [9] SM-RP-SMEA OPTIONAL,
+ sm-deliveryNotIntended [10] SM-DeliveryNotIntended OPTIONAL }
+
+SM-DeliveryNotIntended ::= ENUMERATED {
+ onlyIMSI-requested (0),
+ onlyMCC-MNC-requested (1),
+ ...}
+
+SM-RP-MTI ::= INTEGER (0..10)
+ -- 0 SMS Deliver
+ -- 1 SMS Status Report
+ -- other values are reserved for future use and shall be discarded if
+ -- received
+
+SM-RP-SMEA ::= OCTET STRING (SIZE (1..12))
+ -- this parameter contains an address field which is encoded
+ -- as defined in 3GPP TS 23.040. An address field contains 3 elements :
+ -- address-length
+ -- type-of-address
+ -- address-value
+
+RoutingInfoForSM-Res ::= SEQUENCE {
+ imsi IMSI,
+ locationInfoWithLMSI [0] LocationInfoWithLMSI,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ...}
+
+LocationInfoWithLMSI ::= SEQUENCE {
+ networkNode-Number [1] ISDN-AddressString,
+ lmsi LMSI OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ gprsNodeIndicator [5] NULL OPTIONAL,
+ -- gprsNodeIndicator is set only if the SGSN number is sent as the
+ -- Network Node Number
+ additional-Number [6] Additional-Number OPTIONAL
+ -- NetworkNode-number can be either msc-number or sgsn-number or IP-SM-GW
+ -- number or SMS Router number
+ }
+
+Additional-Number ::= CHOICE {
+ msc-Number [0] ISDN-AddressString,
+ sgsn-Number [1] ISDN-AddressString}
+ -- additional-number can be either msc-number or sgsn-number
+ -- if received networkNode-number is msc-number then the
+ -- additional number is sgsn-number
+ -- if received networkNode-number is sgsn-number then the
+ -- additional number is msc-number
+
+MO-ForwardSM-Arg ::= SEQUENCE {
+ sm-RP-DA SM-RP-DA,
+ sm-RP-OA SM-RP-OA,
+ sm-RP-UI SignalInfo,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ imsi IMSI OPTIONAL }
+
+MO-ForwardSM-Res ::= SEQUENCE {
+ sm-RP-UI SignalInfo OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+MT-ForwardSM-Arg ::= SEQUENCE {
+ sm-RP-DA SM-RP-DA,
+ sm-RP-OA SM-RP-OA,
+ sm-RP-UI SignalInfo,
+ moreMessagesToSend NULL OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+MT-ForwardSM-Res ::= SEQUENCE {
+ sm-RP-UI SignalInfo OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+SM-RP-DA ::= CHOICE {
+ imsi [0] IMSI,
+ lmsi [1] LMSI,
+ serviceCentreAddressDA [4] AddressString,
+ noSM-RP-DA [5] NULL}
+
+SM-RP-OA ::= CHOICE {
+ msisdn [2] ISDN-AddressString,
+ serviceCentreAddressOA [4] AddressString,
+ noSM-RP-OA [5] NULL}
+
+ReportSM-DeliveryStatusArg ::= SEQUENCE {
+ msisdn ISDN-AddressString,
+ serviceCentreAddress AddressString,
+ sm-DeliveryOutcome SM-DeliveryOutcome,
+ absentSubscriberDiagnosticSM [0] AbsentSubscriberDiagnosticSM
+ OPTIONAL,
+ extensionContainer [1] ExtensionContainer OPTIONAL,
+ ...,
+ gprsSupportIndicator [2] NULL OPTIONAL,
+ -- gprsSupportIndicator is set only if the SMS-GMSC supports
+ -- handling of two delivery outcomes
+ deliveryOutcomeIndicator [3] NULL OPTIONAL,
+ -- DeliveryOutcomeIndicator is set when the SM-DeliveryOutcome
+ -- is for GPRS
+ additionalSM-DeliveryOutcome [4] SM-DeliveryOutcome OPTIONAL,
+ -- If received, additionalSM-DeliveryOutcome is for GPRS
+ -- If DeliveryOutcomeIndicator is set, then AdditionalSM-DeliveryOutcome shall be absent
+ additionalAbsentSubscriberDiagnosticSM [5] AbsentSubscriberDiagnosticSM OPTIONAL,
+ -- If received additionalAbsentSubscriberDiagnosticSM is for GPRS
+ -- If DeliveryOutcomeIndicator is set, then AdditionalAbsentSubscriberDiagnosticSM
+ -- shall be absent
+ ip-sm-gw-Indicator [6] NULL OPTIONAL,
+ -- the ip-sm-gw indicator indicates by its presence that sm-deliveryOutcome
+ -- is for delivery via IMS
+ -- If present, deliveryOutcomeIndicator shall be absent.
+ ip-sm-gw-sm-deliveryOutcome [7] SM-DeliveryOutcome OPTIONAL,
+ -- If received ip-sm-gw-sm-deliveryOutcome is for delivery via IMS
+ -- If ip-sm-gw-Indicator is set, then ip-sm-gw-sm-deliveryOutcome shall be absent
+ ip-sm-gw-absentSubscriberDiagnosticSM [8] AbsentSubscriberDiagnosticSM OPTIONAL
+ -- If received ip-sm-gw-sm-absentSubscriberDiagnosticSM is for delivery via IMS
+ -- If ip-sm-gw-Indicator is set, then ip-sm-gw-sm-absentSubscriberDiagnosticSM
+ -- shall be absent
+}
+
+SM-DeliveryOutcome ::= ENUMERATED {
+ memoryCapacityExceeded (0),
+ absentSubscriber (1),
+ successfulTransfer (2)}
+
+ReportSM-DeliveryStatusRes ::= SEQUENCE {
+ storedMSISDN ISDN-AddressString OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+AlertServiceCentreArg ::= SEQUENCE {
+ msisdn ISDN-AddressString,
+ serviceCentreAddress AddressString,
+ ...}
+
+InformServiceCentreArg ::= SEQUENCE {
+ storedMSISDN ISDN-AddressString OPTIONAL,
+ mw-Status MW-Status OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ... ,
+ absentSubscriberDiagnosticSM AbsentSubscriberDiagnosticSM OPTIONAL,
+ additionalAbsentSubscriberDiagnosticSM [0] AbsentSubscriberDiagnosticSM OPTIONAL }
+ -- additionalAbsentSubscriberDiagnosticSM may be present only if
+ -- absentSubscriberDiagnosticSM is present.
+ -- if included, additionalAbsentSubscriberDiagnosticSM is for GPRS and
+ -- absentSubscriberDiagnosticSM is for non-GPRS
+
+MW-Status ::= BIT STRING {
+ sc-AddressNotIncluded (0),
+ mnrf-Set (1),
+ mcef-Set (2) ,
+ mnrg-Set (3)} (SIZE (6..16))
+ -- exception handling:
+ -- bits 4 to 15 shall be ignored if received and not understood
+
+ReadyForSM-Arg ::= SEQUENCE {
+ imsi [0] IMSI,
+ alertReason AlertReason,
+ alertReasonIndicator NULL OPTIONAL,
+ -- alertReasonIndicator is set only when the alertReason
+ -- sent to HLR is for GPRS
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ additionalAlertReasonIndicator [1] NULL OPTIONAL
+ -- additionalAlertReasonIndicator is set only when the alertReason
+ -- sent to HLR is for IP-SM-GW
+ }
+
+ReadyForSM-Res ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+AlertReason ::= ENUMERATED {
+ ms-Present (0),
+ memoryAvailable (1)}
+
+MT-ForwardSM-VGCS-Arg ::= SEQUENCE {
+ asciCallReference ASCI-CallReference,
+ sm-RP-OA SM-RP-OA,
+ sm-RP-UI SignalInfo,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...}
+
+MT-ForwardSM-VGCS-Res ::= SEQUENCE {
+ sm-RP-UI [0] SignalInfo OPTIONAL,
+ dispatcherList [1] DispatcherList OPTIONAL,
+ ongoingCall NULL OPTIONAL,
+ extensionContainer [2] ExtensionContainer OPTIONAL,
+ ...}
+
+DispatcherList ::=
+ SEQUENCE SIZE (1..maxNumOfDispatchers) OF
+ ISDN-AddressString
+
+maxNumOfDispatchers INTEGER ::= 5
+
+
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-SS-Code.asn b/rrlp-ephemeris/asn1/MAP-SS-Code.asn
new file mode 100644
index 000000000..163f2dc3a
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-SS-Code.asn
@@ -0,0 +1,190 @@
+-- $Id: MAP-SS-Code.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+-- 17.7.5 Supplementary service codes
+
+MAP-SS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
+
+DEFINITIONS
+
+::=
+
+BEGIN
+
+SS-Code ::= OCTET STRING (SIZE (1))
+ -- This type is used to represent the code identifying a single
+ -- supplementary service, a group of supplementary services, or
+ -- all supplementary services. The services and abbreviations
+ -- used are defined in TS 3GPP TS 22.004 [5]. The internal structure is
+ -- defined as follows:
+ --
+ -- bits 87654321: group (bits 8765), and specific service
+ -- (bits 4321)
+
+allSS SS-Code ::= '00000000'B
+ -- reserved for possible future use
+ -- all SS
+
+allLineIdentificationSS SS-Code ::= '00010000'B
+ -- reserved for possible future use
+ -- all line identification SS
+clip SS-Code ::= '00010001'B
+ -- calling line identification presentation
+clir SS-Code ::= '00010010'B
+ -- calling line identification restriction
+colp SS-Code ::= '00010011'B
+ -- connected line identification presentation
+colr SS-Code ::= '00010100'B
+ -- connected line identification restriction
+mci SS-Code ::= '00010101'B
+ -- reserved for possible future use
+ -- malicious call identification
+
+allNameIdentificationSS SS-Code ::= '00011000'B
+ -- all name identification SS
+cnap SS-Code ::= '00011001'B
+ -- calling name presentation
+
+ -- SS-Codes '00011010'B to '00011111'B are reserved for future
+ -- NameIdentification Supplementary Service use.
+
+allForwardingSS SS-Code ::= '00100000'B
+ -- all forwarding SS
+cfu SS-Code ::= '00100001'B
+ -- call forwarding unconditional
+allCondForwardingSS SS-Code ::= '00101000'B
+ -- all conditional forwarding SS
+cfb SS-Code ::= '00101001'B
+ -- call forwarding on mobile subscriber busy
+cfnry SS-Code ::= '00101010'B
+ -- call forwarding on no reply
+cfnrc SS-Code ::= '00101011'B
+ -- call forwarding on mobile subscriber not reachable
+cd SS-Code ::= '00100100'B
+ -- call deflection
+
+allCallOfferingSS SS-Code ::= '00110000'B
+ -- reserved for possible future use
+ -- all call offering SS includes also all forwarding SS
+ect SS-Code ::= '00110001'B
+ -- explicit call transfer
+mah SS-Code ::= '00110010'B
+ -- reserved for possible future use
+ -- mobile access hunting
+
+allCallCompletionSS SS-Code ::= '01000000'B
+ -- reserved for possible future use
+ -- all Call completion SS
+cw SS-Code ::= '01000001'B
+ -- call waiting
+hold SS-Code ::= '01000010'B
+ -- call hold
+ccbs-A SS-Code ::= '01000011'B
+ -- completion of call to busy subscribers, originating side
+ -- this SS-Code is used only in InsertSubscriberData, DeleteSubscriberData
+ -- and InterrogateSS
+ccbs-B SS-Code ::= '01000100'B
+ -- completion of call to busy subscribers, destination side
+ -- this SS-Code is used only in InsertSubscriberData and DeleteSubscriberData
+mc SS-Code ::= '01000101'B
+ -- multicall
+
+allMultiPartySS SS-Code ::= '01010000'B
+ -- reserved for possible future use
+ -- all multiparty SS
+multiPTY SS-Code ::= '01010001'B
+ -- multiparty
+
+allCommunityOfInterest-SS SS-Code ::= '01100000'B
+ -- reserved for possible future use
+ -- all community of interest SS
+cug SS-Code ::= '01100001'B
+ -- closed user group
+
+allChargingSS SS-Code ::= '01110000'B
+ -- reserved for possible future use
+ -- all charging SS
+aoci SS-Code ::= '01110001'B
+ -- advice of charge information
+aocc SS-Code ::= '01110010'B
+ -- advice of charge charging
+
+allAdditionalInfoTransferSS SS-Code ::= '10000000'B
+ -- reserved for possible future use
+ -- all additional information transfer SS
+uus1 SS-Code ::= '10000001'B
+ -- UUS1 user-to-user signalling
+uus2 SS-Code ::= '10000010'B
+ -- UUS2 user-to-user signalling
+uus3 SS-Code ::= '10000011'B
+ -- UUS3 user-to-user signalling
+
+allBarringSS SS-Code ::= '10010000'B
+ -- all barring SS
+barringOfOutgoingCalls SS-Code ::= '10010001'B
+ -- barring of outgoing calls
+baoc SS-Code ::= '10010010'B
+ -- barring of all outgoing calls
+boic SS-Code ::= '10010011'B
+ -- barring of outgoing international calls
+boicExHC SS-Code ::= '10010100'B
+ -- barring of outgoing international calls except those directed
+ -- to the home PLMN Country
+barringOfIncomingCalls SS-Code ::= '10011001'B
+ -- barring of incoming calls
+baic SS-Code ::= '10011010'B
+ -- barring of all incoming calls
+bicRoam SS-Code ::= '10011011'B
+ -- barring of incoming calls when roaming outside home PLMN
+ -- Country
+
+allPLMN-specificSS SS-Code ::= '11110000'B
+plmn-specificSS-1 SS-Code ::= '11110001'B
+plmn-specificSS-2 SS-Code ::= '11110010'B
+plmn-specificSS-3 SS-Code ::= '11110011'B
+plmn-specificSS-4 SS-Code ::= '11110100'B
+plmn-specificSS-5 SS-Code ::= '11110101'B
+plmn-specificSS-6 SS-Code ::= '11110110'B
+plmn-specificSS-7 SS-Code ::= '11110111'B
+plmn-specificSS-8 SS-Code ::= '11111000'B
+plmn-specificSS-9 SS-Code ::= '11111001'B
+plmn-specificSS-A SS-Code ::= '11111010'B
+plmn-specificSS-B SS-Code ::= '11111011'B
+plmn-specificSS-C SS-Code ::= '11111100'B
+plmn-specificSS-D SS-Code ::= '11111101'B
+plmn-specificSS-E SS-Code ::= '11111110'B
+plmn-specificSS-F SS-Code ::= '11111111'B
+
+allCallPrioritySS SS-Code ::= '10100000'B
+ -- reserved for possible future use
+ -- all call priority SS
+emlpp SS-Code ::= '10100001'B
+ -- enhanced Multilevel Precedence Pre-emption (EMLPP) service
+
+allLCSPrivacyException SS-Code ::= '10110000'B
+ -- all LCS Privacy Exception Classes
+universal SS-Code ::= '10110001'B
+ -- allow location by any LCS client
+callSessionRelated SS-Code ::= '10110010'B
+ -- allow location by any value added LCS client to which a call/session
+ -- is established from the target MS
+callSessionUnrelated SS-Code ::= '10110011'B
+ -- allow location by designated external value added LCS clients
+plmnoperator SS-Code ::= '10110100'B
+ -- allow location by designated PLMN operator LCS clients
+serviceType SS-Code ::= '10110101'B
+ -- allow location by LCS clients of a designated LCS service type
+
+allMOLR-SS SS-Code ::= '11000000'B
+ -- all Mobile Originating Location Request Classes
+basicSelfLocation SS-Code ::= '11000001'B
+ -- allow an MS to request its own location
+autonomousSelfLocation SS-Code ::= '11000010'B
+ -- allow an MS to perform self location without interaction
+ -- with the PLMN for a predetermined period of time
+transferToThirdParty SS-Code ::= '11000011'B
+ -- allow an MS to request transfer of its location to another LCS client
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-SS-DataTypes.asn b/rrlp-ephemeris/asn1/MAP-SS-DataTypes.asn
new file mode 100644
index 000000000..253f7f01a
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-SS-DataTypes.asn
@@ -0,0 +1,342 @@
+-- $Id: MAP-SS-DataTypes.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+-- 17.7.4 Supplementary service data types
+
+MAP-SS-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SS-DataTypes (14) version11 (11)}
+
+DEFINITIONS
+
+IMPLICIT TAGS
+
+::=
+
+BEGIN
+
+EXPORTS
+ RegisterSS-Arg,
+ SS-Info,
+ SS-Status,
+ SS-SubscriptionOption,
+ SS-ForBS-Code,
+ InterrogateSS-Res,
+ USSD-Arg,
+ USSD-Res,
+ USSD-DataCodingScheme,
+ USSD-String,
+ Password,
+ GuidanceInfo,
+ SS-List,
+ SS-InfoList,
+ OverrideCategory,
+ CliRestrictionOption,
+ NoReplyConditionTime,
+ ForwardingOptions,
+ maxNumOfSS,
+ SS-Data,
+ SS-InvocationNotificationArg,
+ SS-InvocationNotificationRes,
+ CCBS-Feature,
+ RegisterCC-EntryArg,
+ RegisterCC-EntryRes,
+ EraseCC-EntryArg,
+ EraseCC-EntryRes
+;
+
+IMPORTS
+ AddressString,
+ ISDN-AddressString,
+ ISDN-SubaddressString,
+ FTN-AddressString,
+ IMSI,
+ BasicServiceCode,
+ AlertingPattern,
+ EMLPP-Priority,
+ MaxMC-Bearers,
+ MC-Bearers,
+ ExternalSignalInfo
+FROM MAP-CommonDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-CommonDataTypes (18) version11 (11)}
+
+ ExtensionContainer
+FROM MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+
+ SS-Code
+FROM MAP-SS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-SS-Code (15) version11 (11)}
+;
+
+
+RegisterSS-Arg ::= SEQUENCE {
+ ss-Code SS-Code,
+ basicService BasicServiceCode OPTIONAL,
+ forwardedToNumber [4] AddressString OPTIONAL,
+ forwardedToSubaddress [6] ISDN-SubaddressString OPTIONAL,
+ noReplyConditionTime [5] NoReplyConditionTime OPTIONAL,
+ ...,
+ defaultPriority [7] EMLPP-Priority OPTIONAL,
+ nbrUser [8] MC-Bearers OPTIONAL,
+ longFTN-Supported [9] NULL OPTIONAL }
+
+NoReplyConditionTime ::= INTEGER (5..30)
+
+SS-Info ::= CHOICE {
+ forwardingInfo [0] ForwardingInfo,
+ callBarringInfo [1] CallBarringInfo,
+ ss-Data [3] SS-Data}
+
+ForwardingInfo ::= SEQUENCE {
+ ss-Code SS-Code OPTIONAL,
+ forwardingFeatureList ForwardingFeatureList,
+ ...}
+
+ForwardingFeatureList ::=
+ SEQUENCE SIZE (1..maxNumOfBasicServiceGroups) OF
+ ForwardingFeature
+
+ForwardingFeature ::= SEQUENCE {
+ basicService BasicServiceCode OPTIONAL,
+ ss-Status [4] SS-Status OPTIONAL,
+ forwardedToNumber [5] ISDN-AddressString OPTIONAL,
+ forwardedToSubaddress [8] ISDN-SubaddressString OPTIONAL,
+ forwardingOptions [6] ForwardingOptions OPTIONAL,
+ noReplyConditionTime [7] NoReplyConditionTime OPTIONAL,
+ ...,
+ longForwardedToNumber [9] FTN-AddressString OPTIONAL }
+
+SS-Status ::= OCTET STRING (SIZE (1))
+
+ -- bits 8765: 0000 (unused)
+ -- bits 4321: Used to convey the "P bit","R bit","A bit" and "Q bit",
+ -- representing supplementary service state information
+ -- as defined in TS 3GPP TS 23.011 [22]
+
+ -- bit 4: "Q bit"
+
+ -- bit 3: "P bit"
+
+ -- bit 2: "R bit"
+
+ -- bit 1: "A bit"
+
+ForwardingOptions ::= OCTET STRING (SIZE (1))
+
+ -- bit 8: notification to forwarding party
+ -- 0 no notification
+ -- 1 notification
+
+ -- bit 7: redirecting presentation
+ -- 0 no presentation
+ -- 1 presentation
+
+ -- bit 6: notification to calling party
+ -- 0 no notification
+ -- 1 notification
+
+ -- bit 5: 0 (unused)
+
+ -- bits 43: forwarding reason
+ -- 00 ms not reachable
+ -- 01 ms busy
+ -- 10 no reply
+ -- 11 unconditional when used in a SRI Result,
+ -- or call deflection when used in a RCH Argument
+ -- bits 21: 00 (unused)
+
+CallBarringInfo ::= SEQUENCE {
+ ss-Code SS-Code OPTIONAL,
+ callBarringFeatureList CallBarringFeatureList,
+ ...}
+
+CallBarringFeatureList ::= SEQUENCE SIZE (1..maxNumOfBasicServiceGroups) OF
+ CallBarringFeature
+
+CallBarringFeature ::= SEQUENCE {
+ basicService BasicServiceCode OPTIONAL,
+ ss-Status [4] SS-Status OPTIONAL,
+ ...}
+
+SS-Data ::= SEQUENCE {
+ ss-Code SS-Code OPTIONAL,
+ ss-Status [4] SS-Status OPTIONAL,
+ ss-SubscriptionOption SS-SubscriptionOption OPTIONAL,
+ basicServiceGroupList BasicServiceGroupList OPTIONAL,
+ ...,
+ defaultPriority EMLPP-Priority OPTIONAL,
+ nbrUser [5] MC-Bearers OPTIONAL
+ }
+
+SS-SubscriptionOption ::= CHOICE {
+ cliRestrictionOption [2] CliRestrictionOption,
+ overrideCategory [1] OverrideCategory}
+
+CliRestrictionOption ::= ENUMERATED {
+ permanent (0),
+ temporaryDefaultRestricted (1),
+ temporaryDefaultAllowed (2)}
+
+OverrideCategory ::= ENUMERATED {
+ overrideEnabled (0),
+ overrideDisabled (1)}
+
+SS-ForBS-Code ::= SEQUENCE {
+ ss-Code SS-Code,
+ basicService BasicServiceCode OPTIONAL,
+ ...,
+ longFTN-Supported [4] NULL OPTIONAL }
+
+GenericServiceInfo ::= SEQUENCE {
+ ss-Status SS-Status,
+ cliRestrictionOption CliRestrictionOption OPTIONAL,
+ ...,
+ maximumEntitledPriority [0] EMLPP-Priority OPTIONAL,
+ defaultPriority [1] EMLPP-Priority OPTIONAL,
+ ccbs-FeatureList [2] CCBS-FeatureList OPTIONAL,
+ nbrSB [3] MaxMC-Bearers OPTIONAL,
+ nbrUser [4] MC-Bearers OPTIONAL,
+ nbrSN [5] MC-Bearers OPTIONAL }
+
+CCBS-FeatureList ::= SEQUENCE SIZE (1..maxNumOfCCBS-Requests) OF
+ CCBS-Feature
+
+maxNumOfCCBS-Requests INTEGER ::= 5
+
+CCBS-Feature ::= SEQUENCE {
+ ccbs-Index [0] CCBS-Index OPTIONAL,
+ b-subscriberNumber [1] ISDN-AddressString OPTIONAL,
+ b-subscriberSubaddress [2] ISDN-SubaddressString OPTIONAL,
+ basicServiceGroup [3] BasicServiceCode OPTIONAL,
+ ...}
+
+CCBS-Index ::= INTEGER (1..maxNumOfCCBS-Requests)
+
+InterrogateSS-Res ::= CHOICE {
+ ss-Status [0] SS-Status,
+ basicServiceGroupList [2] BasicServiceGroupList,
+ forwardingFeatureList [3] ForwardingFeatureList,
+ genericServiceInfo [4] GenericServiceInfo }
+
+USSD-Arg ::= SEQUENCE {
+ ussd-DataCodingScheme USSD-DataCodingScheme,
+ ussd-String USSD-String,
+ ... ,
+ alertingPattern AlertingPattern OPTIONAL,
+ msisdn [0] ISDN-AddressString OPTIONAL }
+
+USSD-Res ::= SEQUENCE {
+ ussd-DataCodingScheme USSD-DataCodingScheme,
+ ussd-String USSD-String,
+ ...}
+
+USSD-DataCodingScheme ::= OCTET STRING (SIZE (1))
+ -- The structure of the USSD-DataCodingScheme is defined by
+ -- the Cell Broadcast Data Coding Scheme as described in
+ -- TS 3GPP TS 23.038 [25]
+
+USSD-String ::= OCTET STRING (SIZE (1..maxUSSD-StringLength))
+ -- The structure of the contents of the USSD-String is dependent
+ -- on the USSD-DataCodingScheme as described in TS 3GPP TS 23.038 [25].
+
+maxUSSD-StringLength INTEGER ::= 160
+
+Password ::= NumericString
+ (FROM ("0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"))
+ (SIZE (4))
+
+GuidanceInfo ::= ENUMERATED {
+ enterPW (0),
+ enterNewPW (1),
+ enterNewPW-Again (2)}
+ -- How this information is really delivered to the subscriber
+ -- (display, announcement, ...) is not part of this
+ -- specification.
+
+SS-List ::= SEQUENCE SIZE (1..maxNumOfSS) OF
+ SS-Code
+
+maxNumOfSS INTEGER ::= 30
+
+SS-InfoList ::= SEQUENCE SIZE (1..maxNumOfSS) OF
+ SS-Info
+
+BasicServiceGroupList ::= SEQUENCE SIZE (1..maxNumOfBasicServiceGroups) OF
+ BasicServiceCode
+
+maxNumOfBasicServiceGroups INTEGER ::= 13
+
+SS-InvocationNotificationArg ::= SEQUENCE {
+ imsi [0] IMSI,
+ msisdn [1] ISDN-AddressString,
+ ss-Event [2] SS-Code,
+ -- The following SS-Code values are allowed :
+ -- ect SS-Code ::= '00110001'B
+ -- multiPTY SS-Code ::= '01010001'B
+ -- cd SS-Code ::= '00100100'B
+ -- ccbs SS-Code ::= '01000100'B
+ ss-EventSpecification [3] SS-EventSpecification OPTIONAL,
+ extensionContainer [4] ExtensionContainer OPTIONAL,
+ ...,
+ b-subscriberNumber [5] ISDN-AddressString OPTIONAL,
+ ccbs-RequestState [6] CCBS-RequestState OPTIONAL
+ }
+
+CCBS-RequestState ::= ENUMERATED {
+ request (0),
+ recall (1),
+ active (2),
+ completed (3),
+ suspended (4),
+ frozen (5),
+ deleted (6)
+ }
+
+SS-InvocationNotificationRes ::= SEQUENCE {
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...
+ }
+
+SS-EventSpecification ::= SEQUENCE SIZE (1..maxEventSpecification) OF
+ AddressString
+
+maxEventSpecification INTEGER ::= 2
+
+RegisterCC-EntryArg ::= SEQUENCE {
+ ss-Code [0] SS-Code,
+ ccbs-Data [1] CCBS-Data OPTIONAL,
+ ...}
+
+CCBS-Data ::= SEQUENCE {
+ ccbs-Feature [0] CCBS-Feature,
+ translatedB-Number [1] ISDN-AddressString,
+ serviceIndicator [2] ServiceIndicator OPTIONAL,
+ callInfo [3] ExternalSignalInfo,
+ networkSignalInfo [4] ExternalSignalInfo,
+ ...}
+
+ServiceIndicator ::= BIT STRING {
+ clir-invoked (0),
+ camel-invoked (1)} (SIZE(2..32))
+ -- exception handling:
+ -- bits 2 to 31 shall be ignored if received and not understood
+
+RegisterCC-EntryRes ::= SEQUENCE {
+ ccbs-Feature [0] CCBS-Feature OPTIONAL,
+ ...}
+
+EraseCC-EntryArg ::= SEQUENCE {
+ ss-Code [0] SS-Code,
+ ccbs-Index [1] CCBS-Index OPTIONAL,
+ ...}
+
+EraseCC-EntryRes ::= SEQUENCE {
+ ss-Code [0] SS-Code,
+ ss-Status [1] SS-Status OPTIONAL,
+ ...}
+
+END
+
diff --git a/rrlp-ephemeris/asn1/MAP-TS-Code.asn b/rrlp-ephemeris/asn1/MAP-TS-Code.asn
new file mode 100644
index 000000000..5ac00bff2
--- /dev/null
+++ b/rrlp-ephemeris/asn1/MAP-TS-Code.asn
@@ -0,0 +1,92 @@
+-- $Id: MAP-TS-Code.asn 28149 2009-04-25 17:45:34Z etxrab $
+-- 3GPP TS 29.002 V8.9.0 (2009-04)
+-- 17.7.9 Teleservice Codes
+
+MAP-TS-Code {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-TS-Code (19) version11 (11)}
+
+DEFINITIONS
+
+::=
+
+BEGIN
+
+TeleserviceCode ::= OCTET STRING (SIZE (1))
+ -- This type is used to represent the code identifying a single
+ -- teleservice, a group of teleservices, or all teleservices. The
+ -- services are defined in TS GSM 22.003 [4].
+ -- The internal structure is defined as follows:
+
+ -- bits 87654321: group (bits 8765) and specific service
+ -- (bits 4321)
+
+Ext-TeleserviceCode ::= OCTET STRING (SIZE (1..5))
+ -- This type is used to represent the code identifying a single
+ -- teleservice, a group of teleservices, or all teleservices. The
+ -- services are defined in TS GSM 22.003 [4].
+ -- The internal structure is defined as follows:
+
+ -- OCTET 1:
+ -- bits 87654321: group (bits 8765) and specific service
+ -- (bits 4321)
+
+ -- OCTETS 2-5: reserved for future use. If received the
+ -- Ext-TeleserviceCode shall be
+ -- treated according to the exception handling defined for the
+ -- operation that uses this type.
+
+ -- Ext-TeleserviceCode includes all values defined for TeleserviceCode.
+
+allTeleservices TeleserviceCode ::= '00000000'B
+
+allSpeechTransmissionServices TeleserviceCode ::= '00010000'B
+telephony TeleserviceCode ::= '00010001'B
+emergencyCalls TeleserviceCode ::= '00010010'B
+
+allShortMessageServices TeleserviceCode ::= '00100000'B
+shortMessageMT-PP TeleserviceCode ::= '00100001'B
+shortMessageMO-PP TeleserviceCode ::= '00100010'B
+
+allFacsimileTransmissionServices TeleserviceCode ::= '01100000'B
+facsimileGroup3AndAlterSpeech TeleserviceCode ::= '01100001'B
+automaticFacsimileGroup3 TeleserviceCode ::= '01100010'B
+facsimileGroup4 TeleserviceCode ::= '01100011'B
+
+-- The following non-hierarchical Compound Teleservice Groups
+-- are defined in TS 3GPP TS 22.030:
+allDataTeleservices TeleserviceCode ::= '01110000'B
+ -- covers Teleservice Groups 'allFacsimileTransmissionServices'
+ -- and 'allShortMessageServices'
+allTeleservices-ExeptSMS TeleserviceCode ::= '10000000'B
+ -- covers Teleservice Groups 'allSpeechTransmissionServices' and
+ -- 'allFacsimileTransmissionServices'
+--
+-- Compound Teleservice Group Codes are only used in call
+-- independent supplementary service operations, i.e. they
+-- are not used in InsertSubscriberData or in
+-- DeleteSubscriberData messages.
+
+allVoiceGroupCallServices TeleserviceCode ::= '10010000'B
+voiceGroupCall TeleserviceCode ::= '10010001'B
+voiceBroadcastCall TeleserviceCode ::= '10010010'B
+
+allPLMN-specificTS TeleserviceCode ::= '11010000'B
+plmn-specificTS-1 TeleserviceCode ::= '11010001'B
+plmn-specificTS-2 TeleserviceCode ::= '11010010'B
+plmn-specificTS-3 TeleserviceCode ::= '11010011'B
+plmn-specificTS-4 TeleserviceCode ::= '11010100'B
+plmn-specificTS-5 TeleserviceCode ::= '11010101'B
+plmn-specificTS-6 TeleserviceCode ::= '11010110'B
+plmn-specificTS-7 TeleserviceCode ::= '11010111'B
+plmn-specificTS-8 TeleserviceCode ::= '11011000'B
+plmn-specificTS-9 TeleserviceCode ::= '11011001'B
+plmn-specificTS-A TeleserviceCode ::= '11011010'B
+plmn-specificTS-B TeleserviceCode ::= '11011011'B
+plmn-specificTS-C TeleserviceCode ::= '11011100'B
+plmn-specificTS-D TeleserviceCode ::= '11011101'B
+plmn-specificTS-E TeleserviceCode ::= '11011110'B
+plmn-specificTS-F TeleserviceCode ::= '11011111'B
+
+END
+
diff --git a/rrlp-ephemeris/asn1/RRLP-Components.asn b/rrlp-ephemeris/asn1/RRLP-Components.asn
new file mode 100644
index 000000000..3bade6a6a
--- /dev/null
+++ b/rrlp-ephemeris/asn1/RRLP-Components.asn
@@ -0,0 +1,1488 @@
+-- RRLP-Components.asn
+-- $Id$
+-- Taken from 3GPP TS 44.031 V7.4.0 (2007-03)
+-- http://www.3gpp.org/ftp/Specs/archive/44_series/44.031/44031-740.zip/44031-740.doc
+--
+-- 4 Components
+-- 5 Elements of Components
+--
+
+RRLP-Components
+-- { RRLP-Components }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+IMPORTS
+ Ext-GeographicalInformation, VelocityEstimate
+FROM
+ MAP-LCS-DataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-LCS-DataTypes (25) version11 (11)}
+
+ ExtensionContainer
+FROM MAP-ExtensionDataTypes {
+ itu-t identified-organization (4) etsi (0) mobileDomain (0)
+ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+;
+
+
+-- Add here other ASN.1 definitions presented below
+-- in chapters 4 and 5.
+
+-- Measurement Position request component
+MsrPosition-Req ::= SEQUENCE {
+ positionInstruct PositionInstruct,
+ referenceAssistData ReferenceAssistData OPTIONAL,
+ msrAssistData MsrAssistData OPTIONAL,
+ systemInfoAssistData SystemInfoAssistData OPTIONAL,
+ gps-AssistData GPS-AssistData OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ -- Release 98 extension element
+rel98-MsrPosition-Req-extension Rel98-MsrPosition-Req-Extension OPTIONAL,
+ -- Release 5 extension element
+rel5-MsrPosition-Req-extension Rel5-MsrPosition-Req-Extension OPTIONAL,
+ -- Release 7 extension element
+rel7-MsrPosition-Req-extension Rel7-MsrPosition-Req-Extension OPTIONAL
+}
+
+-- Measurement Position response component
+MsrPosition-Rsp ::= SEQUENCE {
+ multipleSets MultipleSets OPTIONAL,
+ referenceIdentity ReferenceIdentity OPTIONAL,
+ otd-MeasureInfo OTD-MeasureInfo OPTIONAL,
+ locationInfo LocationInfo OPTIONAL,
+ gps-MeasureInfo GPS-MeasureInfo OPTIONAL,
+ locationError LocationError OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ -- Release extension here
+ rel-98-MsrPosition-Rsp-Extension
+ Rel-98-MsrPosition-Rsp-Extension OPTIONAL,
+ rel-5-MsrPosition-Rsp-Extension
+ Rel-5-MsrPosition-Rsp-Extension OPTIONAL,
+ -- rel-5-MsrPosition-Rsp-Extension and other possible future extensions
+ -- are the only information elements that may be included in the 2nd
+ -- MsrPosition-Rsp component when RRLP pseudo-segmentation is used
+ rel-7-MsrPosition-Rsp-Extension
+ Rel-7-MsrPosition-Rsp-Extension OPTIONAL
+}
+
+-- Assistance Data component
+AssistanceData ::= SEQUENCE {
+ referenceAssistData ReferenceAssistData OPTIONAL,
+ msrAssistData MsrAssistData OPTIONAL,
+ systemInfoAssistData SystemInfoAssistData OPTIONAL,
+ gps-AssistData GPS-AssistData OPTIONAL,
+ moreAssDataToBeSent MoreAssDataToBeSent OPTIONAL, -- If not present, interpret as only
+ -- Assistance Data component used to
+ -- deliver entire set of assistance
+ -- data.
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ -- Release extension here
+ rel98-AssistanceData-Extension Rel98-AssistanceData-Extension OPTIONAL,
+ rel5-AssistanceData-Extension Rel5-AssistanceData-Extension OPTIONAL,
+ rel7-AssistanceData-Extension Rel7-AssistanceData-Extension OPTIONAL
+}
+
+-- Protocol Error component
+ProtocolError ::= SEQUENCE {
+ errorCause ErrorCodes,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ -- Release extensions here
+ rel-5-ProtocolError-Extension Rel-5-ProtocolError-Extension OPTIONAL
+}
+
+-- Position instructions
+PositionInstruct ::= SEQUENCE {
+ -- Method type
+ methodType MethodType,
+ positionMethod PositionMethod,
+ measureResponseTime MeasureResponseTime,
+ useMultipleSets UseMultipleSets,
+ environmentCharacter EnvironmentCharacter OPTIONAL
+}
+
+--
+MethodType ::= CHOICE {
+ msAssisted AccuracyOpt, -- accuracy is optional
+ msBased Accuracy, -- accuracy is mandatory
+ msBasedPref Accuracy, -- accuracy is mandatory
+ msAssistedPref Accuracy -- accuracy is mandatory
+}
+
+-- Accuracy of the location estimation
+AccuracyOpt ::= SEQUENCE {
+ accuracy Accuracy OPTIONAL
+}
+
+-- The values of this field are defined in 3GPP TS 23.032 (Uncertainty code)
+Accuracy ::= INTEGER (0..127)
+
+
+-- Position Method
+PositionMethod ::= ENUMERATED {
+ eotd (0),
+ gps (1),
+ gpsOrEOTD (2)
+}
+
+-- Measurement request response time
+MeasureResponseTime ::= INTEGER (0..7)
+
+-- useMultiple Sets, FFS!
+UseMultipleSets ::= ENUMERATED {
+ multipleSets (0), -- multiple sets are allowed
+ oneSet (1) -- sending of multiple is not allowed
+}
+
+-- Environment characterization
+EnvironmentCharacter ::= ENUMERATED {
+ badArea (0), -- bad urban or suburban, heavy multipath and NLOS
+ notBadArea (1), -- light multipath and NLOS
+ mixedArea (2), -- not defined or mixed environment
+ ...
+}
+
+-- E-OTD reference BTS for Assitance data IE
+ReferenceAssistData ::= SEQUENCE {
+ bcchCarrier BCCHCarrier, -- BCCH carrier
+ bsic BSIC, -- BSIC
+ timeSlotScheme TimeSlotScheme, -- Timeslot scheme
+ btsPosition BTSPosition OPTIONAL
+}
+
+-- ellipsoid point and
+-- ellipsoid point with altitude and uncertainty ellipsoid shapes are supported
+BTSPosition ::= Ext-GeographicalInformation
+
+-- RF channel number of BCCH
+BCCHCarrier ::= INTEGER (0..1023)
+
+-- Base station Identity Code
+BSIC ::= INTEGER (0..63)
+
+-- Timeslot scheme
+TimeSlotScheme ::= ENUMERATED {
+ equalLength (0),
+ variousLength (1)
+}
+
+-- Time slot (modulo)
+ModuloTimeSlot ::= INTEGER (0..3)
+
+-- E-OTD measurement assistance data IE
+-- The total number of neighbors in this element (MsrAssistData)
+-- and in SystemInfoAssistData element (presented neighbors
+-- can be at a maximum 15!)
+MsrAssistData ::= SEQUENCE {
+ msrAssistList SeqOfMsrAssistBTS
+}
+SeqOfMsrAssistBTS ::= SEQUENCE (SIZE(1..15)) OF MsrAssistBTS
+
+MsrAssistBTS ::= SEQUENCE {
+ bcchCarrier BCCHCarrier, -- BCCH carrier
+ bsic BSIC, -- BSIC
+ multiFrameOffset MultiFrameOffset, -- multiframe offset
+ timeSlotScheme TimeSlotScheme, -- Timeslot scheme
+ roughRTD RoughRTD, -- rough RTD value
+
+ -- Location Calculation Assistance data is moved here
+ calcAssistanceBTS CalcAssistanceBTS OPTIONAL
+}
+
+-- Multiframe offset
+MultiFrameOffset ::= INTEGER (0..51)
+-- The Multiframe Offset value 51 shall not be encoded by the transmitting entity and
+-- shall be treated by the receiving entity as 0.
+
+-- Rough RTD value between one base station and reference BTS
+RoughRTD ::= INTEGER (0..1250)
+-- The RoughRTD value 1250 shall not be encoded by the transmitting entity and shall
+-- be treated by the receiving entity as 0.
+
+-- E-OTD Measurement assistance data for system information List IE
+-- The total number of base stations in this element (SystemInfoAssistData
+-- presented neighbors) and in MsrAssistData element can be at a maximum 15.
+SystemInfoAssistData ::= SEQUENCE {
+ systemInfoAssistList SeqOfSystemInfoAssistBTS
+}
+SeqOfSystemInfoAssistBTS::= SEQUENCE (SIZE(1..32)) OF SystemInfoAssistBTS
+
+-- whether n.th is present or not ?
+SystemInfoAssistBTS ::= CHOICE {
+ notPresent NULL,
+ present AssistBTSData
+}
+
+-- Actual assistance data for system information base station
+AssistBTSData ::= SEQUENCE {
+ bsic BSIC, -- BSIC
+ multiFrameOffset MultiFrameOffset, -- multiframe offset
+ timeSlotScheme TimeSlotScheme, -- Timeslot scheme
+ roughRTD RoughRTD, -- rough RTD value
+
+ -- Location Calculation Assistance data
+ calcAssistanceBTS CalcAssistanceBTS OPTIONAL
+}
+
+-- E-OTD Location calculation assistance data,
+-- CalcAssistanceBTS element is optional not subfields
+CalcAssistanceBTS ::= SEQUENCE {
+ fineRTD FineRTD, -- fine RTD value between base stations
+ referenceWGS84 ReferenceWGS84 -- reference coordinates
+}
+
+-- Coordinates of neighbour BTS, WGS-84 ellipsoid
+ReferenceWGS84 ::= SEQUENCE {
+ relativeNorth RelDistance, -- relative distance (south negative)
+ relativeEast RelDistance, -- relative distance (west negative)
+ -- Relative Altitude is not always known
+ relativeAlt RelativeAlt OPTIONAL -- relative altitude
+}
+
+-- Fine RTD value between this BTS and the reference BTS
+FineRTD ::= INTEGER (0..255)
+
+-- Relative north/east distance
+RelDistance ::= INTEGER (-200000..200000)
+
+-- Relative altitude
+RelativeAlt ::= INTEGER (-4000..4000)
+
+-- Measure position response IEs
+-- Reference Identity
+-- Multiple sets
+MultipleSets ::= SEQUENCE {
+ -- number of reference sets
+ nbrOfSets INTEGER (2..3),
+
+ -- This field actually tells the number of reference BTSs
+ nbrOfReferenceBTSs INTEGER (1..3),
+
+ -- This field is conditional and included optionally only if
+ -- nbrOfSets is 3 and number of reference BTSs is 2.
+ referenceRelation ReferenceRelation OPTIONAL
+}
+
+-- Relation between refence BTSs and sets
+ReferenceRelation ::= ENUMERATED {
+ secondBTSThirdSet (0), -- 1st BTS related to 1st and 2nd sets
+ secondBTSSecondSet (1), -- 1st BTS related to 1st and 3rd sets
+ firstBTSFirstSet (2) -- 1st BTS related to 1st set
+}
+
+-- Reference BTS Identity, this element contains number of
+-- BTSs told nbrOfReferenceBTSs field in Multiple sets element)
+ReferenceIdentity ::= SEQUENCE {
+ -- Reference BTS list
+ refBTSList SeqOfReferenceIdentityType
+}
+SeqOfReferenceIdentityType ::= SEQUENCE (SIZE(1..3)) OF ReferenceIdentityType
+
+-- Cell identity
+ReferenceIdentityType ::= CHOICE {
+ bsicAndCarrier BSICAndCarrier, -- BSIC and Carrier
+ ci CellID, -- Cell ID, LAC not needed
+ requestIndex RequestIndex, -- Index to Requested Neighbor List
+ systemInfoIndex SystemInfoIndex, -- Index to System info list, this type of ref. identity
+ -- shall not be used by the MS unless it has received
+ -- the SystemInfoAssistData from the SMLC for this cell.
+ ciAndLAC CellIDAndLAC -- CI and LAC
+}
+
+BSICAndCarrier ::= SEQUENCE {
+ carrier BCCHCarrier,
+ bsic BSIC
+}
+
+RequestIndex ::= INTEGER (1..16)
+
+SystemInfoIndex ::= INTEGER (1..32)
+
+CellIDAndLAC ::= SEQUENCE {
+ referenceLAC LACID, -- Location area code
+ referenceCI CellID -- Cell identity
+}
+CellID ::= INTEGER (0..65535)
+LACID ::= INTEGER (0..65535)
+
+-- OTD-MeasureInfo
+OTD-MeasureInfo ::= SEQUENCE {
+ -- Measurement info elements, OTD-MsrElement is repeated number of times
+ -- told in nbrOfReferenceBTSs in MultipleSets, default value is 1
+ otdMsrFirstSets OTD-MsrElementFirst,
+
+ -- if more than one sets are present this element is repeated
+ -- NumberOfSets - 1 (-1 = first set)
+ otdMsrRestSets SeqOfOTD-MsrElementRest OPTIONAL
+}
+
+SeqOfOTD-MsrElementRest ::= SEQUENCE (SIZE(1..2)) OF OTD-MsrElementRest
+
+-- OTD measurent information for 1 set
+OTD-MsrElementFirst ::= SEQUENCE {
+ refFrameNumber INTEGER (0..42431), -- Frame number modulo 42432
+ referenceTimeSlot ModuloTimeSlot,
+ toaMeasurementsOfRef TOA-MeasurementsOfRef OPTIONAL,
+ stdResolution StdResolution,
+ taCorrection INTEGER (0..960) OPTIONAL, -- TA correction
+
+ -- measured neighbors in OTD measurements
+ otd-FirstSetMsrs SeqOfOTD-FirstSetMsrs OPTIONAL
+}
+SeqOfOTD-FirstSetMsrs ::= SEQUENCE (SIZE(1..10)) OF OTD-FirstSetMsrs
+
+-- OTD measurent information 2 and 3 sets if exist
+OTD-MsrElementRest ::= SEQUENCE {
+ refFrameNumber INTEGER (0..42431), -- Frame number modulo 42432
+ referenceTimeSlot ModuloTimeSlot,
+ toaMeasurementsOfRef TOA-MeasurementsOfRef OPTIONAL,
+ stdResolution StdResolution,
+ taCorrection INTEGER (0..960) OPTIONAL, -- TA correction
+
+ -- measured neighbors in OTD measurements
+ otd-MsrsOfOtherSets SeqOfOTD-MsrsOfOtherSets OPTIONAL
+}
+SeqOfOTD-MsrsOfOtherSets ::= SEQUENCE (SIZE(1..10)) OF OTD-MsrsOfOtherSets
+
+-- Standard deviation of the TOA measurements from the reference BTS
+TOA-MeasurementsOfRef ::= SEQUENCE {
+ refQuality RefQuality,
+ numOfMeasurements NumOfMeasurements
+}
+
+RefQuality ::= INTEGER (0..31) -- St Dev of TOA of reference as defined in annex
+NumOfMeasurements ::= INTEGER (0..7) -- No. of measurements for RefQuality as defined in annex
+StdResolution ::= INTEGER (0..3) -- Values of resolution are defined in annex
+
+OTD-FirstSetMsrs ::= OTD-MeasurementWithID
+
+-- Neighbour info in OTD measurements 0-10 times in TD measurement info
+OTD-MsrsOfOtherSets ::= CHOICE {
+ identityNotPresent OTD-Measurement,
+ identityPresent OTD-MeasurementWithID
+}
+
+-- For this OTD measurement identity is same as the identity of BTS
+-- in the first set with same sequence number
+OTD-Measurement ::= SEQUENCE {
+ nborTimeSlot ModuloTimeSlot,
+ eotdQuality EOTDQuality,
+ otdValue OTDValue
+}
+
+-- This measurement contains the BTS identity and measurement
+OTD-MeasurementWithID ::=SEQUENCE {
+ neighborIdentity NeighborIdentity,
+ nborTimeSlot ModuloTimeSlot,
+ eotdQuality EOTDQuality,
+ otdValue OTDValue
+}
+
+EOTDQuality ::= SEQUENCE {
+ nbrOfMeasurements INTEGER (0..7),
+ stdOfEOTD INTEGER (0..31)
+}
+
+NeighborIdentity ::= CHOICE {
+ bsicAndCarrier BSICAndCarrier, -- BSIC and Carrier
+ ci CellID, -- Cell ID, LAC not needed
+ multiFrameCarrier MultiFrameCarrier, -- MultiFrameOffest and BSIC
+ requestIndex RequestIndex, -- Index to Requested Neighbor List
+ systemInfoIndex SystemInfoIndex, -- Index to System info list, this type of neighbour
+ -- identity shall not be used by the MS unless it has
+ -- received the SystemInfoAssistData from the SMLC for
+ -- this cell.
+ ciAndLAC CellIDAndLAC -- CI and LAC
+}
+
+-- Multiframe and carrier
+MultiFrameCarrier ::= SEQUENCE {
+ bcchCarrier BCCHCarrier,
+ multiFrameOffset MultiFrameOffset
+}
+
+-- OTD measurement value for neighbour
+OTDValue ::= INTEGER (0..39999)
+
+-- Location information IE
+LocationInfo ::= SEQUENCE {
+ refFrame INTEGER (0..65535), -- Reference Frame number
+ -- If refFrame is within (42432..65535), it shall be ignored by the receiver
+ -- in that case the MS should provide GPS TOW if available
+ gpsTOW INTEGER (0..14399999) OPTIONAL, -- GPS TOW
+ fixType FixType,
+ -- Note that applicable range for refFrame is 0 - 42431
+ -- Possible shapes carried in posEstimate are
+ -- ellipsoid point,
+ -- ellipsoid point with uncertainty circle
+ -- ellipsoid point with uncertainty ellipse
+ -- ellipsoid point with altitude and uncertainty ellipsoid
+ posEstimate Ext-GeographicalInformation
+}
+
+FixType ::= INTEGER {
+ twoDFix (0),
+ threeDFix (1)
+} (0..1)
+
+-- GPS-Measurement information
+GPS-MeasureInfo ::= SEQUENCE {
+ -- Measurement info elements
+ -- user has to make sure that in this element is number of elements
+ -- defined in reference BTS identity
+ gpsMsrSetList SeqOfGPS-MsrSetElement
+}
+SeqOfGPS-MsrSetElement ::= SEQUENCE (SIZE(1..3)) OF GPS-MsrSetElement
+
+-- OTD measurent information 1-3 times in message
+GPS-MsrSetElement ::= SEQUENCE {
+ refFrame INTEGER (0..65535) OPTIONAL, -- Reference Frame number
+ gpsTOW GPSTOW24b, -- GPS TOW
+ -- Note that applicable range for refFrame is 0 - 42431
+
+--N_SAT can be read from number of elements of gps-msrList
+
+ gps-msrList SeqOfGPS-MsrElement
+}
+
+-- 24 bit presentation for GPSTOW
+GPSTOW24b ::= INTEGER (0..14399999)
+
+-- measured elements in measurement parameters field
+SeqOfGPS-MsrElement ::= SEQUENCE (SIZE(1..16)) OF GPS-MsrElement
+
+GPS-MsrElement ::= SEQUENCE {
+ satelliteID SatelliteID, -- Satellite identifier
+ cNo INTEGER (0..63), -- carrier noise ratio
+ doppler INTEGER (-32768..32767), -- doppler, mulltiply by 0.2
+ wholeChips INTEGER (0..1022), -- whole value of the code phase measurement
+ fracChips INTEGER (0..1024), -- fractional value of the code phase measurement
+ -- a value of 1024 shall not be encoded by the sender
+ -- the receiver shall consider a value of 1024 to be
+ -- invalid data
+ mpathIndic MpathIndic, -- multipath indicator
+ pseuRangeRMSErr INTEGER (0..63) -- index
+}
+
+-- Multipath indicator
+MpathIndic ::= ENUMERATED {
+ notMeasured (0),
+ low (1),
+ medium (2),
+ high (3)
+}
+
+-- Location error IE
+LocationError ::= SEQUENCE {
+ locErrorReason LocErrorReason,
+ additionalAssistanceData AdditionalAssistanceData OPTIONAL,
+ ...
+}
+
+LocErrorReason ::= ENUMERATED {
+ unDefined (0),
+ notEnoughBTSs (1),
+ notEnoughSats (2),
+ eotdLocCalAssDataMissing (3),
+ eotdAssDataMissing (4),
+ gpsLocCalAssDataMissing (5),
+ gpsAssDataMissing (6),
+ methodNotSupported (7),
+ notProcessed (8),
+ refBTSForGPSNotServingBTS (9),
+ refBTSForEOTDNotServingBTS (10),
+ ...,
+ notEnoughGANSSSats (11),
+ ganssAssDataMissing (12),
+ refBTSForGANSSNotServingBTS (13)
+}
+
+-- exception handling:
+-- an unrecognized value shall be treated the same as value 0
+
+
+-- defines additional assistance data needed for any new location attempt
+-- MS shall retain any assistance data already received
+AdditionalAssistanceData ::= SEQUENCE {
+ gpsAssistanceData GPSAssistanceData OPTIONAL,
+ extensionContainer ExtensionContainer OPTIONAL,
+ ...,
+ ganssAssistanceData GANSSAssistanceData OPTIONAL
+}
+
+GPSAssistanceData ::= OCTET STRING (SIZE (1..maxGPSAssistanceData))
+-- GPSAssistanceData has identical structure and encoding to octets 3 to n of the
+-- GPS Assistance Data IE in 3GPP TS 49.031
+
+maxGPSAssistanceData INTEGER ::= 40
+
+GANSSAssistanceData ::= OCTET STRING (SIZE (1..maxGANSSAssistanceData))
+-- GANSSAssistanceData has identical structure and encoding to octets 3 to n of the
+-- GANSS Assistance Data IE in 3GPP TS 49.031
+
+maxGANSSAssistanceData INTEGER ::= 40
+
+
+-- Protocol Error Causes
+ErrorCodes ::= ENUMERATED {
+ unDefined (0),
+missingComponet (1),
+incorrectData (2),
+missingIEorComponentElement (3),
+messageTooShort (4),
+unknowReferenceNumber (5),
+...
+}
+
+-- exception handling:
+-- an unrecognized value shall be treated the same as value 0
+
+-- GPS assistance data IE
+GPS-AssistData ::= SEQUENCE {
+ controlHeader ControlHeader
+}
+
+-- More Assistance Data To Be Sent IE
+-- More Assistance Data Components On the Way indication for delivery of an entire set of assistance
+-- data in multiple Assistance Data components.
+
+MoreAssDataToBeSent ::= ENUMERATED {
+ noMoreMessages (0), -- This is the only or last Assistance Data message used to deliver
+ -- the entire set of assistance data.
+ moreMessagesOnTheWay (1) -- The SMLC will send more Assistance Data messages or a final RRLP
+ -- Measure Position Request message to deliver the
+ -- the entire set of assistance data.
+}
+
+-- Control header of the GPS assistance data
+ControlHeader ::= SEQUENCE {
+
+ -- Field type Present information
+ referenceTime ReferenceTime OPTIONAL,
+ refLocation RefLocation OPTIONAL,
+ dgpsCorrections DGPSCorrections OPTIONAL,
+ navigationModel NavigationModel OPTIONAL,
+ ionosphericModel IonosphericModel OPTIONAL,
+ utcModel UTCModel OPTIONAL,
+ almanac Almanac OPTIONAL,
+ acquisAssist AcquisAssist OPTIONAL,
+ realTimeIntegrity SeqOf-BadSatelliteSet OPTIONAL
+}
+
+ReferenceTime ::= SEQUENCE {
+ gpsTime GPSTime,
+ gsmTime GSMTime OPTIONAL,
+ gpsTowAssist GPSTOWAssist OPTIONAL
+}
+
+-- GPS Time includes week number and time-of-week (TOW)
+GPSTime ::= SEQUENCE {
+ gpsTOW23b GPSTOW23b,
+ gpsWeek GPSWeek
+}
+
+-- GPSTOW, range 0-604799.92, resolution 0.08 sec, 23-bit presentation
+GPSTOW23b ::= INTEGER (0..7559999)
+
+-- GPS week number
+GPSWeek ::= INTEGER (0..1023)
+
+-- GPSTOWAssist consists of TLM message, Anti-spoof flag, Alert flag, and 2 reserved bits in TLM Word
+-- for each visible satellite.
+-- N_SAT can be read from number of elements in GPSTOWAssist
+GPSTOWAssist ::= SEQUENCE (SIZE(1..12)) OF GPSTOWAssistElement
+
+GPSTOWAssistElement ::= SEQUENCE {
+ satelliteID SatelliteID,
+ tlmWord TLMWord,
+ antiSpoof AntiSpoofFlag,
+ alert AlertFlag,
+ tlmRsvdBits TLMReservedBits
+}
+
+-- TLM Word, 14 bits
+TLMWord ::= INTEGER (0..16383)
+
+-- Anti-Spoof flag
+AntiSpoofFlag ::= INTEGER (0..1)
+
+-- Alert flag
+AlertFlag ::= INTEGER (0..1)
+
+-- Reserved bits in TLM word, MSB occurs earlier in TLM Word transmitted by satellite
+TLMReservedBits ::= INTEGER (0..3)
+
+GSMTime ::= SEQUENCE {
+ bcchCarrier BCCHCarrier, -- BCCH carrier
+ bsic BSIC, -- BSIC
+ frameNumber FrameNumber,
+ timeSlot TimeSlot,
+ bitNumber BitNumber
+}
+
+-- Frame number
+FrameNumber ::= INTEGER (0..2097151)
+
+-- Time slot number
+TimeSlot ::= INTEGER (0..7)
+
+-- Bit number
+BitNumber ::= INTEGER (0..156)
+
+
+-- Reference Location IE
+RefLocation ::= SEQUENCE {
+ threeDLocation Ext-GeographicalInformation
+}
+
+-- DGPS Corrections IE
+DGPSCorrections ::= SEQUENCE {
+
+ gpsTOW INTEGER (0..604799), -- DGPS reference time
+ status INTEGER (0..7),
+ -- N_SAT can be read from number of elements of satList
+ satList SeqOfSatElement
+}
+SeqOfSatElement ::= SEQUENCE (SIZE (1..16)) OF SatElement
+
+-- number of correction for satellites
+SatElement ::= SEQUENCE {
+ satelliteID SatelliteID,
+
+
+--- Sequence number for ephemeris
+ iode INTEGER (0..239),
+ -- User Differential Range Error
+ udre INTEGER (0..3),
+
+ -- Pseudo Range Correction, range is
+ -- -655.04 - +655.04,
+ pseudoRangeCor INTEGER (-2047..2047),
+
+ -- Pseudo Range Rate Correction, range is
+ -- -4.064 - +4.064,
+ rangeRateCor INTEGER (-127..127),
+
+-- Delta Pseudo Range Correction 2
+ deltaPseudoRangeCor2 INTEGER (-127..127), -- This IE shall be ignored by the receiver and
+ -- set to zero by the sender
+ -- Delta Pseudo Range Correction 2
+ deltaRangeRateCor2 INTEGER (-7..7), -- This IE shall be ignored by the receiver and
+ -- set to zero by the sender
+ -- Delta Pseudo Range Correction 3
+ deltaPseudoRangeCor3 INTEGER (-127..127), -- This IE shall be ignored by the receiver and
+ -- set to zero by the sender
+ -- Delta Pseudo Range Correction 3
+ deltaRangeRateCor3 INTEGER (-7..7) -- This IE shall be ignored by the receiver and
+ -- set to zero by the sender
+}
+
+SatelliteID ::= INTEGER (0..63) -- identifies satellite
+
+-- Navigation Model IE
+NavigationModel ::= SEQUENCE {
+ navModelList SeqOfNavModelElement
+}
+
+-- navigation model satellite list
+SeqOfNavModelElement ::= SEQUENCE (SIZE(1..16)) OF NavModelElement
+
+NavModelElement ::= SEQUENCE {
+ satelliteID SatelliteID,
+ satStatus SatStatus -- satellite status
+}
+
+-- the Status of the navigation model
+SatStatus ::= CHOICE {
+ -- New satellite, new Navigation Model
+ newSatelliteAndModelUC UncompressedEphemeris,
+
+ -- Existing satellite, Existing Navigation Model
+ oldSatelliteAndModel NULL,
+
+ -- Existing satellite, new Navigation Model
+ newNaviModelUC UncompressedEphemeris,
+ ...
+}
+
+-- Uncompressed satellite emhemeris and clock corrections
+UncompressedEphemeris ::= SEQUENCE {
+ ephemCodeOnL2 INTEGER (0..3),
+ ephemURA INTEGER (0..15),
+ ephemSVhealth INTEGER (0..63),
+ ephemIODC INTEGER (0..1023),
+ ephemL2Pflag INTEGER (0..1),
+ ephemSF1Rsvd EphemerisSubframe1Reserved,
+ ephemTgd INTEGER (-128..127),
+ ephemToc INTEGER (0..37799),
+ ephemAF2 INTEGER (-128..127),
+ ephemAF1 INTEGER (-32768..32767),
+ ephemAF0 INTEGER (-2097152..2097151),
+ ephemCrs INTEGER (-32768..32767),
+ ephemDeltaN INTEGER (-32768..32767),
+ ephemM0 INTEGER (-2147483648..2147483647),
+ ephemCuc INTEGER (-32768..32767),
+ ephemE INTEGER (0..4294967295),
+ ephemCus INTEGER (-32768..32767),
+ ephemAPowerHalf INTEGER (0..4294967295),
+ ephemToe INTEGER (0..37799),
+ ephemFitFlag INTEGER (0..1),
+ ephemAODA INTEGER (0..31),
+ ephemCic INTEGER (-32768..32767),
+ ephemOmegaA0 INTEGER (-2147483648..2147483647),
+ ephemCis INTEGER (-32768..32767),
+ ephemI0 INTEGER (-2147483648..2147483647),
+ ephemCrc INTEGER (-32768..32767),
+ ephemW INTEGER (-2147483648..2147483647),
+ ephemOmegaADot INTEGER (-8388608..8388607),
+ ephemIDot INTEGER (-8192..8191)
+}
+
+-- Reserved bits in subframe 1 of navigation message
+EphemerisSubframe1Reserved ::= SEQUENCE {
+ reserved1 INTEGER (0..8388607), -- 23-bit field
+ reserved2 INTEGER (0..16777215), -- 24-bit field
+ reserved3 INTEGER (0..16777215), -- 24-bit field
+ reserved4 INTEGER (0..65535) -- 16-bit field
+}
+
+-- Ionospheric Model IE
+IonosphericModel ::= SEQUENCE {
+ alfa0 INTEGER (-128..127),
+ alfa1 INTEGER (-128..127),
+ alfa2 INTEGER (-128..127),
+ alfa3 INTEGER (-128..127),
+ beta0 INTEGER (-128..127),
+ beta1 INTEGER (-128..127),
+ beta2 INTEGER (-128..127),
+ beta3 INTEGER (-128..127)
+}
+
+-- Universal Time Coordinate Model
+UTCModel ::= SEQUENCE {
+ utcA1 INTEGER (-8388608..8388607),
+ utcA0 INTEGER (-2147483648..2147483647),
+ utcTot INTEGER (0..255),
+ utcWNt INTEGER (0..255),
+ utcDeltaTls INTEGER (-128..127),
+ utcWNlsf INTEGER (0..255),
+ utcDN INTEGER (-128..127),
+ utcDeltaTlsf INTEGER (-128..127)
+}
+
+-- Almanac, Long term model
+-- NOTE: These are parameters are subset of the ephemeris
+-- NOTE: But with reduced resolution and accuracy
+Almanac ::= SEQUENCE {
+ alamanacWNa INTEGER (0..255), -- Once per message
+
+ -- navigation model satellite list.
+ -- The size of almanacList is actually Nums_Sats_Total field
+ almanacList SeqOfAlmanacElement
+}
+SeqOfAlmanacElement ::= SEQUENCE (SIZE(1..64)) OF AlmanacElement
+
+-- Almanac info once per satellite
+AlmanacElement ::= SEQUENCE {
+ satelliteID SatelliteID,
+ almanacE INTEGER (0..65535),
+ alamanacToa INTEGER (0..255),
+ almanacKsii INTEGER (-32768..32767),
+ almanacOmegaDot INTEGER (-32768..32767),
+ almanacSVhealth INTEGER (0..255),
+ almanacAPowerHalf INTEGER (0..16777215),
+ almanacOmega0 INTEGER (-8388608..8388607),
+ almanacW INTEGER (-8388608..8388607),
+ almanacM0 INTEGER (-8388608..8388607),
+ almanacAF0 INTEGER (-1024..1023),
+ almanacAF1 INTEGER (-1024..1023)
+}
+
+-- Acquisition Assistance
+AcquisAssist ::= SEQUENCE {
+
+ -- Number of Satellites can be read from acquistList
+ timeRelation TimeRelation,
+
+ -- Acquisition assistance list
+ -- The size of Number of Satellites is actually Number of Satellites field
+ acquisList SeqOfAcquisElement
+}
+SeqOfAcquisElement ::= SEQUENCE (SIZE(1..16)) OF AcquisElement
+
+-- the relationship between GPS time and air-interface timing
+TimeRelation ::= SEQUENCE {
+ --
+ gpsTOW GPSTOW23b, -- 23b presentation
+ gsmTime GSMTime OPTIONAL
+}
+
+-- data occuring per number of satellites
+AcquisElement ::= SEQUENCE {
+ svid SatelliteID,
+
+ -- Doppler 0th order term,
+ -- -5120.0 - 5117.5 Hz (= -2048 - 2047 with 2.5 Hz resolution)
+ doppler0 INTEGER (-2048..2047),
+ addionalDoppler AddionalDopplerFields OPTIONAL,
+ codePhase INTEGER (0..1022), -- Code Phase
+ intCodePhase INTEGER (0..19), -- Integer Code Phase
+ gpsBitNumber INTEGER (0..3), -- GPS bit number
+ codePhaseSearchWindow INTEGER (0..15), -- Code Phase Search Window
+ addionalAngle AddionalAngleFields OPTIONAL
+}
+
+AddionalDopplerFields ::= SEQUENCE {
+ -- Doppler 1st order term, -1.0 - +0.5 Hz/sec
+ -- (= -42 + (0 to 63) with 1/42 Hz/sec. resolution)
+ doppler1 INTEGER (0..63),
+ dopplerUncertainty INTEGER (0..7)
+ -- a sender shall not encode any DopplerUncertainty value in the range 5 to 7
+ -- a receiver shall ignore any value between 5 and 7.
+}
+
+AddionalAngleFields ::= SEQUENCE {
+ -- azimuth angle, 0 - 348.75 deg (= 0 - 31 with 11.25 deg resolution)
+ azimuth INTEGER (0..31),
+ -- elevation angle, 0 - 78.75 deg (= 0 - 7 with 11.25 deg resolution)
+ elevation INTEGER (0..7)
+}
+
+-- Real-Time Integrity
+-- number of bad satellites can be read from this element
+SeqOf-BadSatelliteSet ::= SEQUENCE (SIZE(1..16)) OF SatelliteID
+
+-- Extension Elements
+
+-- Release 98 Extensions here
+Rel98-MsrPosition-Req-Extension ::= SEQUENCE {
+ rel98-Ext-ExpOTD Rel98-Ext-ExpOTD OPTIONAL, -- ExpectedOTD extension
+ ...,
+ gpsTimeAssistanceMeasurementRequest NULL OPTIONAL,
+ gpsReferenceTimeUncertainty GPSReferenceTimeUncertainty OPTIONAL
+
+-- Further R98 extensions here
+}
+Rel98-AssistanceData-Extension ::= SEQUENCE {
+ rel98-Ext-ExpOTD Rel98-Ext-ExpOTD OPTIONAL, -- ExpectedOTD extension
+ ...,
+ gpsTimeAssistanceMeasurementRequest NULL OPTIONAL,
+ gpsReferenceTimeUncertainty GPSReferenceTimeUncertainty OPTIONAL
+
+-- Further R98 extensions here
+}
+
+-- Release 98 ExpOTD extension
+Rel98-Ext-ExpOTD ::= SEQUENCE {
+-- If MsrAssistBTS is included in message, msrAssistData-R98-ExpOTD shall be included.
+ msrAssistData-R98-ExpOTD MsrAssistData-R98-ExpOTD OPTIONAL,
+
+-- If SystemInfoAssistaData is included in message, systemInfoAssistData-R98-ExpOTD shall be
+-- included.
+ systemInfoAssistData-R98-ExpOTD SystemInfoAssistData-R98-ExpOTD OPTIONAL
+}
+
+-- MsrAssistData R98 extension
+MsrAssistData-R98-ExpOTD ::= SEQUENCE {
+ msrAssistList-R98-ExpOTD SeqOfMsrAssistBTS-R98-ExpOTD
+}
+
+-- Indexes in SeqOfMsrAssistBTS-R98-ExpOTD refer to SeqOfMsrAssistBTS
+-- If the index exceeds the SegOfMsrAssistBTS range or if there is other
+-- inconsistencies between the BTS indices, the MS shall apply protocol
+-- error cause incorrectData
+SeqOfMsrAssistBTS-R98-ExpOTD ::= SEQUENCE (SIZE(1..15)) OF MsrAssistBTS-R98-ExpOTD
+
+-- This element completes MsrAssistBTS IE
+MsrAssistBTS-R98-ExpOTD ::= SEQUENCE {
+ expectedOTD ExpectedOTD,
+ expOTDUncertainty ExpOTDUncertainty
+}
+
+-- SystemInfoAssistData R98 extension
+SystemInfoAssistData-R98-ExpOTD ::= SEQUENCE {
+ systemInfoAssistListR98-ExpOTD SeqOfSystemInfoAssistBTS-R98-ExpOTD
+}
+
+-- SeqOfSystemInfoAssistBTS-R98-ExpOTD index refer to SeqOfSystemInfoAssistBTS
+-- If the index exceeds the SegOfSystemInfoAssistBTS range or if there is other
+-- inconsistencies between the BTS indices, the MS shall apply protocol
+-- error cause incorrectData
+SeqOfSystemInfoAssistBTS-R98-ExpOTD ::= SEQUENCE (SIZE(1..32)) OF SystemInfoAssistBTS-R98-ExpOTD
+
+-- whether n.th is present or not ?
+SystemInfoAssistBTS-R98-ExpOTD ::= CHOICE {
+ notPresent NULL,
+ present AssistBTSData-R98-ExpOTD
+}
+
+-- This element completes AssistBTSData IE
+AssistBTSData-R98-ExpOTD ::= SEQUENCE {
+ expectedOTD ExpectedOTD,
+ expOTDuncertainty ExpOTDUncertainty -- Uncertainty of expected OTD
+}
+
+-- Expected OTD value between nbor base station and reference BTS
+-- at MS's current estimated location.
+ExpectedOTD ::= INTEGER (0..1250)
+-- The ExpectedOTD value 1250 shall not be encoded by the transmitting entity and
+-- shall be treated by the receiving entity as 0.
+-- Uncertainty of Exptected OTD in bits
+ExpOTDUncertainty ::= INTEGER(0..7)
+
+-- Release 98 extensions
+
+GPSReferenceTimeUncertainty ::= INTEGER (0 .. 127) -- Coding according to Annex
+
+GPSTimeAssistanceMeasurements ::= SEQUENCE {
+ referenceFrameMSB INTEGER (0 .. 63), -- MSB of frame number
+ gpsTowSubms INTEGER (0 .. 9999) OPTIONAL, -- in units of 100ns, for MS based AGPS
+ deltaTow INTEGER (0 .. 127) OPTIONAL, -- for MS assisted AGPS
+ gpsReferenceTimeUncertainty GPSReferenceTimeUncertainty OPTIONAL
+}
+
+Rel-98-MsrPosition-Rsp-Extension ::= SEQUENCE {
+
+ -- First extension to Release 98
+ rel-98-Ext-MeasureInfo SEQUENCE {
+ otd-MeasureInfo-R98-Ext OTD-MeasureInfo-R98-Ext OPTIONAL
+ },
+ ...,
+ timeAssistanceMeasurements GPSTimeAssistanceMeasurements OPTIONAL
+ -- Further R98 extensions here
+}
+
+-- This is an addition to OTD-MeasureInfo element defined in original message,
+-- If OTD-MeasureInfo is absent, or if one or more OTD-MsrElementRest are present
+-- OTD-MeasureInfo-R98-Ext shall be absent.
+-- OTD-MeasureInfo-R98-Ext
+OTD-MeasureInfo-R98-Ext ::= SEQUENCE {
+ -- Measurement info elements
+ otdMsrFirstSets-R98-Ext OTD-MsrElementFirst-R98-Ext
+}
+
+-- OTD measurement information Ext for the first set only
+OTD-MsrElementFirst-R98-Ext ::= SEQUENCE {
+ -- additional measured neighbors in OTD measurements
+ otd-FirstSetMsrs-R98-Ext SeqOfOTD-FirstSetMsrs-R98-Ext OPTIONAL
+}
+SeqOfOTD-FirstSetMsrs-R98-Ext ::= SEQUENCE (SIZE(1..5)) OF OTD-FirstSetMsrs
+
+Rel-5-MsrPosition-Rsp-Extension ::= SEQUENCE {
+
+ extended-reference Extended-reference OPTIONAL,
+ -- The extended-reference shall be included by the MS if and only if previously
+ -- received from the SMLC in a Measure Position Request. When included, the value sent
+ -- by the MS shall equal the value received from the SMLC.
+
+ -- extension to Release 5, for RRLP pseudo-segmentation here
+ otd-MeasureInfo-5-Ext OTD-MeasureInfo-5-Ext OPTIONAL,
+ ulPseudoSegInd UlPseudoSegInd OPTIONAL, -- Included when uplink RRLP
+ -- Pseudo-segmentation is used, not included when no uplink pseudo-segmentation is used
+ ...
+ -- Possibly more extensions for Release 5 here later
+}
+
+Extended-reference ::= SEQUENCE {
+ smlc-code INTEGER (0..63),
+ transaction-ID INTEGER (0..262143)
+}
+
+OTD-MeasureInfo-5-Ext ::= SeqOfOTD-MsrElementRest
+ -- if more than one measurement sets are present this element is repeated
+ -- NumberOfSets - 1 (-1 = first set) combined in OTD-MeasureInfo-5-Ext and
+ -- OTD-MeasureInfo (e.g. if NumberOfSets is 3, then one otdMsrRestSets may
+ -- be sent in OTD-MeasureInfo-5-Ext and one in OTD-MeasureInfo)
+
+-- First part of Uplink RRLP Pseudo-segmentation indication, possibly more may be defined
+-- in the future for segmentation with more than two segments.
+UlPseudoSegInd ::= ENUMERATED {
+ firstOfMany (0),
+ secondOfMany(1)
+}
+
+Rel5-MsrPosition-Req-Extension ::= SEQUENCE {
+ extended-reference Extended-reference,
+ ...
+ -- Possibly more extensions for Release 5 here later
+}
+
+Rel5-AssistanceData-Extension ::= SEQUENCE {
+ extended-reference Extended-reference,
+ ...
+
+-- Possibly more extensions for Release 5 here later
+}
+
+Rel-5-ProtocolError-Extension::= SEQUENCE {
+ extended-reference Extended-reference OPTIONAL,
+ -- The extended-reference shall be included by the MS if and only if previously
+ -- received from the SMLC.
+ -- When included, the value sent by the MS shall equal the value received from the SMLC.
+ ...
+
+ -- Possibly more extensions for Release 5 here later
+}
+
+-- Release 7 Extensions here
+
+Rel7-MsrPosition-Req-Extension ::= SEQUENCE {
+velocityRequested NULL OPTIONAL,
+ ganssPositionMethod GANSSPositioningMethod OPTIONAL,
+ ganss-AssistData GANSS-AssistData OPTIONAL,
+ ganssCarrierPhaseMeasurementRequest NULL OPTIONAL,
+ ganssTODGSMTimeAssociationMeasurementRequest NULL OPTIONAL,
+requiredResponseTime RequiredResponseTime OPTIONAL,
+ ...
+ -- Further Release 7 extentions here
+}
+
+-- additional satellite systems may be added in future versions of the protocol
+GANSSPositioningMethod ::= BIT STRING {
+ gps (0),
+ galileo (1)} (SIZE (2..16))
+
+GANSS-AssistData ::= SEQUENCE {
+ ganss-controlHeader GANSS-ControlHeader
+}
+
+GANSS-ControlHeader ::= SEQUENCE {
+ ganssCommonAssistData GANSSCommonAssistData OPTIONAL,
+ ganssGenericAssistDataList SeqOfGANSSGenericAssistDataElement OPTIONAL
+}
+
+-- GANSS Common Assistance Data Elements
+GANSSCommonAssistData ::= SEQUENCE {
+ ganssReferenceTime GANSSReferenceTime OPTIONAL,
+ ganssRefLocation GANSSRefLocation OPTIONAL,
+ ganssIonosphericModel GANSSIonosphericModel OPTIONAL,
+ ...
+}
+
+-- List of GANSS Generic Assistance Data Elements, up to 8 GANSS
+SeqOfGANSSGenericAssistDataElement ::= SEQUENCE (SIZE (1..8)) OF GANSSGenericAssistDataElement
+
+-- GANSS Generic Assistance Data Elements
+GANSSGenericAssistDataElement ::= SEQUENCE {
+ ganssID INTEGER (0..7) OPTIONAL, -- Coding according to Annex
+ ganssTimeModel SeqOfGANSSTimeModel OPTIONAL,
+ ganssDiffCorrections GANSSDiffCorrections OPTIONAL,
+ ganssNavigationModel GANSSNavModel OPTIONAL,
+ ganssRealTimeIntegrity GANSSRealTimeIntegrity OPTIONAL,
+ ganssDataBitAssist GANSSDataBitAssist OPTIONAL,
+ ganssRefMeasurementAssist GANSSRefMeasurementAssist OPTIONAL,
+ ganssAlmanacModel GANSSAlmanacModel OPTIONAL,
+ ganssUTCModel GANSSUTCModel OPTIONAL,
+ ...
+}
+
+-- GANSS COMMON ASSISTANCE DATA ELEMENTS
+
+-- GANSS Reference Time IE
+GANSSReferenceTime ::= SEQUENCE {
+ ganssRefTimeInfo GANSSRefTimeInfo,
+ ganssTOD-GSMTimeAssociation GANSSTOD-GSMTimeAssociation OPTIONAL
+}
+
+-- GANSS Reference Time includes GANSS TOD, GANSS Day, uncertainty
+GANSSRefTimeInfo ::= SEQUENCE {
+ ganssDay INTEGER(0 .. 8191) OPTIONAL,
+ ganssTOD GANSSTOD,
+ ganssTODUncertainty GANSSTODUncertainty OPTIONAL,
+ ganssTimeID INTEGER (0 .. 7) OPTIONAL
+}
+
+-- GANSS TOD integer seconds
+GANSSTOD ::= INTEGER (0 .. 86399)
+
+-- GANSS TOD uncertainty
+GANSSTODUncertainty ::= INTEGER (0 .. 127) -- Coding according to Annex
+
+-- GANSS TOD-GSM Time association
+GANSSTOD-GSMTimeAssociation ::= SEQUENCE {
+ bcchCarrier BCCHCarrier, -- BCCH carrier
+ bsic BSIC, -- BSIC
+ frameNumber FrameNumber,
+ timeSlot TimeSlot,
+ bitNumber BitNumber,
+ frameDrift FrameDrift OPTIONAL
+}
+
+-- Frame drift
+FrameDrift ::= INTEGER(-64 .. 63)
+
+-- GANSS Reference Location IE
+GANSSRefLocation ::= SEQUENCE {
+ threeDLocation Ext-GeographicalInformation
+}
+
+-- GANSS Ionospheric Model IE
+-- GANSS Ionospheric Model consists of NeQuick model parameters and storm flags
+
+GANSSIonosphericModel ::= SEQUENCE {
+ ganssIonoModel GANSSIonosphereModel,
+ ganssIonoStormFlags GANSSIonoStormFlags OPTIONAL,
+ ...
+}
+
+-- GANSS ionosphere model. Coding according to Annex
+GANSSIonosphereModel ::= SEQUENCE {
+ ai0 INTEGER (0 .. 4095),
+ ai1 INTEGER (0 .. 4095),
+ ai2 INTEGER (0 .. 4095)
+}
+
+-- GANSS ionosphere storm flags
+GANSSIonoStormFlags ::= SEQUENCE {
+ ionoStormFlag1 INTEGER (0 .. 1),
+ ionoStormFlag2 INTEGER (0 .. 1),
+ ionoStormFlag3 INTEGER (0 .. 1),
+ ionoStormFlag4 INTEGER (0 .. 1),
+ ionoStormFlag5 INTEGER (0 .. 1)
+}
+
+-- GANSS GENERIC ASSISTANCE DATA ELEMENTS
+
+-- GANSS Time Model IE consists of time offset and first and second order parameters to relate GNSS
+-- specific system time to selected time reference
+SeqOfGANSSTimeModel ::= SEQUENCE (SIZE(1..7)) OF GANSSTimeModelElement
+
+GANSSTimeModelElement ::= SEQUENCE {
+ ganssTimeModelRefTime INTEGER(0 .. 65535),
+ tA0 TA0,
+ tA1 TA1 OPTIONAL,
+ tA2 TA2 OPTIONAL,
+ gnssTOID INTEGER (0 .. 7),
+ weekNumber INTEGER (0 .. 8191) OPTIONAL
+}
+
+-- GANSS time model parameter A0
+TA0 ::= INTEGER (-2147483648 .. 2147483647)
+
+-- GANSS time model parameter A1
+TA1 ::= INTEGER (-8388608 .. 8388607)
+
+-- GANSS time model parameter A2
+TA2 ::= INTEGER (-64 .. 63)
+
+-- DGANSS Corrections IE
+GANSSDiffCorrections ::= SEQUENCE {
+ dganssRefTime INTEGER (0 .. 119), -- DGANSS reference time
+
+ -- N_SGN_TYPE can be read from number of elements of sgnTypeList
+ sgnTypeList SeqOfSgnTypeElement
+}
+
+SeqOfSgnTypeElement ::= SEQUENCE (SIZE (1..3)) OF SgnTypeElement -- max three signals per GNSS
+
+-- DGANSS signal type element, once per GNSS signal type included in DGANSS
+SgnTypeElement ::= SEQUENCE {
+ ganssSignalID GANSSSignalID OPTIONAL, -- signal type identity
+ ganssStatusHealth INTEGER (0 .. 7),
+ -- N_SGN can be read from number of elements of dganssSgnList
+ dganssSgnList SeqOfDGANSSSgnElement
+}
+
+GANSSSignalID ::= INTEGER (0 .. 3) -- Coding according to Annex
+SeqOfDGANSSSgnElement ::= SEQUENCE (SIZE (1..16)) OF DGANSSSgnElement
+
+-- number of correction for signals
+DGANSSSgnElement ::= SEQUENCE {
+ svID SVID, -- Satellite identity
+
+--- Sequence number for GANSS Navigation Model that matches the DGANSS correction set
+ iod INTEGER (0 .. 1023),
+
+ -- User Differential Range Error
+ udre INTEGER (0..3),
+
+ -- Pseudo Range Correction, range is
+ -- -655.04 - +655.04,
+ pseudoRangeCor INTEGER (-2047..2047),
+
+ -- Pseudo Range Rate Correction, range is
+ -- -4.064 - +4.064,
+ rangeRateCor INTEGER (-127..127)
+}
+
+SVID ::= INTEGER (0 .. 63) -- Coding according to Annex
+
+-- GANSS Navigation Model IE
+GANSSNavModel ::= SEQUENCE {
+ nonBroadcastIndFlag INTEGER (0 .. 1),
+ toeMSB INTEGER (0 .. 31) OPTIONAL, -- 5 MSB of toe and toc
+ eMSB INTEGER (0 .. 127) OPTIONAL,
+ sqrtAMBS INTEGER (0 .. 63) OPTIONAL,
+ ganssSatelliteList SeqOfGANSSSatelliteElement
+}
+
+SeqOfGANSSSatelliteElement ::= SEQUENCE (SIZE(1..32)) OF GANSSSatelliteElement
+
+GANSSSatelliteElement ::= SEQUENCE {
+ svID SVID,
+ svHealth INTEGER (-7 .. 13), -- Coding according to Annex
+ iod INTEGER (0 .. 1023), -- Coding according to Annex
+ ganssClockModel GANSSClockModel,
+ ganssOrbitModel GANSSOrbitModel,
+ ...
+}
+
+-- GANSS orbit model for the GNSS satellite according to the choice
+GANSSOrbitModel ::= CHOICE {
+ keplerianSet NavModel-KeplerianSet,
+ ...
+}
+
+-- Navigation model in Keplerian parameters
+NavModel-KeplerianSet ::= SEQUENCE {
+ keplerToeLSB INTEGER (0 .. 511), -- 9LSB are given in GANSSNavigationModel
+ keplerW INTEGER (-2147483648..2147483647),
+ keplerDeltaN INTEGER (-32768..32767),
+ keplerM0 INTEGER (-2147483648..2147483647),
+ keplerOmegaDot INTEGER (-8388608..8388607),
+ keplerELSB INTEGER (0..33554431),
+ keplerIDot INTEGER (-8192..8191),
+ keplerAPowerHalfLSB INTEGER (0.. 67108863),
+ keplerI0 INTEGER (-2147483648..2147483647),
+ keplerOmega0 INTEGER (-2147483648..2147483647),
+ keplerCrs INTEGER (-32768..32767),
+ keplerCis INTEGER (-32768..32767),
+ keplerCus INTEGER (-32768..32767),
+ keplerCrc INTEGER (-32768..32767),
+ keplerCic INTEGER (-32768..32767),
+ keplerCuc INTEGER (-32768..32767)
+}
+
+-- GANSS clock model for the GNSS satellite according to the choice
+GANSSClockModel ::= CHOICE {
+ standardClockModelList SeqOfStandardClockModelElement,
+ ...
+}
+
+SeqOfStandardClockModelElement ::= SEQUENCE (SIZE(1..2)) OF StandardClockModelElement
+
+StandardClockModelElement ::= SEQUENCE {
+ stanClockTocLSB INTEGER (0 .. 511), -- 9LSB of time of clock
+ stanClockAF2 INTEGER (-2048 .. 2047),
+ stanClockAF1 INTEGER (-131072 .. 131071),
+ stanClockAF0 INTEGER (-134217728 .. 134217727),
+ stanClockTgd INTEGER (-512 .. 511) OPTIONAL,
+ stanModelID INTEGER (0 .. 1) OPTIONAL,
+ ...
+}
+
+-- GANSS Real-Time Integrity IE
+GANSSRealTimeIntegrity ::= SEQUENCE {
+ -- list of bad signals
+ -- NBS can be read from number of elements in SeqOf-BadSignalSet
+ ganssBadSignalList SeqOfBadSignalElement
+}
+
+SeqOfBadSignalElement ::= SEQUENCE (SIZE(1..16)) OF BadSignalElement
+
+BadSignalElement ::= SEQUENCE {
+ badSVID SVID, -- Coding according to Annex
+ badSignalID INTEGER (0 .. 3) OPTIONAL -- Coding according to Annex
+}
+
+
+-- GANSS Data Bit Assistance IE
+GANSSDataBitAssist ::= SEQUENCE {
+ ganssTOD INTEGER (0 .. 59),
+ svID SVID,
+ ganssDataTypeID INTEGER (0 .. 2), -- Coding according to Annex
+ -- list of navigation data bits
+ -- N_BIT can be read from number of elements in SeqOf-DataBits
+ ganssDataBits SeqOf-GANSSDataBits
+}
+
+SeqOf-GANSSDataBits ::= SEQUENCE (SIZE(1 .. 1024)) OF GANSSDataBit
+GANSSDataBit ::= INTEGER(0 .. 1)
+
+-- GANSS Reference Measurement Assistance IE
+-- Code and Doppler assistance from the network.
+GANSSRefMeasurementAssist ::= SEQUENCE {
+ ganssSignalID INTEGER (0 .. 3) OPTIONAL, -- Coding according to Annex
+ ganssRefMeasAssitList SeqOfGANSSRefMeasurementElement
+}
+
+SeqOfGANSSRefMeasurementElement ::= SEQUENCE (SIZE(1 .. 16)) OF GANSSRefMeasurementElement
+
+GANSSRefMeasurementElement ::= SEQUENCE {
+ svID SVID,
+ -- Doppler 0th order term,
+ -- -1024 m/s to 1023.5 m/s with 0.5 m/s resolution)
+ doppler0 INTEGER (-2048 .. 2047), -- Coding according to Annex
+ additionalDoppler AdditionalDopplerFields OPTIONAL,
+ codePhase INTEGER (0 .. 1022), -- Code Phase in ms
+ intCodePhase INTEGER (0 .. 127), -- Integer Code Phase in ms
+ codePhaseSearchWindow INTEGER (0 .. 31), -- Code Phase Search Window, see Annex
+ additionalAngle AddionalAngleFields OPTIONAL,
+ ...
+}
+
+AdditionalDopplerFields ::= SEQUENCE {
+ -- Doppler 1st order term, -0.2 - +0.1 m/s2
+ doppler1 INTEGER (0..63),
+ dopplerUncertainty INTEGER (0..4)
+}
+
+-- GANSS Almanac Model IE
+GANSSAlmanacModel ::= SEQUENCE {
+ weekNumber INTEGER (0 .. 255),
+ svIDMask SVIDMASK,
+ toa INTEGER (0 .. 255) OPTIONAL,
+ ioda INTEGER (0 .. 3) OPTIONAL,
+ ganssAlmanacList SeqOfGANSSAlmanacElement
+}
+
+-- SV ID Mask, LSB for ID 1 and MSB for ID 36
+SVIDMASK ::= BIT STRING (SIZE (1..36))
+
+SeqOfGANSSAlmanacElement ::= SEQUENCE (SIZE(1 .. 36)) OF GANSSAlmanacElement
+
+-- GANSS Almanac Model
+GANSSAlmanacElement ::= CHOICE {
+ keplerianAlmanacSet Almanac-KeplerianSet,
+ ...
+}
+
+-- Almanac parameters according to Keplerian parameters
+Almanac-KeplerianSet ::= SEQUENCE {
+ kepAlmanacE INTEGER (0 .. 2047),
+ kepAlmanacDeltaI INTEGER (-1024 .. 1023),
+ kepAlmanacOmegaDot INTEGER (-1024 .. 1023),
+ kepSVHealth INTEGER (0 .. 15), -- Coding according to Annex
+ kepAlmanacAPowerHalf INTEGER (-65536 .. 65535),
+ kepAlmanacOmega0 INTEGER (-32768 .. 32767),
+ kepAlmanacW INTEGER (-32768 .. 32767),
+ kepAlmanacM0 INTEGER (-32768 .. 32767),
+ kepAlmanacAF0 INTEGER (-8192 .. 8191),
+ kepAlmanacAF1 INTEGER (-1024..1023)
+}
+
+-- GANSS Universal Time Coordinate Model
+GANSSUTCModel ::= SEQUENCE {
+ ganssUtcA1 INTEGER (-8388608..8388607),
+ ganssUtcA0 INTEGER (-2147483648..2147483647),
+ ganssUtcTot INTEGER (0..255),
+ ganssUtcWNt INTEGER (0..255),
+ ganssUtcDeltaTls INTEGER (-128..127),
+ ganssUtcWNlsf INTEGER (0..255),
+ ganssUtcDN INTEGER (-128..127),
+ ganssUtcDeltaTlsf INTEGER (-128..127)
+}
+
+--Required Measurement Request Response Time, range is 1 to 128 seconds.
+RequiredResponseTime ::= INTEGER (1..128)
+
+Rel-7-MsrPosition-Rsp-Extension ::= SEQUENCE {
+
+ velEstimate VelocityEstimate OPTIONAL,
+ -- Horizontal Velocity
+ -- Horizontal with Vertical Velocity
+ -- Horizontal Velocity with Uncertainty
+ -- Horizontal with Vertical Velocity and Uncertainty
+ ganssLocationInfo GANSSLocationInfo OPTIONAL,
+ ganssMeasureInfo GANSSMeasureInfo OPTIONAL,
+ ...
+-- Further Release 7 extensions here
+}
+
+-- GANSS Location Information contains location estimate, time stamp with uncertainty
+-- and optionally Reference Frame field
+GANSSLocationInfo ::= SEQUENCE {
+ referenceFrame ReferenceFrame OPTIONAL, -- Reference Frame Number
+ ganssTODm GANSSTODm OPTIONAL, -- GNSS TOD modulo
+ ganssTODFrac INTEGER (0 .. 16384) OPTIONAL, -- Coding according to Annex
+ ganssTODUncertainty GANSSTODUncertainty OPTIONAL, -- Coding according to Annex
+ ganssTimeID INTEGER (0 .. 3) OPTIONAL, -- Coding according to Annex
+ fixType FixType,
+ posData PositionData,
+ stationaryIndication INTEGER(0 .. 1) OPTIONAL, -- '0' if moving or motion not known
+ -- Possible shapes carried in posEstimate are
+ -- ellipsoid point,
+ -- ellipsoid point with uncertainty circle
+ -- ellipsoid point with uncertainty ellipse
+ -- ellipsoid point with altitude and uncertainty ellipsoid
+ posEstimate Ext-GeographicalInformation,
+ ...
+}
+
+PositionData ::= BIT STRING {
+ e-otd(0),
+ gps (1),
+ galileo (2) } (SIZE (3..16))
+
+
+-- GANSS TOD modulo 1 hour
+GANSSTODm ::= INTEGER (0 .. 3599999)
+
+ReferenceFrame ::= SEQUENCE {
+ referenceFN INTEGER (0 .. 65535),
+ -- Note that applicable range for referenceFN is 0 - 42431
+ referenceFNMSB INTEGER (0 .. 63) OPTIONAL -- MSB of Reference Frame Number
+}
+
+
+
+-- GANSS Measurement Information
+GANSSMeasureInfo ::= SEQUENCE {
+ -- Measurement info elements
+ -- user has to make sure that in this element is number of elements
+ -- defined in reference BTS identity
+ ganssMsrSetList SeqOfGANSS-MsrSetElement
+}
+SeqOfGANSS-MsrSetElement ::= SEQUENCE (SIZE(1..3)) OF GANSS-MsrSetElement
+
+-- GANSS measurement information 1-3 times in a message
+GANSS-MsrSetElement ::= SEQUENCE {
+ referenceFrame ReferenceFrame OPTIONAL, -- Reference Frame Number
+ ganssTODm GANSSTODm OPTIONAL, -- GANSS TOD modulo
+ deltaGNASSTOD INTEGER (0 .. 127) OPTIONAL,
+ ganssTODUncertainty GANSSTODUncertainty OPTIONAL, -- Coding accoring to Annex
+
+ --N_SGN_TYPE can be read from number of elements of SeqOfGANSS-SgnTypeElement
+ ganss-SgnTypeList SeqOfGANSS-SgnTypeElement
+}
+
+-- Measurements can be returned up to 6 different signal types
+SeqOfGANSS-SgnTypeElement ::= SEQUENCE (SIZE(1..6)) OF GANSS-SgnTypeElement
+
+GANSS-SgnTypeElement ::= SEQUENCE {
+ ganssSignalID INTEGER (0 .. 15), -- Coding accroding to Annex
+ --N_SGN can be read from number of elements of SeqOfGANSS-SgnElement
+ ganss-SgnList SeqOfGANSS-SgnElement
+}
+
+-- Measurements can be returned up to 16 per signal types
+SeqOfGANSS-SgnElement ::= SEQUENCE (SIZE(1..16)) OF GANSS-SgnElement
+
+
+GANSS-SgnElement ::= SEQUENCE {
+ svID SVID,
+ cNo INTEGER (0 .. 63),
+ mpathDet MpathIndic, -- Coding according to Annex
+ carrierQualityInd INTEGER (0 .. 3) OPTIONAL, -- Coding according to Annex
+ codePhase INTEGER (0 .. 2097151),
+ integerCodePhase INTEGER (0 .. 63) OPTIONAL,
+ codePhaseRMSError INTEGER (0..63), -- Coding accoring to Annex
+ doppler INTEGER (-32768 .. 32767) OPTIONAL,
+ adr INTEGER (0 .. 33554431) OPTIONAL
+}
+
+Rel7-AssistanceData-Extension ::= SEQUENCE {
+ ganss-AssistData GANSS-AssistData OPTIONAL,
+ ganssCarrierPhaseMeasurementRequest NULL OPTIONAL,
+ ganssTODGSMTimeAssociationMeasurementRequest NULL OPTIONAL,
+ ...
+-- Possibly more extensions for Release 7 here
+}
+
+END
diff --git a/rrlp-ephemeris/asn1/RRLP-Messages.asn b/rrlp-ephemeris/asn1/RRLP-Messages.asn
new file mode 100644
index 000000000..79140e2a2
--- /dev/null
+++ b/rrlp-ephemeris/asn1/RRLP-Messages.asn
@@ -0,0 +1,38 @@
+-- RRLP-Messages.asn
+-- $Id$
+-- Taken from 3GPP TS 44.031 V7.4.0 (2007-03)
+-- http://www.3gpp.org/ftp/Specs/archive/44_series/44.031/44031-740.zip/44031-740.doc
+--
+-- 3.1 General Format of RRLP Message
+--
+
+RRLP-Messages
+-- { RRLP-messages }
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+IMPORTS
+ MsrPosition-Req, MsrPosition-Rsp, AssistanceData,
+ ProtocolError
+FROM
+ RRLP-Components -- { RRLP-Components }
+;
+
+PDU ::= SEQUENCE {
+ referenceNumber INTEGER (0..7),
+ component RRLP-Component
+}
+
+RRLP-Component ::= CHOICE {
+ msrPositionReq MsrPosition-Req,
+ msrPositionRsp MsrPosition-Rsp,
+ assistanceData AssistanceData,
+ assistanceDataAck NULL,
+ protocolError ProtocolError,
+ ...
+
+}
+
+END
diff --git a/rrlp-ephemeris/asn1/patch-rrlp-components.diff b/rrlp-ephemeris/asn1/patch-rrlp-components.diff
new file mode 100644
index 000000000..a5e55ae06
--- /dev/null
+++ b/rrlp-ephemeris/asn1/patch-rrlp-components.diff
@@ -0,0 +1,36 @@
+--- RRLP-Components.asn 2009-10-26 22:10:44.000000000 +0100
++++ RRLP-Components.asn 2009-10-26 22:10:44.000000000 +0100
+@@ -18,16 +18,16 @@
+ Ext-GeographicalInformation, VelocityEstimate
+ FROM
+ MAP-LCS-DataTypes {
+- ccitt identified-organization (4) etsi (0) mobileDomain (0)
+- gsm-Network (1) modules (3) map-LCS-DataTypes (25) version5 (5)}
++ itu-t identified-organization (4) etsi (0) mobileDomain (0)
++ gsm-Network (1) modules (3) map-LCS-DataTypes (25) version11 (11)}
+
+ ExtensionContainer
+ FROM MAP-ExtensionDataTypes {
+- ccitt identified-organization (4) etsi (0) mobileDomain (0)
+- gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version4 (4)}
++ itu-t identified-organization (4) etsi (0) mobileDomain (0)
++ gsm-Network (1) modules (3) map-ExtensionDataTypes (21) version11 (11)}
+ ;
+
+ -- Add here other ASN.1 definitions presented below
+ -- in chapters 4 and 5.
+
+@@ -305,11 +305,11 @@
+ SystemInfoIndex ::= INTEGER (1..32)
+
+ CellIDAndLAC ::= SEQUENCE {
+- referenceLAC LAC, -- Location area code
++ referenceLAC LACID, -- Location area code
+ referenceCI CellID -- Cell identity
+ }
+ CellID ::= INTEGER (0..65535)
+-LAC ::= INTEGER (0..65535)
++LACID ::= INTEGER (0..65535)
+
+ -- OTD-MeasureInfo
+ OTD-MeasureInfo ::= SEQUENCE {
diff --git a/rrlp-ephemeris/asn1c_patches/00_add_enumerated_verbose.diff b/rrlp-ephemeris/asn1c_patches/00_add_enumerated_verbose.diff
new file mode 100644
index 000000000..64c22a3cf
--- /dev/null
+++ b/rrlp-ephemeris/asn1c_patches/00_add_enumerated_verbose.diff
@@ -0,0 +1,56 @@
+Index: skeletons/NativeEnumerated.c
+===================================================================
+--- skeletons/NativeEnumerated.c (revision 1407)
++++ skeletons/NativeEnumerated.c (working copy)
+@@ -22,7 +22,7 @@
+ "ENUMERATED", /* The ASN.1 type is still ENUMERATED */
+ "ENUMERATED",
+ NativeInteger_free,
+- NativeInteger_print,
++ NativeEnumerated_print,
+ asn_generic_no_constraint,
+ NativeInteger_decode_ber,
+ NativeInteger_encode_der,
+@@ -205,3 +205,30 @@
+ _ASN_ENCODED_OK(er);
+ }
+
++int
++NativeEnumerated_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
++ asn_app_consume_bytes_f *cb, void *app_key) {
++ asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics;
++ const long *native = (const long *)sptr;
++ char scratch[256];
++ int ret;
++
++ (void)td; /* Unused argument */
++ (void)ilevel; /* Unused argument */
++
++ if(native) {
++ const asn_INTEGER_enum_map_t *map = INTEGER_map_value2enum(specs, *native);
++ if (map && map->enum_len && map->enum_name) {
++ ret = snprintf(scratch, sizeof(scratch),
++ "%s", map->enum_name);
++ } else {
++ ret = snprintf(scratch, sizeof(scratch),
++ (specs && specs->field_unsigned)
++ ? "%lu" : "%ld", *native);
++ }
++ assert(ret > 0 && (size_t)ret < sizeof(scratch));
++ return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
++ } else {
++ return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
++ }
++}
+Index: skeletons/NativeEnumerated.h
+===================================================================
+--- skeletons/NativeEnumerated.h (revision 1407)
++++ skeletons/NativeEnumerated.h (working copy)
+@@ -24,6 +24,7 @@
+ xer_type_encoder_f NativeEnumerated_encode_xer;
+ per_type_decoder_f NativeEnumerated_decode_uper;
+ per_type_encoder_f NativeEnumerated_encode_uper;
++asn_struct_print_f NativeEnumerated_print;
+
+ #ifdef __cplusplus
+ }
diff --git a/rrlp-ephemeris/asn1c_patches/01_fix_per_encoding_dieter.diff b/rrlp-ephemeris/asn1c_patches/01_fix_per_encoding_dieter.diff
new file mode 100644
index 000000000..a09c20159
--- /dev/null
+++ b/rrlp-ephemeris/asn1c_patches/01_fix_per_encoding_dieter.diff
@@ -0,0 +1,17 @@
+Index: skeletons/per_support.c
+===================================================================
+--- skeletons/per_support.c (revision 1407)
++++ skeletons/per_support.c (working copy)
+@@ -336,7 +336,12 @@
+ buf[3] = bits;
+ else {
+ ASN_DEBUG("->[PER out split %d]", obits);
++#if 1 // Dieter
++ po->nboff -= obits; // undo incrementation from a few lines above
++ per_put_few_bits(po, bits >> (obits - 24), 24); // shift according to the rest of the bits
++#else
+ per_put_few_bits(po, bits >> 8, 24);
++#endif
+ per_put_few_bits(po, bits, obits - 24);
+ ASN_DEBUG("<-[PER out split %d]", obits);
+ }
diff --git a/rrlp-ephemeris/data.ubx b/rrlp-ephemeris/data.ubx
new file mode 100644
index 000000000..07cdddcd9
--- /dev/null
+++ b/rrlp-ephemeris/data.ubx
Binary files differ
diff --git a/rrlp-ephemeris/get-test-data.sh b/rrlp-ephemeris/get-test-data.sh
new file mode 100755
index 000000000..169f43c8f
--- /dev/null
+++ b/rrlp-ephemeris/get-test-data.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+DEV=$1
+OUTF=$2
+
+# Change mode
+echo -en "\$PUBX,41,1,0001,0001,9600,0*14\r\n" > ${DEV}
+
+# Wait a little
+sleep 2
+
+# Start dump
+echo -en "\xb5\x62\x01\x02\x00\x00\x03\x0a" | \
+ socat -t5 ${DEV},b9600,raw,clocal=1,echo=0 - > ${OUTF}
+echo -en "\xb5\x62\x0b\x10\x00\x00\x1b\x5c" | \
+ socat -t10 ${DEV},b9600,raw,clocal=1,echo=0 - >> ${OUTF}
+
diff --git a/rrlp-ephemeris/gpl-2.0.txt b/rrlp-ephemeris/gpl-2.0.txt
new file mode 100644
index 000000000..d511905c1
--- /dev/null
+++ b/rrlp-ephemeris/gpl-2.0.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/rrlp-ephemeris/gpl-3.0.txt b/rrlp-ephemeris/gpl-3.0.txt
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/rrlp-ephemeris/gpl-3.0.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/rrlp-ephemeris/gps.c b/rrlp-ephemeris/gps.c
new file mode 100644
index 000000000..c23574840
--- /dev/null
+++ b/rrlp-ephemeris/gps.c
@@ -0,0 +1,126 @@
+/*
+ * gps.c
+ *
+ * A few utility functions to deal with low level GPS data
+ *
+ *
+ * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gps.h"
+
+
+#define GET_FIELD_U(w, nb, pos) (((w) >> (pos)) & ((1<<(nb))-1))
+#define GET_FIELD_S(w, nb, pos) (((int)((w) << (32-(nb)-(pos)))) >> (32-(nb)))
+
+/*
+ * Unpacks GPS Subframe 1,2,3 payloads (3 * 8 words)
+ *
+ * Note: eph->sv_id is not filled here since not present in those subframes
+ *
+ * (no parity bit checking is done, only the lower 24 bits of each word
+ * are used)
+ */
+int
+gps_unpack_sf123(uint32_t *sf, struct gps_ephemeris_sv *eph)
+{
+ uint32_t *sf1 = &sf[0];
+ uint32_t *sf2 = &sf[8];
+ uint32_t *sf3 = &sf[16];
+
+ int iode1, iode2;
+
+ eph->week_no = GET_FIELD_U(sf1[0], 10, 14);
+ eph->code_on_l2 = GET_FIELD_U(sf1[0], 2, 12);
+ eph->sv_ura = GET_FIELD_U(sf1[0], 4, 8);
+ eph->sv_health = GET_FIELD_U(sf1[0], 6, 2);
+ eph->l2_p_flag = GET_FIELD_U(sf1[1], 1, 23);
+ eph->t_gd = GET_FIELD_S(sf1[4], 8, 0);
+ eph->iodc = (GET_FIELD_U(sf1[0], 2, 0) << 8) | \
+ GET_FIELD_U(sf1[5], 8, 16);
+ eph->t_oc = GET_FIELD_U(sf1[5], 16, 0);
+ eph->a_f2 = GET_FIELD_S(sf1[6], 8, 16);
+ eph->a_f1 = GET_FIELD_S(sf1[6], 16, 0);
+ eph->a_f0 = GET_FIELD_S(sf1[7], 22, 2);
+
+ iode1 = GET_FIELD_U(sf2[0], 8, 16);
+ eph->c_rs = GET_FIELD_S(sf2[0], 16, 0);
+ eph->delta_n = GET_FIELD_S(sf2[1], 16, 8);
+ eph->m_0 = (GET_FIELD_S(sf2[1], 8, 0) << 24) | \
+ GET_FIELD_U(sf2[2], 24, 0);
+ eph->c_uc = GET_FIELD_S(sf2[3], 16, 8);
+ eph->e = (GET_FIELD_U(sf2[3], 8, 0) << 24) | \
+ GET_FIELD_U(sf2[4], 24, 0);
+ eph->c_us = GET_FIELD_S(sf2[5], 16, 8);
+ eph->a_powhalf = (GET_FIELD_U(sf2[5], 8, 0) << 24) | \
+ GET_FIELD_U(sf2[6], 24, 0);
+ eph->t_oe = GET_FIELD_U(sf2[7], 16, 8);
+ eph->fit_flag = GET_FIELD_U(sf2[7], 1, 7);
+
+ eph->c_ic = GET_FIELD_S(sf3[0], 16, 8);
+ eph->omega_0 = (GET_FIELD_S(sf3[0], 8, 0) << 24) | \
+ GET_FIELD_U(sf3[1], 24, 0);
+ eph->c_is = GET_FIELD_S(sf3[2], 16, 8);
+ eph->i_0 = (GET_FIELD_S(sf3[2], 8, 0) << 24) | \
+ GET_FIELD_U(sf3[3], 24, 0);
+ eph->c_rc = GET_FIELD_S(sf3[4], 16, 8);
+ eph->w = (GET_FIELD_S(sf3[4], 8, 0) << 24) | \
+ GET_FIELD_U(sf3[5], 24, 0);
+ eph->omega_dot = GET_FIELD_S(sf3[6], 24, 0);
+ iode2 = GET_FIELD_U(sf3[7], 8, 16);
+ eph->idot = GET_FIELD_S(sf3[7], 14, 2);
+
+ eph->_rsvd1 = GET_FIELD_U(sf1[1], 23, 0);
+ eph->_rsvd2 = GET_FIELD_U(sf1[2], 24, 0);
+ eph->_rsvd3 = GET_FIELD_U(sf1[3], 24, 0);
+ eph->_rsvd4 = GET_FIELD_U(sf1[4], 16, 8);
+ eph->aodo = GET_FIELD_U(sf2[7], 5, 2);
+
+ /* Check & cross-validate iodc[7:0], iode1, iode2 */
+ if ((iode1 != iode2) || (iode1 != (eph->iodc & 0xff)))
+ return -1;
+
+ return 0;
+}
+
+
+/*
+ * Unpacks GPS Subframe 4 or 5 Almanac pages payload (8 words)
+ *
+ * (no parity bit checking is done, only the lower 24 bits of each word
+ * are used)
+ */
+int
+gps_unpack_sf45_almanac(uint32_t *sf, struct gps_almanac_sv *alm)
+{
+ alm->sv_id = GET_FIELD_U(sf[0], 6, 16);
+
+ alm->e = GET_FIELD_U(sf[0], 16, 0);
+ alm->t_oa = GET_FIELD_U(sf[1], 8, 16);
+ alm->ksii = GET_FIELD_S(sf[1], 16, 0);
+ alm->omega_dot = GET_FIELD_S(sf[2], 16, 8);
+ alm->sv_health = GET_FIELD_U(sf[2], 8, 0);
+ alm->a_powhalf = GET_FIELD_U(sf[3], 24, 0);
+ alm->omega_0 = GET_FIELD_S(sf[4], 24, 0);
+ alm->w = GET_FIELD_S(sf[5], 24, 0);
+ alm->m_0 = GET_FIELD_S(sf[6], 24, 0);
+ alm->a_f0 = (GET_FIELD_S(sf[7], 8, 16) << 3) | \
+ GET_FIELD_U(sf[7], 3, 2);
+ alm->a_f1 = GET_FIELD_S(sf[7], 11, 5);
+
+ return 0;
+}
+
diff --git a/rrlp-ephemeris/gps.h b/rrlp-ephemeris/gps.h
new file mode 100644
index 000000000..241b9d743
--- /dev/null
+++ b/rrlp-ephemeris/gps.h
@@ -0,0 +1,190 @@
+/*
+ * gps.h
+ *
+ * Header to deal with low level GPS data
+ *
+ *
+ * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GPS_H__
+#define __GPS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+
+#define MAX_SV 64
+
+
+/* Ionosperic model data */
+struct gps_ionosphere_model {
+ /* #bits Scale factor Effective Units */
+ /* (LSB) range */
+
+ int alpha_0; /* s 8 2^-30 seconds */
+ int alpha_1; /* s 8 2^-27 s / semi-circles */
+ int alpha_2; /* s 8 2^-24 s / (semi-circles)^2 */
+ int alpha_3; /* s 8 2^-24 s / (semi-circles)^3 */
+ int beta_0; /* s 8 2^11 seconds */
+ int beta_1; /* s 8 2^14 s / semi-circles */
+ int beta_2; /* s 8 2^16 s / (semi-circles)^2 */
+ int beta_3; /* s 8 2^16 s / (semi-circles)^3 */
+};
+
+
+/* UTC model data */
+struct gps_utc_model {
+ /* #bits Scale factor Effective Units */
+ /* (LSB) range */
+
+ int a0; /* s 32 2^-30 seconds */
+ int a1; /* s 24 2^-50 seconds / seconds */
+ int delta_t_ls; /* s 8 1 seconds */
+ int t_ot; /* u 8 2^12 602,112 seconds */
+ int wn_t; /* u 8 1 weeks */
+ int wn_lsf; /* u 8 1 weeks */
+ int dn; /* u 8 1 7 days */
+ int delta_t_lsf;/* s 8 1 seconds */
+};
+
+
+/* Almanach data */
+struct gps_almanac_sv {
+ int sv_id;
+ int sv_health;
+
+ /* #bits Scale factor Effective Units */
+ /* (LSB) range */
+
+ int e; /* u 16 2^-21 */
+ int t_oa; /* u 8 2^12 602,112 seconds */
+ int ksii; /* s 16 2^-19 semi-circles */
+ int omega_dot; /* s 16 2^-38 semi-circles / s */
+ int a_powhalf; /* u 24 2^-11 meters */
+ int omega_0; /* s 24 2^-23 semi-circles */
+ int w; /* s 24 2^-23 semi-circles */
+ int m_0; /* s 24 2^-23 semi-circles */
+ int a_f0; /* s 11 2^-20 seconds */
+ int a_f1; /* s 11 2^-38 seconds / seconds */
+};
+
+struct gps_almanac {
+ int wna;
+ int n_sv;
+ struct gps_almanac_sv svs[MAX_SV];
+};
+
+
+/* Ephemeris data */
+struct gps_ephemeris_sv {
+ int sv_id;
+
+ /* #bits Scale factor Effective Units */
+ /* (LSB) range */
+
+ int code_on_l2; /* u 2 1 / */
+ int week_no; /* u 10 1 week */
+ int l2_p_flag; /* u 1 1 / */
+ int sv_ura; /* u 4 / / */
+ int sv_health; /* u 6 / / */
+ int t_gd; /* s 8 2^-31 seconds */
+ int iodc; /* u 10 / / */
+ int t_oc; /* u 16 2^4 604,784 seconds */
+ int a_f2; /* s 8 2^-55 sec / sec^2 */
+ int a_f1; /* s 16 2^-43 sec / sec */
+ int a_f0; /* s 22 2^-31 seconds */
+
+ int c_rs; /* s 16 2^-5 meters */
+ int delta_n; /* s 16 2^-43 semi-circles / s */
+ int m_0; /* s 32 2^-31 semi-circles */
+ int c_uc; /* s 16 2^-29 radians */
+ unsigned int e; /* u 32 2^-33 0.03 / */
+ int c_us; /* s 16 2^-29 radians */
+ unsigned int a_powhalf; /* u 32 2^-19 meters^(1/2) */
+ int t_oe; /* u 16 2^4 604,784 seconds */
+ int fit_flag; /* u 1 / / */
+
+ int c_ic; /* s 16 2^-29 radians */
+ int omega_0; /* s 32 2^-31 semi-circles */
+ int c_is; /* s 16 2^-29 radians */
+ int i_0; /* s 32 2^-31 semi-circles */
+ int c_rc; /* s 16 2^-5 meters */
+ int w; /* s 32 2^-31 semi-circles */
+ int omega_dot; /* s 24 2^-43 semi-circles / s */
+ int idot; /* s 14 2^-43 semi-circles / s */
+
+ int _rsvd1; /* 23 bits */
+ int _rsvd2; /* 24 bits */
+ int _rsvd3; /* 24 bits */
+ int _rsvd4; /* 16 bits */
+ int aodo; /* 8 bits Not sure it needs to be here ... */
+};
+
+struct gps_ephemeris {
+ int n_sv;
+ struct gps_ephemeris_sv svs[MAX_SV];
+};
+
+
+/* Reference position */
+struct gps_ref_pos { /* WSG84 ellipsoid */
+ double latitude; /* deg */
+ double longitude; /* deg */
+ double altitude; /* m above ellipsoid */
+};
+
+
+/* Reference time */
+struct gps_ref_time {
+ int wn; /* GPS week number */
+ double tow; /* in seconds */
+};
+
+
+/* All assist data */
+#define GPS_FIELD_IONOSPHERE (1<<0)
+#define GPS_FIELD_UTC (1<<1)
+#define GPS_FIELD_ALMANAC (1<<2)
+#define GPS_FIELD_EPHEMERIS (1<<3)
+#define GPS_FIELD_REFPOS (1<<4)
+#define GPS_FIELD_REFTIME (1<<5)
+
+struct gps_assist_data {
+ int fields;
+ struct gps_ionosphere_model ionosphere;
+ struct gps_utc_model utc;
+ struct gps_almanac almanac;
+ struct gps_ephemeris ephemeris;
+ struct gps_ref_pos ref_pos;
+ struct gps_ref_time ref_time;
+};
+
+
+/* GPS Subframe utility methods (see gps.c for details) */
+int gps_unpack_sf123(uint32_t *sf, struct gps_ephemeris_sv *eph);
+int gps_unpack_sf45_almanac(uint32_t *sf, struct gps_almanac_sv *alm);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPS_H__ */
+
diff --git a/rrlp-ephemeris/main.c b/rrlp-ephemeris/main.c
new file mode 100644
index 000000000..bb025a2ba
--- /dev/null
+++ b/rrlp-ephemeris/main.c
@@ -0,0 +1,99 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "gps.h"
+#include "ubx.h"
+#include "ubx-parse.h"
+#include "rrlp.h"
+
+static int
+do_ubx_read(struct gps_assist_data *gps, const char *filename)
+{
+ int rv, fd, i;
+ struct stat st;
+ void *buf;
+
+ /* Load file */
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ rv = fstat(fd, &st);
+ if (rv < 0) {
+ close(fd);
+ return -1;
+ }
+
+ buf = malloc(st.st_size);
+ if (!buf) {
+ close(fd);
+ return -1;
+ }
+
+ rv = read(fd, buf, st.st_size);
+ if (rv != st.st_size) {
+ free(buf);
+ close(fd);
+ return -1;
+ }
+
+ /* Parse each message */
+ for (i=0; i<st.st_size;) {
+ int rv;
+ rv = ubx_msg_dispatch(ubx_parse_dt, buf + i, st.st_size - i, gps);
+ if (rv < 0)
+ i++; /* Invalid message: try one byte later */
+ else
+ i += rv;
+ }
+
+ /* Done */
+ free(buf);
+ close(fd);
+
+ return 0;
+}
+
+static int
+do_rrlp(struct gps_assist_data *gps)
+{
+ struct rrlp_assist_req ar;
+ void *pdus[64];
+ int len[64];
+ int i, rv;
+
+ char *test = "\x28\x00\x80\x10\x01\x32\x00\x19\x4F\x07\x15\x04";
+
+ rrlp_decode_assistance_request(&ar, test, 12);
+ printf("%08x %016llx\n", ar.req_elems, (long long unsigned) ar.eph_svs);
+
+ ar.req_elems = -1;
+ ar.eph_svs = -1LL;
+ rv = rrlp_gps_assist_pdus(gps, &ar, pdus, len, 64);
+ printf("%d\n", rv);
+ for (i=0; i<rv; i++) {
+ printf("%p %d\n", pdus[i], len[i]);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ struct gps_assist_data gps;
+ int rv;
+
+ memset(&gps, 0x00, sizeof(gps));
+
+ rv = do_ubx_read(&gps, "data.ubx");
+
+ rv = do_rrlp(&gps);
+
+ return 0;
+}
+
diff --git a/rrlp-ephemeris/rrlp.c b/rrlp-ephemeris/rrlp.c
new file mode 100644
index 000000000..e60c3ab01
--- /dev/null
+++ b/rrlp-ephemeris/rrlp.c
@@ -0,0 +1,648 @@
+/*
+ * rrlp.c
+ *
+ * RRLP implementation
+ *
+ *
+ * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <errno.h>
+#include <math.h>
+
+#include "gps.h"
+#include "rrlp.h"
+
+#include <PDU.h>
+#include <GPS-AssistData.h>
+#include <NavigationModel.h>
+#include <IonosphericModel.h>
+#include <UTCModel.h>
+#include <Almanac.h>
+#include <RefLocation.h>
+#include <ReferenceTime.h>
+
+
+/* ------------------------------------------------------------------------ */
+/* RRLP Assistance request decoding */
+/* ---------------------------------------------------------------------{{{ */
+/* Decode and validate the assistance data request messages.
+ * See section 10.10 of
+ * . ETSI TS 149 031 V8.1.0 (2009-01)
+ * . 3GPP TS 49.031 version 8.1.0 Release 8
+ */
+
+/* Packed structure from 49.031 spec (RGA = Request GPS Assistance) */
+
+#define RRLP_RGA0_ALMANAC (1<<0)
+#define RRLP_RGA0_UTC_MODEL (1<<1)
+#define RRLP_RGA0_IONO_MODEL (1<<2)
+#define RRLP_RGA0_NAV_MODEL (1<<3)
+#define RRLP_RGA0_DGPS (1<<4)
+#define RRLP_RGA0_REF_LOC (1<<5)
+#define RRLP_RGA0_REF_TIME (1<<6)
+#define RRLP_RGA0_ACQ_ASSIST (1<<7)
+
+#define RRLP_RGA1_REALTIME_INT (1<<0)
+#define RRLP_RGA1_EPH_EXT (1<<1)
+#define RRLP_RGA1_EPH_EXT_CHECK (1<<2)
+
+struct rrlp_rga_hdr {
+ uint8_t items0;
+ uint8_t items1;
+} __attribute__((packed));
+
+struct rrlp_rga_eph_sv {
+ uint8_t sv_id; /* [7:6] reserved, [5:0] sv_id */
+ uint8_t iode; /* latest eph in the MS memory in hours */
+} __attribute__((packed));
+
+struct rrlp_rga_eph {
+ uint8_t wn_hi; /* [7:6] = wn[9:8] */
+ uint8_t wn_lo; /* wn[7:0] */
+ uint8_t toe; /* latest eph in the MS memory in hours */
+ uint8_t nsat_tmtoe; /* [7:4] nstat, [3:0] T-Toe limit */
+ struct rrlp_rga_eph_sv svs[0];
+} __attribute__((packed));
+
+struct rrlp_rga_eph_ext {
+ uint8_t validity; /* in 4 hours units */
+} __attribute__((packed));
+
+struct rrlp_rga_eph_ext_check {
+ /* weeks are in gps week modulo 4 */
+ uint8_t wn_begin_end; /* [7:4] begin, [3:0] end */
+ uint8_t tow_begin;
+ uint8_t tow_end;
+} __attribute__((packed));
+
+
+/* Parsing function */
+
+int
+rrlp_decode_assistance_request(
+ struct rrlp_assist_req *ar,
+ void *req, int req_len)
+{
+ struct rrlp_rga_hdr *hdr = NULL;
+ struct rrlp_rga_eph *eph = NULL;
+ struct rrlp_rga_eph_ext *eph_ext = NULL;
+ struct rrlp_rga_eph_ext_check *eph_ext_check = NULL;
+ int p = 0;
+
+ /* Reset */
+ ar->req_elems = 0;
+ ar->eph_svs = 0;
+
+ /* Parse message */
+ hdr = req;
+ p += sizeof(struct rrlp_rga_hdr);
+ if (p > req_len)
+ return -1;
+
+ if (hdr->items0 & RRLP_RGA0_NAV_MODEL) {
+ eph = req + p;
+ p += sizeof(struct rrlp_rga_eph);
+ if (p > req_len)
+ return -1;
+ p += (eph->nsat_tmtoe >> 4) * sizeof(struct rrlp_rga_eph_sv);
+ if (p > req_len)
+ return -1;
+ }
+
+ if (hdr->items1 & RRLP_RGA1_EPH_EXT) {
+ eph_ext = req + p;
+ p += sizeof(struct rrlp_rga_eph_ext);
+ if (p > req_len)
+ return -1;
+ }
+
+ if (hdr->items1 & RRLP_RGA1_EPH_EXT_CHECK) {
+ eph_ext_check = req + p;
+ p += sizeof(struct rrlp_rga_eph_ext_check);
+ if (p > req_len)
+ return -1;
+ }
+
+ if (p != req_len)
+ return -2; /* not all bytes consumed ??? */
+
+ /* Print a warning for unsupported requests */
+ if ((eph_ext != NULL) ||
+ (eph_ext_check != NULL) ||
+ (hdr->items0 & (RRLP_RGA0_DGPS | RRLP_RGA0_ACQ_ASSIST)) ||
+ (hdr->items1 & RRLP_RGA1_REALTIME_INT)) {
+ fprintf(stderr, "[w] Unsupported assistance data requested, ignored ...\n");
+ }
+
+ /* Copy the request */
+ if (hdr->items0 & RRLP_RGA0_ALMANAC)
+ ar->req_elems |= RRLP_AR_ALMANAC;
+
+ if (hdr->items0 & RRLP_RGA0_UTC_MODEL)
+ ar->req_elems |= RRLP_AR_UTC_MODEL;
+
+ if (hdr->items0 & RRLP_RGA0_IONO_MODEL)
+ ar->req_elems |= RRLP_AR_IONO_MODEL;
+
+ if (hdr->items0 & RRLP_RGA0_REF_LOC)
+ ar->req_elems |= RRLP_AR_REF_LOC;
+
+ if (hdr->items0 & RRLP_RGA0_REF_TIME)
+ ar->req_elems |= RRLP_AR_REF_TIME;
+
+ if (hdr->items0 & RRLP_RGA0_NAV_MODEL) {
+ int i, n_svs = eph->nsat_tmtoe >> 4;
+ ar->req_elems |= RRLP_AR_EPHEMERIS;
+ for (i=0; i<n_svs; i++)
+ ar->eph_svs |= (1ULL << (eph->svs[i].sv_id - 1));
+ }
+
+ return 0;
+}
+
+/* }}} */
+
+
+/* ------------------------------------------------------------------------ */
+/* RRLP elements fill */
+/* ---------------------------------------------------------------------{{{ */
+
+ /* Helpers */
+
+static void
+_ts_23_032_store_latitude(double lat, uint8_t *b)
+{
+ uint32_t x;
+ x = (uint32_t) floor(fabs(lat/90.0) * ((double)(1<<23)));
+ if (x >= (1<<23))
+ x = (1<<23) - 1;
+ if (lat < 0.0)
+ x |= (1<<23);
+ b[0] = (x >> 16) & 0xff;
+ b[1] = (x >> 8) & 0xff;
+ b[2] = x & 0xff;
+}
+
+static void
+_ts_23_032_store_longitude(double lon, uint8_t *b)
+{
+ int32_t x;
+ x = floor((lon/360.0) * ((double)(1<<24)));
+ if (x >= (1<<23))
+ x = 0x007fffff;
+ else if (x < -(1<<23))
+ x = 0x00800000;
+ b[0] = (x >> 16) & 0xff;
+ b[1] = (x >> 8) & 0xff;
+ b[2] = x & 0xff;
+}
+
+static void
+_ts_23_032_store_altitude(double alt, uint8_t *b)
+{
+ int alt_i = (int)fabs(alt);
+ b[0] = ((alt_i >> 8) & 0x7f) | (alt<0.0 ? 0x80 : 0x00);
+ b[1] = alt_i & 0xff;
+}
+
+
+ /* Fill methods */
+
+static void
+_rrlp_fill_navigation_model_element(
+ struct NavModelElement *rrlp_nme,
+ struct gps_ephemeris_sv *gps_eph_sv)
+{
+ struct UncompressedEphemeris *rrlp_eph;
+
+ rrlp_nme->satStatus.present = SatStatus_PR_newSatelliteAndModelUC;
+ rrlp_nme->satelliteID = gps_eph_sv->sv_id;
+
+ rrlp_eph = &rrlp_nme->satStatus.choice.newSatelliteAndModelUC;
+
+ rrlp_eph->ephemCodeOnL2 = gps_eph_sv->code_on_l2;
+ rrlp_eph->ephemURA = gps_eph_sv->sv_ura;
+ rrlp_eph->ephemSVhealth = gps_eph_sv->sv_health;
+ rrlp_eph->ephemIODC = gps_eph_sv->iodc;
+ rrlp_eph->ephemL2Pflag = gps_eph_sv->l2_p_flag;
+ rrlp_eph->ephemTgd = gps_eph_sv->t_gd;
+ rrlp_eph->ephemToc = gps_eph_sv->t_oc;
+ rrlp_eph->ephemAF2 = gps_eph_sv->a_f2;
+ rrlp_eph->ephemAF1 = gps_eph_sv->a_f1;
+ rrlp_eph->ephemAF0 = gps_eph_sv->a_f0;
+ rrlp_eph->ephemCrs = gps_eph_sv->c_rs;
+ rrlp_eph->ephemDeltaN = gps_eph_sv->delta_n;
+ rrlp_eph->ephemM0 = gps_eph_sv->m_0;
+ rrlp_eph->ephemCuc = gps_eph_sv->c_uc;
+ rrlp_eph->ephemE = gps_eph_sv->e;
+ rrlp_eph->ephemCus = gps_eph_sv->c_us;
+ rrlp_eph->ephemAPowerHalf = gps_eph_sv->a_powhalf;
+ rrlp_eph->ephemToe = gps_eph_sv->t_oe;
+ rrlp_eph->ephemFitFlag = gps_eph_sv->fit_flag;
+ rrlp_eph->ephemAODA = gps_eph_sv->aodo;
+ rrlp_eph->ephemCic = gps_eph_sv->c_ic;
+ rrlp_eph->ephemOmegaA0 = gps_eph_sv->omega_0;
+ rrlp_eph->ephemCis = gps_eph_sv->c_is;
+ rrlp_eph->ephemI0 = gps_eph_sv->i_0;
+ rrlp_eph->ephemCrc = gps_eph_sv->c_rc;
+ rrlp_eph->ephemW = gps_eph_sv->w;
+ rrlp_eph->ephemOmegaADot = gps_eph_sv->omega_dot;
+ rrlp_eph->ephemIDot = gps_eph_sv->idot;
+
+ rrlp_eph->ephemSF1Rsvd.reserved1 = gps_eph_sv->_rsvd1;
+ rrlp_eph->ephemSF1Rsvd.reserved2 = gps_eph_sv->_rsvd2;
+ rrlp_eph->ephemSF1Rsvd.reserved3 = gps_eph_sv->_rsvd3;
+ rrlp_eph->ephemSF1Rsvd.reserved4 = gps_eph_sv->_rsvd4;
+}
+
+static void
+_rrlp_fill_almanac_element(
+ struct AlmanacElement *rrlp_ae,
+ struct gps_almanac_sv *gps_alm_sv)
+{
+ rrlp_ae->satelliteID = gps_alm_sv->sv_id;
+
+ rrlp_ae->almanacE = gps_alm_sv->e;
+ rrlp_ae->alamanacToa = gps_alm_sv->t_oa;
+ rrlp_ae->almanacKsii = gps_alm_sv->ksii;
+ rrlp_ae->almanacOmegaDot = gps_alm_sv->omega_dot;
+ rrlp_ae->almanacSVhealth = gps_alm_sv->sv_health;
+ rrlp_ae->almanacAPowerHalf = gps_alm_sv->a_powhalf;
+ rrlp_ae->almanacOmega0 = gps_alm_sv->omega_0;
+ rrlp_ae->almanacW = gps_alm_sv->w;
+ rrlp_ae->almanacM0 = gps_alm_sv->m_0;
+ rrlp_ae->almanacAF0 = gps_alm_sv->a_f0;
+ rrlp_ae->almanacAF1 = gps_alm_sv->a_f1;
+
+}
+
+static void
+_rrlp_fill_ionospheric_model(
+ struct IonosphericModel *rrlp_iono,
+ struct gps_ionosphere_model *gps_iono)
+{
+ rrlp_iono->alfa0 = gps_iono->alpha_0;
+ rrlp_iono->alfa1 = gps_iono->alpha_1;
+ rrlp_iono->alfa2 = gps_iono->alpha_2;
+ rrlp_iono->alfa3 = gps_iono->alpha_3;
+ rrlp_iono->beta0 = gps_iono->beta_0;
+ rrlp_iono->beta1 = gps_iono->beta_1;
+ rrlp_iono->beta2 = gps_iono->beta_2;
+ rrlp_iono->beta3 = gps_iono->beta_3;
+}
+
+static void
+_rrlp_fill_utc_model(
+ struct UTCModel *rrlp_utc,
+ struct gps_utc_model *gps_utc)
+{
+ rrlp_utc->utcA1 = gps_utc->a1;
+ rrlp_utc->utcA0 = gps_utc->a0;
+ rrlp_utc->utcTot = gps_utc->t_ot;
+ rrlp_utc->utcWNt = gps_utc->wn_t & 0xff;
+ rrlp_utc->utcDeltaTls = gps_utc->delta_t_ls;
+ rrlp_utc->utcWNlsf = gps_utc->wn_lsf & 0xff;
+ rrlp_utc->utcDN = gps_utc->dn;
+ rrlp_utc->utcDeltaTlsf = gps_utc->delta_t_lsf;
+}
+
+/* }}} */
+
+
+/* ------------------------------------------------------------------------ */
+/* RRLP Assistance PDU Generation */
+/* ---------------------------------------------------------------------{{{ */
+
+struct PDU *
+_rrlp_create_gps_assist_pdu(int refnum, struct GPS_AssistData **o_gps_ad)
+{
+ struct PDU *pdu;
+ struct GPS_AssistData *gps_ad;
+
+ pdu = calloc(1, sizeof(*pdu));
+ if (!pdu)
+ return NULL;
+
+ gps_ad = calloc(1, sizeof(*gps_ad));
+ if (!gps_ad) {
+ free(pdu);
+ return NULL;
+ }
+
+ if (o_gps_ad)
+ *o_gps_ad = gps_ad;
+
+ pdu->referenceNumber = refnum;
+ pdu->component.present = RRLP_Component_PR_assistanceData;
+ pdu->component.choice.assistanceData.gps_AssistData = gps_ad;
+
+ return pdu;
+}
+
+static int
+_rrlp_add_ionospheric_model(
+ struct GPS_AssistData *rrlp_gps_ad,
+ struct gps_assist_data *gps_ad)
+{
+ struct IonosphericModel *rrlp_iono;
+
+ if (!(gps_ad->fields & GPS_FIELD_IONOSPHERE))
+ return -EINVAL;
+
+ rrlp_iono = calloc(1, sizeof(*rrlp_iono));
+ if (!rrlp_iono)
+ return -ENOMEM;
+ rrlp_gps_ad->controlHeader.ionosphericModel = rrlp_iono;
+
+ _rrlp_fill_ionospheric_model(rrlp_iono, &gps_ad->ionosphere);
+
+ return 0;
+}
+
+static int
+_rrlp_add_utc_model(
+ struct GPS_AssistData *rrlp_gps_ad,
+ struct gps_assist_data *gps_ad)
+{
+ struct UTCModel *rrlp_utc;
+
+ if (!(gps_ad->fields & GPS_FIELD_UTC))
+ return -EINVAL;
+
+ rrlp_utc = calloc(1, sizeof(*rrlp_utc));
+ if (!rrlp_utc)
+ return -ENOMEM;
+ rrlp_gps_ad->controlHeader.utcModel = rrlp_utc;
+
+ _rrlp_fill_utc_model(rrlp_utc, &gps_ad->utc);
+
+ return 0;
+}
+
+static int
+_rrlp_add_reference_location(
+ struct GPS_AssistData *rrlp_gps_ad,
+ struct gps_assist_data *gps_ad)
+{
+ struct RefLocation *rrlp_refloc;
+ uint8_t *b;
+
+ if (!(gps_ad->fields & GPS_FIELD_REFPOS))
+ return -EINVAL;
+
+ rrlp_refloc = calloc(1, sizeof(*rrlp_refloc));
+ if (!rrlp_refloc)
+ return -ENOMEM;
+ rrlp_gps_ad->controlHeader.refLocation = rrlp_refloc;
+
+ b = malloc(9);
+
+ b[0] = 0x80; /* Ellipsoid Point with altitude */
+ _ts_23_032_store_latitude(gps_ad->ref_pos.latitude, &b[1]);
+ _ts_23_032_store_longitude(gps_ad->ref_pos.longitude, &b[4]);
+ _ts_23_032_store_altitude(gps_ad->ref_pos.altitude, &b[7]);
+
+ rrlp_refloc->threeDLocation.buf = b;
+ rrlp_refloc->threeDLocation.size = 9;
+
+ return 0;
+}
+
+static int
+_rrlp_add_reference_time(
+ struct GPS_AssistData *rrlp_gps_ad,
+ struct gps_assist_data *gps_ad)
+{
+ struct ReferenceTime *rrlp_reftime;
+
+ if (!(gps_ad->fields & GPS_FIELD_REFTIME))
+ return -EINVAL;
+
+ rrlp_reftime = calloc(1, sizeof(*rrlp_reftime));
+ if (!rrlp_reftime)
+ return -ENOMEM;
+ rrlp_gps_ad->controlHeader.referenceTime = rrlp_reftime;
+
+ rrlp_reftime->gpsTime.gpsWeek = gps_ad->ref_time.wn & 0x3ff; /* 10b */
+ rrlp_reftime->gpsTime.gpsTOW23b =
+ ((int)floor(gps_ad->ref_time.tow / 0.08)) & 0x7fffff; /* 23b */
+
+ return 0;
+}
+
+static int
+_rrlp_add_almanac(
+ struct GPS_AssistData *rrlp_gps_ad,
+ struct gps_assist_data *gps_ad, int *start, int count)
+{
+ int i;
+ struct Almanac *rrlp_alm;
+ struct gps_almanac *gps_alm = &gps_ad->almanac;
+
+ if (!(gps_ad->fields & GPS_FIELD_ALMANAC))
+ return -EINVAL;
+
+ rrlp_alm = calloc(1, sizeof(*rrlp_alm));
+ if (!rrlp_alm)
+ return -ENOMEM;
+ rrlp_gps_ad->controlHeader.almanac = rrlp_alm;
+
+ rrlp_alm->alamanacWNa = gps_alm->wna;
+ if (count == -1)
+ count = gps_alm->n_sv - *start;
+ for (i=*start; (i<*start+count) && (i<gps_alm->n_sv); i++) {
+ struct AlmanacElement *ae;
+ ae = calloc(1, sizeof(*ae));
+ if (!ae)
+ return -ENOMEM;
+ _rrlp_fill_almanac_element(ae, &gps_alm->svs[i]);
+ ASN_SEQUENCE_ADD(&rrlp_alm->almanacList.list, ae);
+ }
+
+ *start = i;
+
+ return i < gps_alm->n_sv;
+}
+
+static int
+_rrlp_add_ephemeris(
+ struct GPS_AssistData *rrlp_gps_ad,
+ struct gps_assist_data *gps_ad, int *start, int count, uint64_t mask)
+{
+ int i, j;
+ struct NavigationModel *rrlp_nav;
+ struct gps_ephemeris *gps_eph = &gps_ad->ephemeris;
+
+ if (!(gps_ad->fields & GPS_FIELD_EPHEMERIS))
+ return -EINVAL;
+
+ rrlp_nav = calloc(1, sizeof(*rrlp_nav));
+ if (!rrlp_nav)
+ return -ENOMEM;
+ rrlp_gps_ad->controlHeader.navigationModel = rrlp_nav;
+
+ if (count == -1)
+ count = gps_eph->n_sv - *start;
+ for (i=*start,j=0; (j<count) && (i<gps_eph->n_sv); i++) {
+ if (!(mask & (1ULL<<(gps_eph->svs[i].sv_id-1))))
+ continue;
+ struct NavModelElement *nme;
+ nme = calloc(1, sizeof(*nme));
+ if (!nme)
+ return -ENOMEM;
+ _rrlp_fill_navigation_model_element(nme, &gps_eph->svs[i]);
+ ASN_SEQUENCE_ADD(&rrlp_nav->navModelList.list, nme);
+ j++;
+ }
+
+ *start = i;
+
+ return i < gps_eph->n_sv;
+}
+
+
+#define MAX_PDUS 64
+
+int
+rrlp_gps_assist_pdus(
+ struct gps_assist_data *gps_ad, struct rrlp_assist_req *req,
+ void **o_pdu, int *o_len, int o_max_pdus)
+{
+ struct PDU *lst_pdu[MAX_PDUS];
+ int lst_cnt = 0;
+
+ struct PDU *rrlp_pdu = NULL;
+ struct GPS_AssistData *rrlp_gps_ad = NULL;
+ uint32_t re = req->req_elems;
+ int i, rv = 0;
+
+ /* IonosphericModel, UTCModel, RefLocation, ReferenceTime */
+ if (re & (RRLP_AR_IONO_MODEL |
+ RRLP_AR_UTC_MODEL |
+ RRLP_AR_REF_TIME |
+ RRLP_AR_REF_LOC))
+ {
+ int pdu_has_data = 0;
+
+ rrlp_pdu = _rrlp_create_gps_assist_pdu(1, &rrlp_gps_ad);
+ if (!rrlp_pdu) {
+ rv = -ENOMEM;
+ goto error;
+ }
+
+ if (re & RRLP_AR_IONO_MODEL)
+ if (!_rrlp_add_ionospheric_model(rrlp_gps_ad, gps_ad))
+ pdu_has_data = 1;
+
+ if (re & RRLP_AR_UTC_MODEL)
+ if (!_rrlp_add_utc_model(rrlp_gps_ad, gps_ad))
+ pdu_has_data = 1;
+
+ if (re & RRLP_AR_REF_TIME)
+ if (!_rrlp_add_reference_time(rrlp_gps_ad, gps_ad))
+ pdu_has_data = 1;
+
+ if (re & RRLP_AR_REF_LOC)
+ if (!_rrlp_add_reference_location(rrlp_gps_ad, gps_ad))
+ pdu_has_data = 1;
+
+ if (pdu_has_data) {
+ lst_pdu[lst_cnt++] = rrlp_pdu;
+ rrlp_pdu = NULL;
+ }
+ }
+
+ /* Almanac */
+ if (re & RRLP_AR_ALMANAC) {
+ i = 0;
+ do {
+ if (!(gps_ad->fields & GPS_FIELD_ALMANAC))
+ break;
+
+ if (!rrlp_pdu) {
+ rrlp_pdu = _rrlp_create_gps_assist_pdu(1, &rrlp_gps_ad);
+ if (!rrlp_pdu) {
+ rv = -ENOMEM;
+ goto error;
+ }
+ }
+
+ rv = _rrlp_add_almanac(rrlp_gps_ad, gps_ad, &i, 10);
+ if (rv < 0)
+ goto error;
+
+ lst_pdu[lst_cnt++] = rrlp_pdu;
+ rrlp_pdu = NULL;
+ } while (rv);
+ }
+
+ /* Ephemeris */
+ if (re & RRLP_AR_EPHEMERIS) {
+ i = 0;
+ do {
+ if (!(gps_ad->fields & GPS_FIELD_EPHEMERIS))
+ break;
+
+ if (!rrlp_pdu) {
+ rrlp_pdu = _rrlp_create_gps_assist_pdu(1, &rrlp_gps_ad);
+ if (!rrlp_pdu) {
+ rv = -ENOMEM;
+ goto error;
+ }
+ }
+
+ rv = _rrlp_add_ephemeris(rrlp_gps_ad, gps_ad, &i, 2, req->eph_svs);
+
+ lst_pdu[lst_cnt++] = rrlp_pdu;
+ rrlp_pdu = NULL;
+
+ } while (rv);
+ }
+
+ /* Serialize & Release all PDUs */
+ for (i=0; i<lst_cnt && i<o_max_pdus; i++) {
+ /* Pseudo segmentation flags */
+ MoreAssDataToBeSent_t *mad = calloc(1, sizeof(*mad));
+ *mad = (i == (lst_cnt-1)) ?
+ MoreAssDataToBeSent_noMoreMessages :
+ MoreAssDataToBeSent_moreMessagesOnTheWay;
+ lst_pdu[i]->component.choice.assistanceData.moreAssDataToBeSent = mad;
+
+ /* Serialization */
+ // asn_fprint(stdout, &asn_DEF_PDU, lst_pdu[i]);
+ rv = uper_encode_to_new_buffer(&asn_DEF_PDU, NULL, lst_pdu[i], &o_pdu[i]);
+ if (rv < 0)
+ goto error;
+ o_len[i] = rv;
+ }
+
+ rv = lst_cnt;
+
+ /* Release ASN.1 objects */
+error:
+ if (rrlp_pdu)
+ asn_DEF_PDU.free_struct(&asn_DEF_PDU, (void*)rrlp_pdu, 0);
+
+ for (i=0; i<lst_cnt; i++)
+ asn_DEF_PDU.free_struct(&asn_DEF_PDU, lst_pdu[i], 0);
+
+ return rv;
+}
+
+/* }}} */
+
diff --git a/rrlp-ephemeris/rrlp.h b/rrlp-ephemeris/rrlp.h
new file mode 100644
index 000000000..a5e4344e5
--- /dev/null
+++ b/rrlp-ephemeris/rrlp.h
@@ -0,0 +1,64 @@
+/*
+ * rrlp.h
+ *
+ * RRLP Header
+ *
+ *
+ * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __RRLP_H__
+#define __RRLP_H__
+
+#include <stdint.h>
+
+#include "gps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Our internal simplified structure for requests */
+
+#define RRLP_AR_REF_LOC (1<<0)
+#define RRLP_AR_REF_TIME (1<<1)
+#define RRLP_AR_UTC_MODEL (1<<2)
+#define RRLP_AR_IONO_MODEL (1<<3)
+#define RRLP_AR_ALMANAC (1<<4)
+#define RRLP_AR_EPHEMERIS (1<<5)
+
+struct rrlp_assist_req {
+ uint32_t req_elems;
+ uint64_t eph_svs;
+};
+
+
+/* Methods */
+int rrlp_decode_assistance_request(struct rrlp_assist_req *ar,
+ void *req, int req_len);
+
+int rrlp_gps_assist_pdus(
+ struct gps_assist_data *gps_ad, struct rrlp_assist_req *req,
+ void **o_pdu, int *o_len, int o_max_pdus);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RRLP_H__ */
+
diff --git a/rrlp-ephemeris/ubx-parse.c b/rrlp-ephemeris/ubx-parse.c
new file mode 100644
index 000000000..c3d0f70d7
--- /dev/null
+++ b/rrlp-ephemeris/ubx-parse.c
@@ -0,0 +1,177 @@
+/*
+ * ubx-parse.c
+ *
+ * Implementation of parsing code converting UBX messages to GPS assist
+ * data
+ *
+ *
+ * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#include "gps.h"
+#include "ubx.h"
+#include "ubx-parse.h"
+
+
+/* Helpers */
+
+static int
+float_to_fixedpoint(float f, int sf)
+{
+ if (sf < 0) {
+ while (sf++ < 0)
+ f *= 2.0f;
+ } else {
+ while (sf-- > 0)
+ f *= 0.5f;
+ }
+
+ return (int)f;
+}
+
+static inline int
+double_to_fixedpoint(double d, int sf)
+{
+ if (sf < 0) {
+ while (sf++ < 0)
+ d *= 2.0;
+ } else {
+ while (sf-- > 0)
+ d *= 0.5;
+ }
+
+ return (int)d;
+}
+
+
+/* UBX message parsing to fill gps assist data */
+
+static void
+_ubx_msg_parse_nav_posllh(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
+{
+ struct ubx_nav_posllh *nav_posllh = pl;
+ struct gps_assist_data *gps = ud;
+
+ //printf("[.] NAV_POSLLH\n");
+
+ gps->fields |= GPS_FIELD_REFPOS;
+
+ gps->ref_pos.latitude = (double)(nav_posllh->lat) * 1e-7;
+ gps->ref_pos.longitude = (double)(nav_posllh->lon) * 1e-7;
+ gps->ref_pos.altitude = (double)(nav_posllh->height) * 1e-3;
+}
+
+static void
+_ubx_msg_parse_aid_ini(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
+{
+ struct ubx_aid_ini *aid_ini = pl;
+ struct gps_assist_data *gps = ud;
+
+ //printf("[.] AID_INI\n");
+
+ /* Extract info for "Reference Time" */
+ gps->fields |= GPS_FIELD_REFTIME;
+
+ gps->ref_time.wn = aid_ini->wn;
+ gps->ref_time.tow = (double)aid_ini->tow * 1e-3;
+
+ // FIXME: We could extract ref position as well but we need it in
+ // WGS84 geodetic coordinates and it's provided as ecef, so
+ // we need a lot of math ...
+}
+
+static void
+_ubx_msg_parse_aid_hui(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
+{
+ struct ubx_aid_hui *aid_hui = pl;
+ struct gps_assist_data *gps = ud;
+
+ //printf("[.] AID_HUI\n");
+
+ if (aid_hui->flags & 0x2) { /* UTC parameters valid */
+ struct gps_utc_model *utc = &gps->utc;
+
+ gps->fields |= GPS_FIELD_UTC;
+
+ utc->a0 = double_to_fixedpoint(aid_hui->utc_a0, -30);
+ utc->a1 = double_to_fixedpoint(aid_hui->utc_a1, -50);
+ utc->delta_t_ls = aid_hui->utc_ls;
+ utc->t_ot = aid_hui->utc_tot >> 12;
+ utc->wn_t = aid_hui->utc_wnt;
+ utc->wn_lsf = aid_hui->utc_wnf;
+ utc->dn = aid_hui->utc_dn;
+ utc->delta_t_lsf = aid_hui->utc_lsf;
+ }
+
+ if (aid_hui->flags & 0x04) { /* Klobuchar parameters valid */
+ struct gps_ionosphere_model *iono = &gps->ionosphere;
+
+ gps->fields |= GPS_FIELD_IONOSPHERE;
+
+ iono->alpha_0 = float_to_fixedpoint(aid_hui->klob_a0, -30);
+ iono->alpha_1 = float_to_fixedpoint(aid_hui->klob_a1, -27);
+ iono->alpha_2 = float_to_fixedpoint(aid_hui->klob_a2, -24);
+ iono->alpha_3 = float_to_fixedpoint(aid_hui->klob_a3, -24);
+ iono->beta_0 = float_to_fixedpoint(aid_hui->klob_b0, 11);
+ iono->beta_1 = float_to_fixedpoint(aid_hui->klob_b1, 14);
+ iono->beta_2 = float_to_fixedpoint(aid_hui->klob_b2, 16);
+ iono->beta_3 = float_to_fixedpoint(aid_hui->klob_b3, 16);
+ }
+}
+
+static void
+_ubx_msg_parse_aid_alm(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
+{
+ struct ubx_aid_alm *aid_alm = pl;
+ struct gps_assist_data *gps = ud;
+
+ //printf("[.] AID_ALM %d - %d\n", aid_alm->sv_id, aid_alm->gps_week);
+
+ if (aid_alm->gps_week) {
+ gps->fields |= GPS_FIELD_ALMANAC;
+ gps->almanac.wna = aid_alm->gps_week & 0xff;
+ gps_unpack_sf45_almanac(aid_alm->alm_words, &gps->almanac.svs[gps->almanac.n_sv++]);
+ }
+}
+
+static void
+_ubx_msg_parse_aid_eph(struct ubx_hdr *hdr, void *pl, int pl_len, void *ud)
+{
+ struct ubx_aid_eph *aid_eph = pl;
+ struct gps_assist_data *gps = ud;
+
+ //printf("[.] AID_EPH %d - %s\n", aid_eph->sv_id, aid_eph->present ? "present" : "not present");
+
+ if (aid_eph->present) {
+ int i = gps->ephemeris.n_sv++;
+ gps->fields |= GPS_FIELD_EPHEMERIS;
+ gps->ephemeris.svs[i].sv_id = aid_eph->sv_id;
+ gps_unpack_sf123(aid_eph->eph_words, &gps->ephemeris.svs[i]);
+ }
+}
+
+
+/* Dispatch table */
+struct ubx_dispatch_entry ubx_parse_dt[] = {
+ UBX_DISPATCH(NAV, POSLLH, _ubx_msg_parse_nav_posllh),
+ UBX_DISPATCH(AID, INI, _ubx_msg_parse_aid_ini),
+ UBX_DISPATCH(AID, HUI, _ubx_msg_parse_aid_hui),
+ UBX_DISPATCH(AID, ALM, _ubx_msg_parse_aid_alm),
+ UBX_DISPATCH(AID, EPH, _ubx_msg_parse_aid_eph),
+};
+
diff --git a/rrlp-ephemeris/ubx-parse.h b/rrlp-ephemeris/ubx-parse.h
new file mode 100644
index 000000000..621475d65
--- /dev/null
+++ b/rrlp-ephemeris/ubx-parse.h
@@ -0,0 +1,45 @@
+/*
+ * ubx-parse.h
+ *
+ * Header for parsing code converting UBX messages to GPS assist data
+ *
+ *
+ * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __UBX_PARSE_H__
+#define __UBX_PARSE_H__
+
+
+#include "gps.h"
+#include "ubx.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Dispatch table */
+extern struct ubx_dispatch_entry ubx_parse_dt[];
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UBX_PARSE_H__ */
+
diff --git a/rrlp-ephemeris/ubx.c b/rrlp-ephemeris/ubx.c
new file mode 100644
index 000000000..83dd1f055
--- /dev/null
+++ b/rrlp-ephemeris/ubx.c
@@ -0,0 +1,81 @@
+/*
+ * ubx.c
+ *
+ * Implementation of generic UBX helpers
+ *
+ *
+ * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include "ubx.h"
+
+
+static void
+ubx_checksum(uint8_t *data, int len, uint8_t *cksum)
+{
+ int i;
+ uint8_t ck0 = 0, ck1 = 0;
+ for (i=0; i<len; i++) {
+ ck0 += data[i];
+ ck1 += ck0;
+ }
+ cksum[0] = ck0;
+ cksum[1] = ck1;
+}
+
+
+static ubx_msg_handler_t
+ubx_find_handler(struct ubx_dispatch_entry *dt, uint8_t msg_class, uint8_t msg_id)
+{
+ while (dt->handler) {
+ if ((dt->msg_class == msg_class) && (dt->msg_id == msg_id))
+ return dt->handler;
+ dt++;
+ }
+ return NULL;
+}
+
+
+int
+ubx_msg_dispatch(struct ubx_dispatch_entry *dt,
+ void *msg, int len, void *userdata)
+{
+ struct ubx_hdr *hdr = msg;
+ uint8_t cksum[2], *cksum_ptr;
+ ubx_msg_handler_t h;
+
+ if ((hdr->sync[0] != UBX_SYNC0) || (hdr->sync[1] != UBX_SYNC1)) {
+ fprintf(stderr, "[!] Invalid sync bytes\n");
+ return -1;
+ }
+
+ ubx_checksum(msg + 2, sizeof(struct ubx_hdr) + hdr->payload_len - 2, cksum);
+ cksum_ptr = msg + (sizeof(struct ubx_hdr) + hdr->payload_len);
+ if ((cksum_ptr[0] != cksum[0]) || (cksum_ptr[1] != cksum[1])) {
+ fprintf(stderr, "[!] Invalid checksum\n");
+ return -1;
+ }
+
+ h = ubx_find_handler(dt, hdr->msg_class, hdr->msg_id);
+ if (h)
+ h(hdr, msg + sizeof(struct ubx_hdr), hdr->payload_len, userdata);
+
+ return sizeof(struct ubx_hdr) + hdr->payload_len + 2;
+}
+
diff --git a/rrlp-ephemeris/ubx.h b/rrlp-ephemeris/ubx.h
new file mode 100644
index 000000000..826438658
--- /dev/null
+++ b/rrlp-ephemeris/ubx.h
@@ -0,0 +1,232 @@
+/*
+ * ubx.h
+ *
+ * Header for UBX related stuff
+ *
+ *
+ * Copyright (C) 2009 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __UBX_H__
+#define __UBX_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/* Constants used in UBX */
+
+ /* Sync bytes (two first bytes of each message) */
+#define UBX_SYNC0 0xb5
+#define UBX_SYNC1 0x62
+
+ /* UBX messages classes */
+#define UBX_CLASS_NAV 0x01
+#define UBX_CLASS_RXM 0x02
+#define UBX_CLASS_INF 0x04
+#define UBX_CLASS_ACK 0x05
+#define UBX_CLASS_CFG 0x06
+#define UBX_CLASS_UPD 0x09
+#define UBX_CLASS_MON 0x0a
+#define UBX_CLASS_AID 0x0b
+#define UBX_CLASS_TIM 0x0d
+
+ /* UBX messages type ID (by class) */
+#define UBX_NAV_POSECEF 0x01
+#define UBX_NAV_POSLLH 0x02
+#define UBX_NAV_STATUS 0x03
+#define UBX_NAV_DOP 0x04
+#define UBX_NAV_SOL 0x06
+#define UBX_NAV_POSUTM 0x08
+#define UBX_NAV_VELECEF 0x11
+#define UBX_NAV_VELNED 0x12
+#define UBX_NAV_TIMEGPS 0x20
+#define UBX_NAV_TIMEUTC 0x21
+#define UBX_NAV_CLOCK 0x22
+#define UBX_NAV_SVINFO 0x30
+#define UBX_NAV_DGPS 0x31
+#define UBX_NAV_SBAS 0x32
+#define UBX_NAV_EKFSTATUS 0x40
+
+#define UBX_RXM_RAW 0x10
+#define UBX_RXM_SFRB 0x11
+#define UBX_RXM_SVSI 0x20
+#define UBX_RXM_SVSI_GPS 0x20
+#define UBX_RXM_ALM 0x30
+#define UBX_RXM_EPH 0x31
+#define UBX_RXM_POSREQ 0x40
+
+#define UBX_INF_ERROR 0x00
+#define UBX_INF_WARNING 0x01
+#define UBX_INF_NOTICE 0x02
+#define UBX_INF_TEST 0x03
+#define UBX_INF_DEBUG 0x04
+#define UBX_INF_USER 0x07
+
+#define UBX_ACK_NAK 0x00
+#define UBX_ACK_ACK 0x01
+
+#define UBX_CFG_PRT 0x00
+#define UBX_CFG_USB 0x1b
+#define UBX_CFG_MSG 0x01
+#define UBX_CFG_NMEA 0x17
+#define UBX_CFG_RATE 0x08
+#define UBX_CFG_CFG 0x09
+#define UBX_CFG_TP 0x07
+#define UBX_CFG_NAV2 0x1a
+#define UBX_CFG_DAT 0x06
+#define UBX_CFG_INF 0x02
+#define UBX_CFG_RST 0x04
+#define UBX_CFG_RXM 0x11
+#define UBX_CFG_ANT 0x13
+#define UBX_CFG_FXN 0x0e
+#define UBX_CFG_SBAS 0x16
+#define UBX_CFG_LIC 0x80
+#define UBX_CFG_TM 0x10
+#define UBX_CFG_TM2 0x19
+#define UBX_CFG_TMODE 0x1d
+#define UBX_CFG_EKF 0x12
+
+#define UBX_UPD_DOWNL 0x01
+#define UBX_UPD_UPLOAD 0x02
+#define UBX_UPD_EXEC 0x03
+#define UBX_UPD_MEMCPY 0x04
+
+#define UBX_MON_SCHD 0x01
+#define UBX_MON_IO 0x02
+#define UBX_MON_IPC 0x03
+#define UBX_MON_VER 0x04
+#define UBX_MON_EXCEPT 0x05
+#define UBX_MON_MSGPP 0x06
+#define UBX_MON_RXBUF 0x07
+#define UBX_MON_TXBUF 0x08
+#define UBX_MON_HW 0x09
+#define UBX_MON_USB 0x0a
+
+#define UBX_AID_REQ 0x00
+#define UBX_AID_INI 0x01
+#define UBX_AID_HUI 0x02
+#define UBX_AID_DATA 0x10
+#define UBX_AID_ALM 0x30
+#define UBX_AID_EPH 0x31
+
+#define UBX_TIM_TP 0x01
+#define UBX_TIM_TM 0x02
+#define UBX_TIM_TM2 0x03
+#define UBX_TIM_SVIN 0x04
+
+
+/* Header */
+struct ubx_hdr {
+ uint8_t sync[2];
+ uint8_t msg_class;
+ uint8_t msg_id;
+ uint16_t payload_len;
+} __attribute__((packed));
+
+
+/* Payload formats (some of them) */
+struct ubx_nav_posllh {
+ uint32_t itow;
+ int32_t lon; /* scaling 1e-7 */
+ int32_t lat; /* scaling 1e-7 */
+ int32_t height;/* mm */
+ int32_t hsl; /* mm */
+ uint32_t hacc; /* mm */
+ uint32_t vacc; /* mm */
+} __attribute__((packed));
+
+struct ubx_aid_ini {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ uint32_t posacc;
+ uint16_t tm_cfg;
+ uint16_t wn;
+ uint32_t tow;
+ int32_t tow_ns;
+ uint32_t tacc_ms;
+ uint32_t tacc_ns;
+ int32_t clkd;
+ uint32_t clkdacc;
+ uint32_t flags;
+} __attribute__((packed));
+
+struct ubx_aid_hui {
+ uint32_t health;
+ double utc_a1;
+ double utc_a0;
+ int32_t utc_tot;
+ int16_t utc_wnt;
+ int16_t utc_ls;
+ int16_t utc_wnf;
+ int16_t utc_dn;
+ int16_t utc_lsf;
+ int16_t utc_spare;
+ float klob_a0;
+ float klob_a1;
+ float klob_a2;
+ float klob_a3;
+ float klob_b0;
+ float klob_b1;
+ float klob_b2;
+ float klob_b3;
+ uint32_t flags;
+} __attribute__((packed));
+
+struct ubx_aid_alm {
+ uint32_t sv_id;
+ uint32_t gps_week;
+ uint32_t alm_words[8]; /* Present only if 'gps_week' != 0 */
+} __attribute__((packed));
+
+struct ubx_aid_eph {
+ uint32_t sv_id;
+ uint32_t present;
+ uint32_t eph_words[24]; /* Present only if 'present' != 0 */
+} __attribute__((packed));
+
+
+/* Message handler */
+typedef void (*ubx_msg_handler_t)(
+ struct ubx_hdr *hdr, void *payload, int payload_len, void *userdata);
+
+struct ubx_dispatch_entry {
+ uint8_t msg_class;
+ uint8_t msg_id;
+ ubx_msg_handler_t handler;
+};
+
+#define UBX_DISPATCH(kls,id,hdl) { \
+ .msg_class = UBX_CLASS_ ## kls , \
+ .msg_id = UBX_ ## kls ## _ ## id, \
+ .handler = (hdl), \
+}
+
+
+/* Methods */
+int ubx_msg_dispatch(struct ubx_dispatch_entry *dt,
+ void *msg, int len, void *userdata);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UBX_H__ */
+
diff --git a/wireshark/abis_oml.patch b/wireshark/abis_oml.patch
index 1b2439c86..9f06b4d82 100644
--- a/wireshark/abis_oml.patch
+++ b/wireshark/abis_oml.patch
@@ -10,14 +10,16 @@ Index: wireshark/epan/dissectors/Makefile.common
packet-gsm_ipa.c \
packet-gsm_bsslap.c \
packet-gsm_bssmap_le.c \
-Index: wireshark/epan/dissectors/packet-gsm_abis_oml.c
-===================================================================
+diff --git a/epan/dissectors/packet-gsm_abis_oml.c b/epan/dissectors/packet-gsm_abis_oml.c
+new file mode 100644
+index 0000000..2de9dca
--- /dev/null
-+++ wireshark/epan/dissectors/packet-gsm_abis_oml.c
-@@ -0,0 +1,1365 @@
++++ b/epan/dissectors/packet-gsm_abis_oml.c
+@@ -0,0 +1,1382 @@
+/* packet-abis_oml.c
+ * Routines for packet dissection of GSM A-bis over IP (3GPP TS 12.21)
+ * Copyright 2009 by Harald Welte <laforge@gnumonks.org>
++ * Copyright 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * based on A-bis OML code in OpenBSC
+ *
+ * $Id$
@@ -50,6 +52,7 @@ Index: wireshark/epan/dissectors/packet-gsm_abis_oml.c
+#include <epan/packet.h>
+#include <epan/emem.h>
+#include <epan/lapd_sapi.h>
++#include <epan/prefs.h>
+
+#include "packet-gsm_abis_oml.h"
+#include "packet-gsm_a_common.h"
@@ -128,6 +131,9 @@ Index: wireshark/epan/dissectors/packet-gsm_abis_oml.c
+static int ett_oml_fom = -1;
+static int ett_oml_fom_att = -1;
+
++/* Decode things as nanoBTS traces */
++static gboolean global_oml_use_nano_bts = FALSE;
++
+static proto_tree *top_tree;
+
+/* TS 12.21 Chapter 8.1 / TS 08.59 */
@@ -1053,6 +1059,9 @@ Index: wireshark/epan/dissectors/packet-gsm_abis_oml.c
+}
+
+void
++proto_reg_handoff_abis_oml(void);
++
++void
+proto_register_abis_oml(void)
+{
+ static hf_register_info hf[] = {
@@ -1362,6 +1371,8 @@ Index: wireshark/epan/dissectors/packet-gsm_abis_oml.c
+ &ett_oml_fom_att,
+ };
+
++ module_t *oml_module;
++
+ proto_abis_oml = proto_register_protocol("GSM A-bis OML", "OML",
+ "gsm_abis_oml");
+
@@ -1370,6 +1381,13 @@ Index: wireshark/epan/dissectors/packet-gsm_abis_oml.c
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("gsm_abis_oml", dissect_abis_oml, proto_abis_oml);
++
++
++ oml_module = prefs_register_protocol(proto_abis_oml, proto_reg_handoff_abis_oml);
++ prefs_register_bool_preference(oml_module, "use_ipaccess_oml",
++ "Use nanoBTS definitions",
++ "Use ipaccess nanoBTS specific definitions for OML",
++ &global_oml_use_nano_bts);
+}
+
+void
@@ -2167,6 +2185,7 @@ Index: wireshark/epan/dissectors/packet-gsm_abis_oml.h
+ [NM_ATT_IPACC_CODING_SCHEMES] = { TLV_TYPE_TL16V, 0 },
+ [NM_ATT_IPACC_RLC_CFG_2] = { TLV_TYPE_TL16V, 0 },
+ [NM_ATT_IPACC_RLC_CFG_3] = { TLV_TYPE_TL16V, 0 },
++ [NM_ATT_IPACC_FILE_DATA] = { TLV_TYPE_TL16V, 0 },
+ },
+};
+