diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-01-07 11:42:54 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-01-07 11:42:54 +0100 |
commit | 7ea3caeb81b9db57b5e56ad714a4a704d242bb1b (patch) | |
tree | 8e87652980d2920334d0679e4f925fbc02fff55a | |
parent | 766f0422badf1a0484635c3a3cee15cef1780edb (diff) | |
parent | ef24dff2a22c907f08a24b19773dde5ce20ba5d6 (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
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 Binary files differnew file mode 100644 index 000000000..07cdddcd9 --- /dev/null +++ b/rrlp-ephemeris/data.ubx 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 }, + }, +}; + |