Merge commit '074c9f904cb5e4f6ab014d76e4abc079c16fc5d7'

This commit is contained in:
Harald Welte
2010-04-30 14:29:56 +02:00
17 changed files with 742 additions and 25 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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) */

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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

295
libosmocore/src/gsm0808.c Normal file
View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
*

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;