diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-04-30 14:29:56 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-04-30 14:29:56 +0200 |
commit | e562502e8d35356f3183a39ff6aad200d11a77bb (patch) | |
tree | 31d24174740b1b104a7c13b0086cbee4fecb90c5 | |
parent | e9dd9b047590064eec1c618475ece7f9627e0312 (diff) | |
parent | 074c9f904cb5e4f6ab014d76e4abc079c16fc5d7 (diff) |
Merge commit '074c9f904cb5e4f6ab014d76e4abc079c16fc5d7'
-rw-r--r-- | libosmocore/.gitignore | 5 | ||||
-rw-r--r-- | libosmocore/include/osmocore/Makefile.am | 2 | ||||
-rw-r--r-- | libosmocore/include/osmocore/gsm0808.h | 41 | ||||
-rw-r--r-- | libosmocore/include/osmocore/gsm48.h | 4 | ||||
-rw-r--r-- | libosmocore/include/osmocore/gsm_utils.h | 7 | ||||
-rw-r--r-- | libosmocore/include/osmocore/msgb.h | 20 | ||||
-rw-r--r-- | libosmocore/include/osmocore/protocol/gsm_04_08.h | 1 | ||||
-rw-r--r-- | libosmocore/include/osmocore/protocol/gsm_08_08.h | 303 | ||||
-rw-r--r-- | libosmocore/include/osmocore/write_queue.h | 1 | ||||
-rw-r--r-- | libosmocore/src/Makefile.am | 2 | ||||
-rw-r--r-- | libosmocore/src/gsm0808.c | 295 | ||||
-rw-r--r-- | libosmocore/src/gsm48.c | 48 | ||||
-rw-r--r-- | libosmocore/src/gsm48_ie.c | 2 | ||||
-rw-r--r-- | libosmocore/src/logging.c | 27 | ||||
-rw-r--r-- | libosmocore/src/msgb.c | 3 | ||||
-rw-r--r-- | libosmocore/src/select.c | 3 | ||||
-rw-r--r-- | libosmocore/src/write_queue.c | 3 |
17 files changed, 742 insertions, 25 deletions
diff --git a/libosmocore/.gitignore b/libosmocore/.gitignore index d61cdc589..06904fa09 100644 --- a/libosmocore/.gitignore +++ b/libosmocore/.gitignore @@ -7,6 +7,7 @@ Makefile.in *.la *.pc aclocal.m4 +m4/*.m4 autom4te.cache config.h* config.sub @@ -23,3 +24,7 @@ libtool .tarball-version .version + +tests/sms/sms_test +tests/timer/timer_test + diff --git a/libosmocore/include/osmocore/Makefile.am b/libosmocore/include/osmocore/Makefile.am index 1c3a33f33..56f926bcf 100644 --- a/libosmocore/include/osmocore/Makefile.am +++ b/libosmocore/include/osmocore/Makefile.am @@ -1,7 +1,7 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h \ tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \ gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \ - gsm48_ie.h logging.h + gsm48_ie.h logging.h gsm0808.h if ENABLE_TALLOC osmocore_HEADERS += talloc.h diff --git a/libosmocore/include/osmocore/gsm0808.h b/libosmocore/include/osmocore/gsm0808.h new file mode 100644 index 000000000..a40713f77 --- /dev/null +++ b/libosmocore/include/osmocore/gsm0808.h @@ -0,0 +1,41 @@ +/* (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org> + * (C) 2009,2010 by On-Waves + * 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. + * + */ +#ifndef OSMOCORE_GSM0808_H +#define OSMOCORE_GSM0808_H + +#include "tlv.h" + +struct msgb; + +struct msgb *gsm0808_create_layer3(struct msgb *msg, uint16_t netcode, uint16_t countrycode, int lac, int ci); +struct msgb *gsm0808_create_reset(void); +struct msgb *gsm0808_create_clear_complete(void); +struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id); +struct msgb *gsm0808_create_cipher_reject(uint8_t cause); +struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark, uint8_t length); +struct msgb *gsm0808_create_sapi_reject(uint8_t link_id); +struct msgb *gsm0808_create_assignment_completed(struct gsm_lchan *lchan, uint8_t rr_cause, + uint8_t chosen_channel, uint8_t encr_alg_id, + uint8_t speech_mode); +struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause); + +const struct tlv_definition *gsm0808_att_tlvdef(); + +#endif diff --git a/libosmocore/include/osmocore/gsm48.h b/libosmocore/include/osmocore/gsm48.h index 1e963573c..e3a1defa7 100644 --- a/libosmocore/include/osmocore/gsm48.h +++ b/libosmocore/include/osmocore/gsm48.h @@ -14,4 +14,8 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc, int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi); int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi); +/* Convert Mobile Identity (10.5.1.4) to string */ +int gsm48_mi_to_string(char *string, const int str_len, + const uint8_t *mi, const int mi_len); + #endif diff --git a/libosmocore/include/osmocore/gsm_utils.h b/libosmocore/include/osmocore/gsm_utils.h index c87e967bd..195e865ca 100644 --- a/libosmocore/include/osmocore/gsm_utils.h +++ b/libosmocore/include/osmocore/gsm_utils.h @@ -27,6 +27,13 @@ #include <stdint.h> +#define ADD_MODULO(sum, delta, modulo) do { \ + if ((sum += delta) >= modulo) \ + sum -= modulo; \ + } while (0) + +#define GSM_MAX_FN (26*51*2048) + struct gsm_time { uint32_t fn; /* FN count */ uint16_t t1; /* FN div (26*51) */ diff --git a/libosmocore/include/osmocore/msgb.h b/libosmocore/include/osmocore/msgb.h index 31db71942..2841dc56e 100644 --- a/libosmocore/include/osmocore/msgb.h +++ b/libosmocore/include/osmocore/msgb.h @@ -23,15 +23,11 @@ #include <stdint.h> #include "linuxlist.h" -struct bts_link; - struct msgb { struct llist_head list; - /* ptr to the physical E1 link to the BTS(s) */ - struct gsm_bts_link *bts_link; - /* Part of which TRX logical channel we were received / transmitted */ + /* FIXME: move them into the control buffer */ struct gsm_bts_trx *trx; struct gsm_lchan *lchan; @@ -41,17 +37,11 @@ struct msgb { unsigned char *l2h; /* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */ unsigned char *l3h; - /* the layer 4 header */ - union { - unsigned char *smsh; - unsigned char *llch; - unsigned char *l4h; - }; + unsigned char *l4h; - /* the layer 5 header, GPRS: GMM header */ - unsigned char *gmmh; - uint32_t tlli; + /* the 'control buffer', large enough to contain 5 pointers */ + unsigned long cb[5]; uint16_t data_len; uint16_t len; @@ -71,7 +61,7 @@ extern void msgb_reset(struct msgb *m); #define msgb_l1(m) ((void *)(m->l1h)) #define msgb_l2(m) ((void *)(m->l2h)) #define msgb_l3(m) ((void *)(m->l3h)) -#define msgb_sms(m) ((void *)(m->smsh)) +#define msgb_sms(m) ((void *)(m->l4h)) static inline unsigned int msgb_l1len(const struct msgb *msgb) { diff --git a/libosmocore/include/osmocore/protocol/gsm_04_08.h b/libosmocore/include/osmocore/protocol/gsm_04_08.h index 801b9b54c..47b98b292 100644 --- a/libosmocore/include/osmocore/protocol/gsm_04_08.h +++ b/libosmocore/include/osmocore/protocol/gsm_04_08.h @@ -685,6 +685,7 @@ enum chreq_type { /* Chapter 5.1.2.2 */ #define GSM_CSTATE_NULL 0 #define GSM_CSTATE_INITIATED 1 +#define GSM_CSTATE_MM_CONNECTION_PEND 2 /* see 10.5.4.6 */ #define GSM_CSTATE_MO_CALL_PROC 3 #define GSM_CSTATE_CALL_DELIVERED 4 #define GSM_CSTATE_CALL_PRESENT 6 diff --git a/libosmocore/include/osmocore/protocol/gsm_08_08.h b/libosmocore/include/osmocore/protocol/gsm_08_08.h new file mode 100644 index 000000000..6b8f93595 --- /dev/null +++ b/libosmocore/include/osmocore/protocol/gsm_08_08.h @@ -0,0 +1,303 @@ +/* From GSM08.08 */ + +#ifndef GSM_0808_H +#define GSM_0808_H + +#include <stdlib.h> + +/* + * this is from GSM 03.03 CGI but is copied in GSM 08.08 + * in § 3.2.2.27 for Cell Identifier List + */ +enum CELL_IDENT { + CELL_IDENT_WHOLE_GLOBAL = 0, + CELL_IDENT_LAC_AND_CI = 1, + CELL_IDENT_CI = 2, + CELL_IDENT_NO_CELL = 3, + CELL_IDENT_LAI_AND_LAC = 4, + CELL_IDENT_LAC = 5, + CELL_IDENT_BSS = 6, + CELL_IDENT_UTRAN_PLMN_LAC_RNC = 8, + CELL_IDENT_UTRAN_RNC = 9, + CELL_IDENT_UTRAN_LAC_RNC = 10, +}; + + +/* GSM 08.06 § 6.3 */ +enum BSSAP_MSG_TYPE { + BSSAP_MSG_BSS_MANAGEMENT = 0x0, + BSSAP_MSG_DTAP = 0x1, +}; + +struct bssmap_header { + uint8_t type; + uint8_t length; +} __attribute__((packed)); + +struct dtap_header { + uint8_t type; + uint8_t link_id; + uint8_t length; +} __attribute__((packed)); + + +enum BSS_MAP_MSG_TYPE { + BSS_MAP_MSG_RESERVED_0 = 0, + + /* ASSIGNMENT MESSAGES */ + BSS_MAP_MSG_ASSIGMENT_RQST = 1, + BSS_MAP_MSG_ASSIGMENT_COMPLETE = 2, + BSS_MAP_MSG_ASSIGMENT_FAILURE = 3, + + /* HANDOVER MESSAGES */ + BSS_MAP_MSG_HANDOVER_RQST = 16, + BSS_MAP_MSG_HANDOVER_REQUIRED = 17, + BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE= 18, + BSS_MAP_MSG_HANDOVER_CMD = 19, + BSS_MAP_MSG_HANDOVER_COMPLETE = 20, + BSS_MAP_MSG_HANDOVER_SUCCEEDED = 21, + BSS_MAP_MSG_HANDOVER_FAILURE = 22, + BSS_MAP_MSG_HANDOVER_PERFORMED = 23, + BSS_MAP_MSG_HANDOVER_CANDIDATE_ENQUIRE = 24, + BSS_MAP_MSG_HANDOVER_CANDIDATE_RESPONSE = 25, + BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT = 26, + BSS_MAP_MSG_HANDOVER_DETECT = 27, + + /* RELEASE MESSAGES */ + BSS_MAP_MSG_CLEAR_CMD = 32, + BSS_MAP_MSG_CLEAR_COMPLETE = 33, + BSS_MAP_MSG_CLEAR_RQST = 34, + BSS_MAP_MSG_RESERVED_1 = 35, + BSS_MAP_MSG_RESERVED_2 = 36, + BSS_MAP_MSG_SAPI_N_REJECT = 37, + BSS_MAP_MSG_CONFUSION = 38, + + /* OTHER CONNECTION RELATED MESSAGES */ + BSS_MAP_MSG_SUSPEND = 40, + BSS_MAP_MSG_RESUME = 41, + BSS_MAP_MSG_CONNECTION_ORIENTED_INFORMATION = 42, + BSS_MAP_MSG_PERFORM_LOCATION_RQST = 43, + BSS_MAP_MSG_LSA_INFORMATION = 44, + BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE = 45, + BSS_MAP_MSG_PERFORM_LOCATION_ABORT = 46, + BSS_MAP_MSG_COMMON_ID = 47, + + /* GENERAL MESSAGES */ + BSS_MAP_MSG_RESET = 48, + BSS_MAP_MSG_RESET_ACKNOWLEDGE = 49, + BSS_MAP_MSG_OVERLOAD = 50, + BSS_MAP_MSG_RESERVED_3 = 51, + BSS_MAP_MSG_RESET_CIRCUIT = 52, + BSS_MAP_MSG_RESET_CIRCUIT_ACKNOWLEDGE = 53, + BSS_MAP_MSG_MSC_INVOKE_TRACE = 54, + BSS_MAP_MSG_BSS_INVOKE_TRACE = 55, + BSS_MAP_MSG_CONNECTIONLESS_INFORMATION = 58, + + /* TERRESTRIAL RESOURCE MESSAGES */ + BSS_MAP_MSG_BLOCK = 64, + BSS_MAP_MSG_BLOCKING_ACKNOWLEDGE = 65, + BSS_MAP_MSG_UNBLOCK = 66, + BSS_MAP_MSG_UNBLOCKING_ACKNOWLEDGE = 67, + BSS_MAP_MSG_CIRCUIT_GROUP_BLOCK = 68, + BSS_MAP_MSG_CIRCUIT_GROUP_BLOCKING_ACKNOWLEDGE = 69, + BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCK = 70, + BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCKING_ACKNOWLEDGE = 71, + BSS_MAP_MSG_UNEQUIPPED_CIRCUIT = 72, + BSS_MAP_MSG_CHANGE_CIRCUIT = 78, + BSS_MAP_MSG_CHANGE_CIRCUIT_ACKNOWLEDGE = 79, + + /* RADIO RESOURCE MESSAGES */ + BSS_MAP_MSG_RESOURCE_RQST = 80, + BSS_MAP_MSG_RESOURCE_INDICATION = 81, + BSS_MAP_MSG_PAGING = 82, + BSS_MAP_MSG_CIPHER_MODE_CMD = 83, + BSS_MAP_MSG_CLASSMARK_UPDATE = 84, + BSS_MAP_MSG_CIPHER_MODE_COMPLETE = 85, + BSS_MAP_MSG_QUEUING_INDICATION = 86, + BSS_MAP_MSG_COMPLETE_LAYER_3 = 87, + BSS_MAP_MSG_CLASSMARK_RQST = 88, + BSS_MAP_MSG_CIPHER_MODE_REJECT = 89, + BSS_MAP_MSG_LOAD_INDICATION = 90, + + /* VGCS/VBS */ + BSS_MAP_MSG_VGCS_VBS_SETUP = 4, + BSS_MAP_MSG_VGCS_VBS_SETUP_ACK = 5, + BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE = 6, + BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST = 7, + BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT = 28, + BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE = 29, + BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30, + BSS_MAP_MSG_UPLINK_RQST = 31, + BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39, + BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION = 73, + BSS_MAP_MSG_UPLINK_RELEASE_INDICATION = 74, + BSS_MAP_MSG_UPLINK_REJECT_CMD = 75, + BSS_MAP_MSG_UPLINK_RELEASE_CMD = 76, + BSS_MAP_MSG_UPLINK_SEIZED_CMD = 77, +}; + +enum GSM0808_IE_CODING { + GSM0808_IE_CIRCUIT_IDENTITY_CODE = 1, + GSM0808_IE_RESERVED_0 = 2, + GSM0808_IE_RESOURCE_AVAILABLE = 3, + GSM0808_IE_CAUSE = 4, + GSM0808_IE_CELL_IDENTIFIER = 5, + GSM0808_IE_PRIORITY = 6, + GSM0808_IE_LAYER_3_HEADER_INFORMATION = 7, + GSM0808_IE_IMSI = 8, + GSM0808_IE_TMSI = 9, + GSM0808_IE_ENCRYPTION_INFORMATION = 10, + GSM0808_IE_CHANNEL_TYPE = 11, + GSM0808_IE_PERIODICITY = 12, + GSM0808_IE_EXTENDED_RESOURCE_INDICATOR = 13, + GSM0808_IE_NUMBER_OF_MSS = 14, + GSM0808_IE_RESERVED_1 = 15, + GSM0808_IE_RESERVED_2 = 16, + GSM0808_IE_RESERVED_3 = 17, + GSM0808_IE_CLASSMARK_INFORMATION_T2 = 18, + GSM0808_IE_CLASSMARK_INFORMATION_T3 = 19, + GSM0808_IE_INTERFERENCE_BAND_TO_USE = 20, + GSM0808_IE_RR_CAUSE = 21, + GSM0808_IE_RESERVED_4 = 22, + GSM0808_IE_LAYER_3_INFORMATION = 23, + GSM0808_IE_DLCI = 24, + GSM0808_IE_DOWNLINK_DTX_FLAG = 25, + GSM0808_IE_CELL_IDENTIFIER_LIST = 26, + GSM0808_IE_RESPONSE_RQST = 27, + GSM0808_IE_RESOURCE_INDICATION_METHOD = 28, + GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1 = 29, + GSM0808_IE_CIRCUIT_IDENTITY_CODE_LIST = 30, + GSM0808_IE_DIAGNOSTIC = 31, + GSM0808_IE_LAYER_3_MESSAGE_CONTENTS = 32, + GSM0808_IE_CHOSEN_CHANNEL = 33, + GSM0808_IE_TOTAL_RESOURCE_ACCESSIBLE = 34, + GSM0808_IE_CIPHER_RESPONSE_MODE = 35, + GSM0808_IE_CHANNEL_NEEDED = 36, + GSM0808_IE_TRACE_TYPE = 37, + GSM0808_IE_TRIGGERID = 38, + GSM0808_IE_TRACE_REFERENCE = 39, + GSM0808_IE_TRANSACTIONID = 40, + GSM0808_IE_MOBILE_IDENTITY = 41, + GSM0808_IE_OMCID = 42, + GSM0808_IE_FORWARD_INDICATOR = 43, + GSM0808_IE_CHOSEN_ENCR_ALG = 44, + GSM0808_IE_CIRCUIT_POOL = 45, + GSM0808_IE_CIRCUIT_POOL_LIST = 46, + GSM0808_IE_TIME_INDICATION = 47, + GSM0808_IE_RESOURCE_SITUATION = 48, + GSM0808_IE_CURRENT_CHANNEL_TYPE_1 = 49, + GSM0808_IE_QUEUEING_INDICATOR = 50, + GSM0808_IE_SPEECH_VERSION = 64, + GSM0808_IE_ASSIGNMENT_REQUIREMENT = 51, + GSM0808_IE_TALKER_FLAG = 53, + GSM0808_IE_CONNECTION_RELEASE_RQSTED = 54, + GSM0808_IE_GROUP_CALL_REFERENCE = 55, + GSM0808_IE_EMLPP_PRIORITY = 56, + GSM0808_IE_CONFIG_EVO_INDI = 57, + GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION = 58, + GSM0808_IE_LSA_IDENTIFIER = 59, + GSM0808_IE_LSA_IDENTIFIER_LIST = 60, + GSM0808_IE_LSA_INFORMATION = 61, + GSM0808_IE_LCS_QOS = 62, + GSM0808_IE_LSA_ACCESS_CTRL_SUPPR = 63, + GSM0808_IE_LCS_PRIORITY = 67, + GSM0808_IE_LOCATION_TYPE = 68, + GSM0808_IE_LOCATION_ESTIMATE = 69, + GSM0808_IE_POSITIONING_DATA = 70, + GSM0808_IE_LCS_CAUSE = 71, + GSM0808_IE_LCS_CLIENT_TYPE = 72, + GSM0808_IE_APDU = 73, + GSM0808_IE_NETWORK_ELEMENT_IDENTITY = 74, + GSM0808_IE_GPS_ASSISTANCE_DATA = 75, + GSM0808_IE_DECIPHERING_KEYS = 76, + GSM0808_IE_RETURN_ERROR_RQST = 77, + GSM0808_IE_RETURN_ERROR_CAUSE = 78, + GSM0808_IE_SEGMENTATION = 79, + GSM0808_IE_SERVICE_HANDOVER = 80, + GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS = 81, + GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82, + GSM0808_IE_RESERVED_5 = 65, + GSM0808_IE_RESERVED_6 = 66, +}; + +enum gsm0808_cause { + GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE = 0, + GSM0808_CAUSE_RADIO_INTERFACE_FAILURE = 1, + GSM0808_CAUSE_UPLINK_QUALITY = 2, + GSM0808_CAUSE_UPLINK_STRENGTH = 3, + GSM0808_CAUSE_DOWNLINK_QUALITY = 4, + GSM0808_CAUSE_DOWNLINK_STRENGTH = 5, + GSM0808_CAUSE_DISTANCE = 6, + GSM0808_CAUSE_O_AND_M_INTERVENTION = 7, + GSM0808_CAUSE_RESPONSE_TO_MSC_INVOCATION = 8, + GSM0808_CAUSE_CALL_CONTROL = 9, + GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION = 10, + GSM0808_CAUSE_HANDOVER_SUCCESSFUL = 11, + GSM0808_CAUSE_BETTER_CELL = 12, + GSM0808_CAUSE_DIRECTED_RETRY = 13, + GSM0808_CAUSE_JOINED_GROUP_CALL_CHANNEL = 14, + GSM0808_CAUSE_TRAFFIC = 15, + GSM0808_CAUSE_EQUIPMENT_FAILURE = 32, + GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE = 33, + GSM0808_CAUSE_RQSTED_TERRESTRIAL_RESOURCE_UNAVAILABLE = 34, + GSM0808_CAUSE_CCCH_OVERLOAD = 35, + GSM0808_CAUSE_PROCESSOR_OVERLOAD = 36, + GSM0808_CAUSE_BSS_NOT_EQUIPPED = 37, + GSM0808_CAUSE_MS_NOT_EQUIPPED = 38, + GSM0808_CAUSE_INVALID_CELL = 39, + GSM0808_CAUSE_TRAFFIC_LOAD = 40, + GSM0808_CAUSE_PREEMPTION = 41, + GSM0808_CAUSE_RQSTED_TRANSCODING_RATE_ADAPTION_UNAVAILABLE = 48, + GSM0808_CAUSE_CIRCUIT_POOL_MISMATCH = 49, + GSM0808_CAUSE_SWITCH_CIRCUIT_POOL = 50, + GSM0808_CAUSE_RQSTED_SPEECH_VERSION_UNAVAILABLE = 51, + GSM0808_CAUSE_LSA_NOT_ALLOWED = 52, + GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED = 64, + GSM0808_CAUSE_TERRESTRIAL_CIRCUIT_ALREADY_ALLOCATED = 80, + GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS = 81, + GSM0808_CAUSE_INFORMATION_ELEMENT_OR_FIELD_MISSING = 82, + GSM0808_CAUSE_INCORRECT_VALUE = 83, + GSM0808_CAUSE_UNKNOWN_MESSAGE_TYPE = 84, + GSM0808_CAUSE_UNKNOWN_INFORMATION_ELEMENT = 85, + GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC = 96, +}; + +/* GSM 08.08 3.2.2.11 Channel Type */ +enum gsm0808_chan_indicator { + GSM0808_CHAN_SPEECH = 1, + GSM0808_CHAN_DATA = 2, + GSM0808_CHAN_SIGN = 3, +}; + +enum gsm0808_chan_rate_type_data { + GSM0808_DATA_FULL_BM = 0x8, + GSM0808_DATA_HALF_LM = 0x9, + GSM0808_DATA_FULL_RPREF = 0xa, + GSM0808_DATA_HALF_PREF = 0xb, + GSM0808_DATA_FULL_PREF_NO_CHANGE = 0x1a, + GSM0808_DATA_HALF_PREF_NO_CHANGE = 0x1b, + GSM0808_DATA_MULTI_MASK = 0x20, + GSM0808_DATA_MULTI_MASK_NO_CHANGE = 0x30, +}; + +enum gsm0808_chan_rate_type_speech { + GSM0808_SPEECH_FULL_BM = 0x8, + GSM0808_SPEECH_HALF_LM = 0x9, + GSM0808_SPEECH_FULL_PREF= 0xa, + GSM0808_SPEECH_HALF_PREF= 0xb, + GSM0808_SPEECH_FULL_PREF_NO_CHANGE = 0x1a, + GSM0808_SPEECH_HALF_PREF_NO_CHANGE = 0x1b, + GSM0808_SPEECH_PERM = 0xf, + GSM0808_SPEECH_PERM_NO_CHANGE = 0x1f, +}; + +enum gsm0808_permitted_speech { + GSM0808_PERM_FR1 = 0x01, + GSM0808_PERM_FR2 = 0x11, + GSM0808_PERM_FR3 = 0x21, + GSM0808_PERM_HR1 = GSM0808_PERM_FR1 | 0x4, + GSM0808_PERM_HR2 = GSM0808_PERM_FR2 | 0x4, + GSM0808_PERM_HR3 = GSM0808_PERM_FR3 | 0x4, +}; + +#endif diff --git a/libosmocore/include/osmocore/write_queue.h b/libosmocore/include/osmocore/write_queue.h index 64d4159a0..ef244c32a 100644 --- a/libosmocore/include/osmocore/write_queue.h +++ b/libosmocore/include/osmocore/write_queue.h @@ -35,6 +35,7 @@ struct write_queue { int (*read_cb)(struct bsc_fd *fd); int (*write_cb)(struct bsc_fd *fd, struct msgb *msg); + int (*except_cb)(struct bsc_fd *fd); }; void write_queue_init(struct write_queue *queue, int max_length); diff --git a/libosmocore/src/Makefile.am b/libosmocore/src/Makefile.am index 16978074a..20e99db30 100644 --- a/libosmocore/src/Makefile.am +++ b/libosmocore/src/Makefile.am @@ -10,7 +10,7 @@ lib_LTLIBRARIES = libosmocore.la libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \ tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ - logging.c + logging.c gsm0808.c if ENABLE_TALLOC libosmocore_la_SOURCES += talloc.c diff --git a/libosmocore/src/gsm0808.c b/libosmocore/src/gsm0808.c new file mode 100644 index 000000000..7a7eb3a08 --- /dev/null +++ b/libosmocore/src/gsm0808.c @@ -0,0 +1,295 @@ +/* (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org> + * (C) 2009,2010 by On-Waves + * 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 <osmocore/gsm0808.h> +#include <osmocore/protocol/gsm_08_08.h> +#include <osmocore/gsm48.h> + +#include <arpa/inet.h> + +#define BSSMAP_MSG_SIZE 512 +#define BSSMAP_MSG_HEADROOM 128 + +struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, int _ci) +{ + uint8_t *data; + uint16_t *ci; + struct msgb* msg; + struct gsm48_loc_area_id *lai; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap cmpl l3"); + if (!msg) + return NULL; + + /* create the bssmap header */ + msg->l3h = msgb_put(msg, 2); + msg->l3h[0] = 0x0; + + /* create layer 3 header */ + data = msgb_put(msg, 1); + data[0] = BSS_MAP_MSG_COMPLETE_LAYER_3; + + /* create the cell header */ + data = msgb_put(msg, 3); + data[0] = GSM0808_IE_CELL_IDENTIFIER; + data[1] = 1 + sizeof(*lai) + 2; + data[2] = CELL_IDENT_WHOLE_GLOBAL; + + lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai)); + gsm48_generate_lai(lai, cc, nc, lac); + + ci = (uint16_t *) msgb_put(msg, 2); + *ci = htons(_ci); + + /* copy the layer3 data */ + data = msgb_put(msg, msgb_l3len(msg_l3) + 2); + data[0] = GSM0808_IE_LAYER_3_INFORMATION; + data[1] = msgb_l3len(msg_l3); + memcpy(&data[2], msg_l3->l3h, data[1]); + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + + return msg; +} + +struct msgb *gsm0808_create_reset(void) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: reset"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 6); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0x04; + msg->l3h[2] = 0x30; + msg->l3h[3] = 0x04; + msg->l3h[4] = 0x01; + msg->l3h[5] = 0x20; + return msg; +} + +struct msgb *gsm0808_create_clear_complete(void) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: clear complete"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 1; + msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE; + + return msg; +} + +struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "cipher-complete"); + if (!msg) + return NULL; + + /* send response with BSS override for A5/1... cheating */ + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0xff; + msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_COMPLETE; + + /* include layer3 in case we have at least two octets */ + if (layer3 && msgb_l3len(layer3) > 2) { + msg->l4h = msgb_put(msg, msgb_l3len(layer3) + 2); + msg->l4h[0] = GSM0808_IE_LAYER_3_MESSAGE_CONTENTS; + msg->l4h[1] = msgb_l3len(layer3); + memcpy(&msg->l4h[2], layer3->l3h, msgb_l3len(layer3)); + } + + /* and the optional BSS message */ + msg->l4h = msgb_put(msg, 2); + msg->l4h[0] = GSM0808_IE_CHOSEN_ENCR_ALG; + msg->l4h[1] = alg_id; + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + return msg; +} + +struct msgb *gsm0808_create_cipher_reject(uint8_t cause) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: clear complete"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 2; + msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_REJECT; + msg->l3h[3] = cause; + + return msg; +} + +struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark_data, uint8_t length) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "classmark-update"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0xff; + msg->l3h[2] = BSS_MAP_MSG_CLASSMARK_UPDATE; + + msg->l4h = msgb_put(msg, length); + memcpy(msg->l4h, classmark_data, length); + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + return msg; +} + +struct msgb *gsm0808_create_sapi_reject(uint8_t link_id) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: sapi 'n' reject"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 5); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 3; + msg->l3h[2] = BSS_MAP_MSG_SAPI_N_REJECT; + msg->l3h[3] = link_id; + msg->l3h[4] = GSM0808_CAUSE_BSS_NOT_EQUIPPED; + + return msg; +} + +struct msgb *gsm0808_create_assignment_completed(struct gsm_lchan *lchan, uint8_t rr_cause, + uint8_t chosen_channel, uint8_t encr_alg_id, + uint8_t speech_mode) +{ + uint8_t *data; + + struct msgb *msg = msgb_alloc(35, "bssmap: ass compl"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0xff; + msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_COMPLETE; + + /* write 3.2.2.22 */ + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_RR_CAUSE; + data[1] = rr_cause; + + /* write cirtcuit identity code 3.2.2.2 */ + /* write cell identifier 3.2.2.17 */ + /* write chosen channel 3.2.2.33 when BTS picked it */ + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_CHOSEN_CHANNEL; + data[1] = chosen_channel; + + /* write chosen encryption algorithm 3.2.2.44 */ + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_CHOSEN_ENCR_ALG; + data[1] = encr_alg_id; + + /* write circuit pool 3.2.2.45 */ + /* write speech version chosen: 3.2.2.51 when BTS picked it */ + if (speech_mode != 0) { + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_SPEECH_VERSION; + data[1] = speech_mode; + } + + /* write LSA identifier 3.2.2.15 */ + + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + return msg; +} + +struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause) +{ + uint8_t *data; + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: ass fail"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 6); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0xff; + msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE; + msg->l3h[3] = GSM0808_IE_CAUSE; + msg->l3h[4] = 1; + msg->l3h[5] = cause; + + /* RR cause 3.2.2.22 */ + if (rr_cause) { + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_RR_CAUSE; + data[1] = *rr_cause; + } + + /* Circuit pool 3.22.45 */ + /* Circuit pool list 3.2.2.46 */ + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + return msg; +} + +static const struct tlv_definition bss_att_tlvdef = { + .def = { + [GSM0808_IE_IMSI] = { TLV_TYPE_TLV }, + [GSM0808_IE_TMSI] = { TLV_TYPE_TLV }, + [GSM0808_IE_CELL_IDENTIFIER_LIST] = { TLV_TYPE_TLV }, + [GSM0808_IE_CHANNEL_NEEDED] = { TLV_TYPE_TV }, + [GSM0808_IE_EMLPP_PRIORITY] = { TLV_TYPE_TV }, + [GSM0808_IE_CHANNEL_TYPE] = { TLV_TYPE_TLV }, + [GSM0808_IE_PRIORITY] = { TLV_TYPE_TLV }, + [GSM0808_IE_CIRCUIT_IDENTITY_CODE] = { TLV_TYPE_TV }, + [GSM0808_IE_DOWNLINK_DTX_FLAG] = { TLV_TYPE_TV }, + [GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV }, + [GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV }, + [GSM0808_IE_GROUP_CALL_REFERENCE] = { TLV_TYPE_TLV }, + [GSM0808_IE_TALKER_FLAG] = { TLV_TYPE_T }, + [GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV }, + [GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV }, + [GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TV}, + [GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV }, + [GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV }, + }, +}; + +const struct tlv_definition *gsm0808_att_tlvdef() +{ + return &bss_att_tlvdef; +} diff --git a/libosmocore/src/gsm48.c b/libosmocore/src/gsm48.c index 5761c67b4..783ff6a5d 100644 --- a/libosmocore/src/gsm48.c +++ b/libosmocore/src/gsm48.c @@ -97,10 +97,10 @@ static const struct value_string rr_cause_names[] = { }; /* FIXME: convert to value_string */ -static const char *cc_state_names[32] = { +static const char *cc_state_names[33] = { "NULL", "INITIATED", - "illegal state 2", + "MM_CONNECTION_PEND", "MO_CALL_PROC", "CALL_DELIVERED", "illegal state 5", @@ -261,3 +261,47 @@ int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi) return 2 + buf[1]; } + +/* Convert Mobile Identity (10.5.1.4) to string */ +int gsm48_mi_to_string(char *string, const int str_len, const uint8_t *mi, + const int mi_len) +{ + int i; + uint8_t mi_type; + char *str_cur = string; + uint32_t tmsi; + + mi_type = mi[0] & GSM_MI_TYPE_MASK; + + switch (mi_type) { + case GSM_MI_TYPE_NONE: + break; + case GSM_MI_TYPE_TMSI: + /* Table 10.5.4.3, reverse generate_mid_from_tmsi */ + if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) { + memcpy(&tmsi, &mi[1], 4); + tmsi = ntohl(tmsi); + return snprintf(string, str_len, "%u", tmsi); + } + break; + case GSM_MI_TYPE_IMSI: + case GSM_MI_TYPE_IMEI: + case GSM_MI_TYPE_IMEISV: + *str_cur++ = bcd2char(mi[0] >> 4); + + for (i = 1; i < mi_len; i++) { + if (str_cur + 2 >= string + str_len) + return str_cur - string; + *str_cur++ = bcd2char(mi[i] & 0xf); + /* skip last nibble in last input byte when GSM_EVEN */ + if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD)) + *str_cur++ = bcd2char(mi[i] >> 4); + } + break; + default: + break; + } + *str_cur++ = '\0'; + + return str_cur - string; +} diff --git a/libosmocore/src/gsm48_ie.c b/libosmocore/src/gsm48_ie.c index 4ca5fb800..3c2a1f7b6 100644 --- a/libosmocore/src/gsm48_ie.c +++ b/libosmocore/src/gsm48_ie.c @@ -2,7 +2,7 @@ * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ /* (C) 2008 by Harald Welte <laforge@gnumonks.org> - * (C) 2008-2010 by Andreas Eversberg + * (C) 2009-2010 by Andreas Eversberg * * All Rights Reserved * diff --git a/libosmocore/src/logging.c b/libosmocore/src/logging.c index 508ccfd3e..7c508771f 100644 --- a/libosmocore/src/logging.c +++ b/libosmocore/src/logging.c @@ -20,11 +20,16 @@ * */ +#include "../config.h" + #include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <string.h> + +#ifdef HAVE_STRINGS_H #include <strings.h> +#endif #include <time.h> #include <errno.h> @@ -302,31 +307,46 @@ void log_set_category_filter(struct log_target *target, int category, target->categories[category].loglevel = level; } +/* since C89/C99 says stderr is a macro, we can safely do this! */ +#ifdef stderr static void _stderr_output(struct log_target *target, const char *log) { fprintf(target->tgt_stdout.out, "%s", log); fflush(target->tgt_stdout.out); } +#endif struct log_target *log_target_create(void) { struct log_target *target; + unsigned int i; target = talloc_zero(tall_log_ctx, struct log_target); if (!target) return NULL; INIT_LLIST_HEAD(&target->entry); - memcpy(target->categories, log_info->cat, - sizeof(struct log_category)*log_info->num_cat); + + /* initialize the per-category enabled/loglevel from defaults */ + for (i = 0; i < log_info->num_cat; i++) { + struct log_category *cat = &target->categories[i]; + cat->enabled = log_info->cat[i].enabled; + cat->loglevel = log_info->cat[i].loglevel; + } + + /* global settings */ target->use_color = 1; target->print_timestamp = 0; + + /* global log level */ target->loglevel = 0; return target; } struct log_target *log_target_create_stderr(void) { +/* since C89/C99 says stderr is a macro, we can safely do this! */ +#ifdef stderr struct log_target *target; target = log_target_create(); @@ -336,6 +356,9 @@ struct log_target *log_target_create_stderr(void) target->tgt_stdout.out = stderr; target->output = _stderr_output; return target; +#else + return NULL; +#endif /* stderr */ } void log_init(const struct log_info *cat) diff --git a/libosmocore/src/msgb.c b/libosmocore/src/msgb.c index 60af373eb..9117a0ad0 100644 --- a/libosmocore/src/msgb.c +++ b/libosmocore/src/msgb.c @@ -80,10 +80,9 @@ void msgb_reset(struct msgb *msg) msg->head = msg->_data; msg->tail = msg->_data; - msg->bts_link = NULL; msg->trx = NULL; msg->lchan = NULL; msg->l2h = NULL; msg->l3h = NULL; - msg->smsh = NULL; + msg->l4h = NULL; } diff --git a/libosmocore/src/select.c b/libosmocore/src/select.c index 9517778ce..2f6afa7f5 100644 --- a/libosmocore/src/select.c +++ b/libosmocore/src/select.c @@ -121,7 +121,8 @@ restart: /* ugly, ugly hack. If more than one filedescriptors were * unregistered, they might have been consecutive and * llist_for_each_entry_safe() is no longer safe */ - if (unregistered_count > 1) + /* this seems to happen with the last element of the list as well */ + if (unregistered_count >= 1) goto restart; } return work; diff --git a/libosmocore/src/write_queue.c b/libosmocore/src/write_queue.c index a0ac2d6fd..618a8c0b3 100644 --- a/libosmocore/src/write_queue.c +++ b/libosmocore/src/write_queue.c @@ -32,6 +32,9 @@ int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what) if (what & BSC_FD_READ) queue->read_cb(fd); + if (what & BSC_FD_EXCEPT) + queue->except_cb(fd); + if (what & BSC_FD_WRITE) { struct msgb *msg; |