From 532b8e92c5a33ac4fd7e62f8355abf64292736c7 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Fri, 9 Jun 2023 15:24:59 +0200 Subject: [PATCH] ASCI: Add message definition and encoding according to 3GPP TS 48.008 Change-Id: Ib94c64136c31ce4af67c314a8550d93946cc844f --- include/osmocom/gsm/gsm0808.h | 241 ++++++++- include/osmocom/gsm/protocol/gsm_08_08.h | 3 + src/gsm/gsm0808.c | 656 +++++++++++++++++++++++ src/gsm/libosmogsm.map | 19 + 4 files changed, 917 insertions(+), 2 deletions(-) diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index dcff4159f..80ef6836c 100644 --- a/include/osmocom/gsm/gsm0808.h +++ b/include/osmocom/gsm/gsm0808.h @@ -26,11 +26,11 @@ #include #include +#include + #define BSSMAP_MSG_SIZE 1024 #define BSSMAP_MSG_HEADROOM 512 -struct sockaddr_storage; - struct msgb; struct gsm0808_cell_id_list2; @@ -332,6 +332,243 @@ struct gsm0808_handover_performed { }; struct msgb *gsm0808_create_handover_performed(const struct gsm0808_handover_performed *params); +/*! 3GPP TS 48.008 §3.2.1.50 VGCS/VBS SETUP */ +struct gsm0808_vgcs_vbs_setup { + struct gsm0808_group_callref callref; + + bool priority_present; + struct gsm0808_priority priority; + + bool vgcs_feature_flags_present; + struct gsm0808_vgcs_feature_flags flags; +}; +struct msgb *gsm0808_create_vgcs_vbs_setup(const struct gsm0808_vgcs_vbs_setup *params); + +/*! 3GPP TS 48.008 §3.2.1.51 VGCS/VBS SETUP ACK */ +struct gsm0808_vgcs_vbs_setup_ack { + bool vgcs_feature_flags_present; + struct gsm0808_vgcs_feature_flags flags; +}; +struct msgb *gsm0808_create_vgcs_vbs_setup_ack(const struct gsm0808_vgcs_vbs_setup_ack *params); + +/*! 3GPP TS 48.008 §3.2.1.52 VGCS/VBS SETUP REFUSE */ +struct msgb *gsm0808_create_vgcs_vbs_setup_refuse(enum gsm0808_cause cause); + +/*! 3GPP TS 48.008 §3.2.1.53 VGCS/VBS ASSIGNMENT REQUEST */ +struct gsm0808_vgcs_vbs_assign_req { + struct gsm0808_channel_type channel_type; + enum gsm0808_assignment_requirement ass_req; + struct gsm0808_cell_id cell_identifier; + struct gsm0808_group_callref callref; + + bool priority_present; + struct gsm0808_priority priority; + + bool cic_present; + uint16_t cic; + + bool downlink_dtx_flag_present; + enum gsm0808_downlink_dtx_flag downlink_dtx_flag; + + bool encryption_information_present; + struct gsm0808_encrypt_info encryption_information; + + bool vstk_rand_present; + uint8_t vstk_rand[5]; + + bool vstk_present; + uint8_t vstk[16]; + + bool cils_present; + struct gsm0808_cell_id_list_segment cils; + + bool aoip_transport_layer_present; + struct sockaddr_storage aoip_transport_layer; + + bool call_id_present; + uint32_t call_id; + + bool codec_list_present; + struct gsm0808_speech_codec_list codec_list_msc_preferred; +}; +struct msgb *gsm0808_create_vgcs_vbs_assign_req(const struct gsm0808_vgcs_vbs_assign_req *params); + +/*! 3GPP TS 48.008 §3.2.1.54 VGCS/VBS ASSIGNMENT RESULT */ +struct gsm0808_vgcs_vbs_assign_res { + struct gsm0808_channel_type channel_type; + struct gsm0808_cell_id cell_identifier; + + bool chosen_channel_present; + uint8_t chosen_channel; + + bool cic_present; + uint16_t cic; + + bool circuit_pool_present; + uint8_t circuit_pool; + + bool aoip_transport_layer_present; + struct sockaddr_storage aoip_transport_layer; + + bool codec_present; + struct gsm0808_speech_codec codec_msc_chosen; + + bool call_id_present; + uint32_t call_id; +}; +struct msgb *gsm0808_create_vgcs_vbs_assign_res(const struct gsm0808_vgcs_vbs_assign_res *params); + +/*! 3GPP TS 48.008 §3.2.1.55 VGCS/VBS ASSIGNMENT FAILURE */ +struct gsm0808_vgcs_vbs_assign_fail { + enum gsm0808_cause cause; + + bool circuit_pool_present; + uint8_t circuit_pool; + + bool cpl_present; + struct gsm0808_circuit_pool_list cpl; + + bool codec_list_present; + struct gsm0808_speech_codec_list codec_list_bss_supported; +}; +struct msgb *gsm0808_create_vgcs_vbs_assign_fail(const struct gsm0808_vgcs_vbs_assign_fail *params); + +/*! 3GPP TS 48.008 §3.2.1.57 (VGCS) UPLINK REQUEST */ +struct gsm0808_uplink_request { + bool talker_priority_present; + enum gsm0808_talker_priority talker_priority; + + bool cell_identifier_present; + struct gsm0808_cell_id cell_identifier; + + bool l3_present; + struct gsm0808_layer_3_information l3; + + bool mi_present; + struct osmo_mobile_identity mi; +}; +struct msgb *gsm0808_create_uplink_request(const struct gsm0808_uplink_request *params); + +/*! 3GPP TS 48.008 §3.2.1.58 (VGCS) UPLINK REQUEST ACKNOWLEDGE */ +struct gsm0808_uplink_request_ack { + bool talker_priority_present; + enum gsm0808_talker_priority talker_priority; + + bool emerg_set_ind_present; + + bool talker_identity_present; + struct gsm0808_talker_identity talker_identity; +}; +struct msgb *gsm0808_create_uplink_request_ack(const struct gsm0808_uplink_request_ack *params); + +/*! 3GPP TS 48.008 §3.2.1.59 (VGCS) UPLINK REQUEST CONFIRM */ +struct gsm0808_uplink_request_cnf { + struct gsm0808_cell_id cell_identifier; + + bool talker_identity_present; + struct gsm0808_talker_identity talker_identity; + + /* mandatory! */ + struct gsm0808_layer_3_information l3; +}; +struct msgb *gsm0808_create_uplink_request_cnf(const struct gsm0808_uplink_request_cnf *params); + +/*! 3GPP TS 48.008 §3.2.1.59a (VGCS) UPLINK APPLICATION DATA */ +struct gsm0808_uplink_app_data { + struct gsm0808_cell_id cell_identifier; + struct gsm0808_layer_3_information l3; + bool bt_ind; +}; +struct msgb *gsm0808_create_uplink_app_data(const struct gsm0808_uplink_app_data *params); + +/*! 3GPP TS 48.008 §3.2.1.60 (VGCS) UPLINK RELEASE INDICATION */ +struct gsm0808_uplink_release_ind { + enum gsm0808_cause cause; + + bool talker_priority_present; + enum gsm0808_talker_priority talker_priority; +}; +struct msgb *gsm0808_create_uplink_release_ind(const struct gsm0808_uplink_release_ind *params); + +/*! 3GPP TS 48.008 §3.2.1.61 (VGCS) UPLINK REJECT COMMAND */ +struct gsm0808_uplink_reject_cmd { + enum gsm0808_cause cause; + + bool current_talker_priority_present; + enum gsm0808_talker_priority current_talker_priority; + bool rejected_talker_priority_present; + enum gsm0808_talker_priority rejected_talker_priority; + + bool talker_identity_present; + struct gsm0808_talker_identity talker_identity; +}; +struct msgb *gsm0808_create_uplink_reject_cmd(const struct gsm0808_uplink_reject_cmd *params); + +/*! 3GPP TS 48.008 §3.2.1.62 (VGCS) UPLINK RELEASE COMMAND */ +struct msgb *gsm0808_create_uplink_release_cmd(const enum gsm0808_cause cause); + +/*! 3GPP TS 48.008 §3.2.1.63 (VGCS) UPLINK SEIZED COMMAND */ +struct gsm0808_uplink_seized_cmd { + enum gsm0808_cause cause; + + bool talker_priority_present; + enum gsm0808_talker_priority talker_priority; + + bool emerg_set_ind_present; + + bool talker_identity_present; + struct gsm0808_talker_identity talker_identity; +}; +struct msgb *gsm0808_create_uplink_seized_cmd(const struct gsm0808_uplink_seized_cmd *params); + +/*! 3GPP TS 48.008 §3.2.1.78 VGCS ADDITIONAL INFORMATION */ +struct msgb *gsm0808_create_vgcs_additional_info(const struct gsm0808_talker_identity *ti); + +/*! 3GPP TS 48.008 §3.2.1.79 VGCS/VBS AREA CELL INFO */ +struct gsm0808_vgcs_vbs_area_cell_info { + struct gsm0808_cell_id_list_segment cils; + + bool ass_req_present; + enum gsm0808_assignment_requirement ass_req; +}; +struct msgb *gsm0808_create_vgcs_vbs_area_cell_info(const struct gsm0808_vgcs_vbs_area_cell_info *params); + +/*! 3GPP TS 48.008 §3.2.1.80 VGCS/VBS ASSIGNMENT STATUS */ +struct gsm0808_vgcs_vbs_assign_stat { + /* established cells */ + bool cils_est_present; + struct gsm0808_cell_id_list_segment cils_est; + + /* cells to be established */ + bool cils_tbe_present; + struct gsm0808_cell_id_list_segment cils_tbe; + + /* released cells - no user present */ + bool cils_rel_present; + struct gsm0808_cell_id_list_segment cils_rel; + + /* not established cells - no establishment possible */ + bool cils_ne_present; + struct gsm0808_cell_id_list_segment cils_ne; + + bool cell_status_present; + enum gsm0808_vgcs_vbs_cell_status cell_status; +}; +struct msgb *gsm0808_create_vgcs_vbs_assign_stat(const struct gsm0808_vgcs_vbs_assign_stat *params); + +/*! 3GPP TS 48.008 §3.2.1.81 VGCS SMS */ +struct msgb *gsm0808_create_vgcs_sms(const struct gsm0808_sms_to_vgcs *sms); + +/*! 3GPP TS 48.008 §3.2.1.82 (VGCS/VBS) NOTIFICATION DATA */ +struct gsm0808_notification_data { + struct gsm0808_application_data app_data; + struct gsm0808_data_identity data_ident; + + bool msisdn_present; + char msisdn[MSISDN_MAXLEN + 1]; +}; +struct msgb *gsm0808_create_notification_data(const struct gsm0808_notification_data *parms); + struct msgb *gsm0808_create_dtap(struct msgb *msg, uint8_t link_id); void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id); diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index fad75c2a7..967e4fe54 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -168,12 +168,15 @@ enum BSS_MAP_MSG_TYPE { BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30, BSS_MAP_MSG_UPLINK_RQST = 31, BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39, + BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_STATUS = 59, + BSS_MAP_MSG_VGCS_VBS_AREA_CELL_INFO = 60, 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, BSS_MAP_MSG_VGCS_ADDL_INFO = 0x60, + BSS_MAP_MSG_VGCS_SMS = 0x61, BSS_MAP_MSG_NOTIFICATION_DATA = 0x62, BSS_MAP_MSG_UPLINK_APP_DATA = 0x63, diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index e1768c1ad..d115888e7 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -17,6 +17,8 @@ * */ +#include "config.h" + #include #include @@ -1514,6 +1516,657 @@ struct msgb *gsm0808_create_perform_location_abort(const struct lcs_cause_ie *lc return msg; } +/*! Create BSSMAP VGCS/VBS SETUP message, 3GPP TS 48.008 3.2.1.50. + * Sent from the MSC to the BSC to request VGCS/VBS call. */ +struct msgb *gsm0808_create_vgcs_vbs_setup(const struct gsm0808_vgcs_vbs_setup *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-SETUP"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_VBS_SETUP); + + /* Group Call Reference, 3.2.2.55 */ + gsm0808_enc_group_callref(msg, ¶ms->callref); + + /* Priority, 3.2.2.18 */ + if (params->priority_present) + gsm0808_enc_priority(msg, ¶ms->priority); + + /* VGCS Feature Flags, 3.2.2.88 */ + if (params->vgcs_feature_flags_present) + gsm0808_enc_vgcs_feature_flags(msg, ¶ms->flags); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP VGCS/VBS SETUP ACK message, 3GPP TS 48.008 3.2.1.51. + * Sent from the BSC to the MSC to confirm VGCS/VBS call. */ +struct msgb *gsm0808_create_vgcs_vbs_setup_ack(const struct gsm0808_vgcs_vbs_setup_ack *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-SETUP-ACK"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_VBS_SETUP_ACK); + + /* VGCS Feature Flags, 3.2.2.88 */ + if (params->vgcs_feature_flags_present) + gsm0808_enc_vgcs_feature_flags(msg, ¶ms->flags); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP VGCS/VBS SETUP REFUSE message, 3GPP TS 48.008 3.2.1.52. + * Sent from the BSC to the MSC to reject VGCS/VBS call. */ +struct msgb *gsm0808_create_vgcs_vbs_setup_refuse(enum gsm0808_cause cause) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-SETUP-REFUSE"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE); + + /* Cause, 3.2.2.5 */ + gsm0808_enc_cause(msg, cause); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP VGCS/VBS ASSIGNMENT REQUEST message, 3GPP TS 48.008 3.2.1.53. + * Sent from the MSC to the BSC to assign radio resources for a VGCS/VBS. */ +struct msgb *gsm0808_create_vgcs_vbs_assign_req(const struct gsm0808_vgcs_vbs_assign_req *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-ASSIGNMENT-REQUEST"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST); + + /* Channel Type, 3.2.2.11 */ + gsm0808_enc_channel_type(msg, ¶ms->channel_type); + + /* Assignment Requrirement, 3.2.2.52 */ + gsm0808_enc_assign_req(msg, params->ass_req); + + /* Cell Identifier, 3.2.2.17 */ + gsm0808_enc_cell_id(msg, ¶ms->cell_identifier); + + /* Group Call Reference, 3.2.2.55 */ + gsm0808_enc_group_callref(msg, ¶ms->callref); + + /* Priority, 3.2.2.18 */ + if (params->priority_present) + gsm0808_enc_priority(msg, ¶ms->priority); + + /* Circuit Identity Code, 3.2.2.2 */ + if (params->cic_present) + msgb_tv16_put(msg, GSM0808_IE_CIRCUIT_IDENTITY_CODE, params->cic); + + /* Downlink DTX Flag, 3.2.2.26 */ + if (params->downlink_dtx_flag_present) + msgb_tv_put(msg, GSM0808_IE_DOWNLINK_DTX_FLAG, params->downlink_dtx_flag); + + /* Encryption Information, 3.2.2.10 */ + if (params->encryption_information_present) + gsm0808_enc_encrypt_info(msg, ¶ms->encryption_information); + + /* VSTK_RAND Imformation, 3.2.2.83 */ + if (params->vstk_rand_present) + msgb_tlv_put(msg, GSM0808_IE_VSTK_RAND_INFO, sizeof(params->vstk_rand), params->vstk_rand); + + /* VSTK Information, 3.2.2.84 */ + if (params->vstk_present) + msgb_tlv_put(msg, GSM0808_IE_VSTK_INFO, sizeof(params->vstk), params->vstk); + + /* Cell Identifier List Segment, 3.2.2.27a */ + if (params->cils_present) + gsm0808_enc_cell_id_list_segment(msg, GSM0808_IE_CELL_ID_LIST_SEGMENT, ¶ms->cils); + + /* AoIP Transport Layer Address (MGW), 3.2.2.102 */ + if (params->aoip_transport_layer_present) + gsm0808_enc_aoip_trasp_addr(msg, ¶ms->aoip_transport_layer); + + /* Call Identifier, 3.2.2.105 */ + if (params->call_id_present) { + /* NOTE: 3GPP TS 48.008, section 3.2.2.105 specifies that + * the least significant byte shall be transmitted first. */ + msgb_v_put(msg, GSM0808_IE_CALL_ID); + osmo_store32le(params->call_id, msgb_put(msg, sizeof(uint32_t))); + } + + /* Codec List (MSC Preferred) 3.2.2.103 */ + if (params->codec_list_present) { + if (gsm0808_enc_speech_codec_list2(msg, ¶ms->codec_list_msc_preferred) < 0) + goto exit_free; + } + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; + +exit_free: + msgb_free(msg); + return NULL; +} + +/*! Create BSSMAP VGCS/VBS ASSIGNMENT RESULT message, 3GPP TS 48.008 3.2.1.54. + * Sent from the BSC to the MSC to indicate assignment/deassingment of radio resources for a VGCS/VBS. */ +struct msgb *gsm0808_create_vgcs_vbs_assign_res(const struct gsm0808_vgcs_vbs_assign_res *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-ASSIGNMENT-RESULT"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT); + + /* Channel Type, 3.2.2.11 */ + gsm0808_enc_channel_type(msg, ¶ms->channel_type); + + /* Cell Identifier, 3.2.2.17 */ + gsm0808_enc_cell_id(msg, ¶ms->cell_identifier); + + /* Chosen Channel, 3.2.2.33 */ + if (params->chosen_channel_present) + msgb_tv_put(msg, GSM0808_IE_CHOSEN_CHANNEL, params->chosen_channel); + + /* Circuit Identity Code, 3.2.2.2 */ + if (params->cic_present) + msgb_tv16_put(msg, GSM0808_IE_CIRCUIT_IDENTITY_CODE, params->cic); + + /* Circuit Pool, 3.2.2.45 */ + if (params->circuit_pool_present) + msgb_tv_put(msg, GSM0808_IE_CIRCUIT_POOL, params->circuit_pool); + + /* AoIP Transport Layer Address (BSS), 3.2.2.102 */ + if (params->aoip_transport_layer_present) + gsm0808_enc_aoip_trasp_addr(msg, ¶ms->aoip_transport_layer); + + /* Codec (MSC Chosen) 3.2.2.103 */ + if (params->codec_present) { + if (gsm0808_enc_speech_codec2(msg, ¶ms->codec_msc_chosen) < 0) + goto exit_free; + } + + /* Call Identifier, 3.2.2.105 */ + if (params->call_id_present) { + /* NOTE: 3GPP TS 48.008, section 3.2.2.105 specifies that + * the least significant byte shall be transmitted first. */ + msgb_v_put(msg, GSM0808_IE_CALL_ID); + osmo_store32le(params->call_id, msgb_put(msg, sizeof(uint32_t))); + } + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; + +exit_free: + msgb_free(msg); + return NULL; +} + +/*! Create BSSMAP VGCS/VBS ASSIGNMENT FAILURE message, 3GPP TS 48.008 3.2.1.55. + * Sent from the BSC to the MSC to indicate assignment failure for a VGCS/VBS. */ +struct msgb *gsm0808_create_vgcs_vbs_assign_fail(const struct gsm0808_vgcs_vbs_assign_fail *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-ASSIGNMENT-RESULT"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE); + + /* Cause, 3.2.2.5 */ + gsm0808_enc_cause(msg, params->cause); + + /* Circuit Pool, 3.2.2.45 */ + if (params->circuit_pool_present) + msgb_tv_put(msg, GSM0808_IE_CIRCUIT_POOL, params->circuit_pool); + + /* Circuit Pool List, 3.2.2.46 */ + if (params->circuit_pool_present) + msgb_tlv_put(msg, GSM0808_IE_CIRCUIT_POOL_LIST, params->cpl.list_len, params->cpl.pool); + + /* Codec List (BSS Supported) 3.2.2.103 */ + if (params->codec_list_present) + gsm0808_enc_speech_codec_list2(msg, ¶ms->codec_list_bss_supported); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP VGCS/VBS QUEUING INDICATION message, 3GPP TS 48.008 3.2.1.56. + * Sent from the BSC to the MSC to indicate delay in assignment for a VGCS/VBS. */ +struct msgb *gsm0808_create_vgcs_queuing_ind(void) +{ + struct msgb *msg; + uint8_t val = BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-QUEUING-INDICATION"); + if (!msg) + return NULL; + + msg->l3h = msg->data; + msgb_tlv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 1, &val); + + return msg; +} + +/*! Create BSSMAP (VGCS) UPLINK REQUEST message, 3GPP TS 48.008 3.2.1.57. + * Sent from the BSC to the MSC to indicate that a mobile requested access to uplink. */ +struct msgb *gsm0808_create_uplink_request(const struct gsm0808_uplink_request *params) +{ + struct msgb *msg; + int rc; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-UPLINK-REQUEST"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_UPLINK_RQST); + + /* Talker Priority, 3.2.2.89 */ + if (params->talker_priority_present) + msgb_tv_put(msg, GSM0808_IE_TALKER_PRIORITY, params->talker_priority); + + /* Cell Identifier, 3.2.2.17 */ + if (params->cell_identifier_present) + gsm0808_enc_cell_id(msg, ¶ms->cell_identifier); + + /* Layer 3 Information, 3.2.2.24 */ + if (params->l3_present) + msgb_tlv_put(msg, GSM0808_IE_LAYER_3_INFORMATION, params->l3.l3_len, params->l3.l3); + + /* Mobile Identity, 3.2.2.41 */ + if (params->mi_present) { + rc = osmo_mobile_identity_encode_msgb(msg, ¶ms->mi, false); + if (rc < 0) { + msgb_free(msg); + return NULL; + } + } + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP (VGCS) UPLINK REQUEST ACKNOWLEDGE message, 3GPP TS 48.008 3.2.1.58. + * Sent from the MSC to the BSC to indicate that access to uplink was granted. */ +struct msgb *gsm0808_create_uplink_request_ack(const struct gsm0808_uplink_request_ack *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-UPLINK-REQUEST-ACKNOWLEDGE"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE); + + /* Talker Priority, 3.2.2.89 */ + if (params->talker_priority_present) + msgb_tv_put(msg, GSM0808_IE_TALKER_PRIORITY, params->talker_priority); + + /* Emergency set indication, 3.2.2.90 */ + if (params->emerg_set_ind_present) + msgb_v_put(msg, GSM0808_IE_EMERGENCY_SET_INDICATION); + + /* Talker Identity, 3.2.2.91 */ + if (params->talker_identity_present) + gsm0808_enc_talker_identity(msg, ¶ms->talker_identity); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP (VGCS) UPLINK CONFIRM message, 3GPP TS 48.008 3.2.1.59. + * Sent from the BSC to the MSC to indicate that access to uplink was has been successfully established. */ +struct msgb *gsm0808_create_uplink_request_cnf(const struct gsm0808_uplink_request_cnf *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-UPLINK-REQUEST-CONFIRM"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION); + + /* Cell Identifier, 3.2.2.17 */ + gsm0808_enc_cell_id(msg, ¶ms->cell_identifier); + + /* Talker Identity, 3.2.2.91 */ + if (params->talker_identity_present) + gsm0808_enc_talker_identity(msg, ¶ms->talker_identity); + + /* Layer 3 Information, 3.2.2.24 */ + msgb_tlv_put(msg, GSM0808_IE_LAYER_3_INFORMATION, params->l3.l3_len, params->l3.l3); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP (VGCS) UPLINK APPLICATION DATA message, 3GPP TS 48.008 3.2.1.59a. + * Sent from the BSC to the MSC to pass L3 info from the talker. */ +struct msgb *gsm0808_create_uplink_app_data(const struct gsm0808_uplink_app_data *params) +{ + struct msgb *msg; + uint8_t val; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-UPLINK-APPLICATION-DATA"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_UPLINK_APP_DATA); + + /* Cell Identifier, 3.2.2.17 */ + gsm0808_enc_cell_id(msg, ¶ms->cell_identifier); + + /* Layer 3 Information, 3.2.2.24 */ + msgb_tlv_put(msg, GSM0808_IE_LAYER_3_INFORMATION, params->l3.l3_len, params->l3.l3); + + /* Application Data Information, 3.2.2.100 */ + val = params->bt_ind; + msgb_tlv_put(msg, GSM0808_IE_APP_DATA_INFO, 1, &val); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP (VGCS) UPLINK RELEASE INDICATION message, 3GPP TS 48.008 3.2.1.60. + * Sent from the BSC to the MSC to indicate that the uplink has been released. */ +struct msgb *gsm0808_create_uplink_release_ind(const struct gsm0808_uplink_release_ind *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-UPLINK-RELEASE-INDICATION"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_UPLINK_RELEASE_INDICATION); + + /* Cause, 3.2.2.5 */ + gsm0808_enc_cause(msg, params->cause); + + /* Talker Priority, 3.2.2.89 */ + if (params->talker_priority_present) + msgb_tv_put(msg, GSM0808_IE_TALKER_PRIORITY, params->talker_priority); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP (VGCS) UPLINK REJECT COMMAND message, 3GPP TS 48.008 3.2.1.61. + * Sent from the MSC to the BSC to indicate that the uplink is not available for allocation. */ +struct msgb *gsm0808_create_uplink_reject_cmd(const struct gsm0808_uplink_reject_cmd *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-UPLINK-REJECT-COMMAND"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_UPLINK_REJECT_CMD); + + /* Cause, 3.2.2.5 */ + gsm0808_enc_cause(msg, params->cause); + + /* Talker Priority, 3.2.2.89 */ + if (params->current_talker_priority_present) + msgb_tv_put(msg, GSM0808_IE_TALKER_PRIORITY, params->current_talker_priority); + + /* Talker Priority, 3.2.2.89 */ + if (params->rejected_talker_priority_present) + msgb_tv_put(msg, GSM0808_IE_TALKER_PRIORITY, params->rejected_talker_priority); + + /* Talker Identity, 3.2.2.91 */ + if (params->talker_identity_present) + gsm0808_enc_talker_identity(msg, ¶ms->talker_identity); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP (VGCS) UPLINK RELEASE COMMAND message, 3GPP TS 48.008 3.2.1.62. + * Sent from the MSC to the BSC to indicate that the uplink is available for allocation. */ +struct msgb *gsm0808_create_uplink_release_cmd(const enum gsm0808_cause cause) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-UPLINK-RELEASE-COMMAND"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_UPLINK_RELEASE_CMD); + + /* Cause, 3.2.2.5 */ + gsm0808_enc_cause(msg, cause); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP (VGCS) UPLINK SEIZED COMMAND message, 3GPP TS 48.008 3.2.1.62. + * Sent from the MSC to the BSC to indicate that the uplink is no longer available for allocation. */ +struct msgb *gsm0808_create_uplink_seized_cmd(const struct gsm0808_uplink_seized_cmd *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-UPLINK-SEIZED-COMMAND"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_UPLINK_SEIZED_CMD); + + /* Cause, 3.2.2.5 */ + gsm0808_enc_cause(msg, params->cause); + + /* Talker Priority, 3.2.2.89 */ + if (params->talker_priority_present) + msgb_tv_put(msg, GSM0808_IE_TALKER_PRIORITY, params->talker_priority); + + /* Emergency set indication, 3.2.2.90 */ + if (params->emerg_set_ind_present) + msgb_v_put(msg, GSM0808_IE_EMERGENCY_SET_INDICATION); + + /* Talker Identity, 3.2.2.91 */ + if (params->talker_identity_present) + gsm0808_enc_talker_identity(msg, ¶ms->talker_identity); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP VGCS ADDITIONAL INFORMATION message, 3GPP TS 48.008 3.2.1.78. + * Sent from the MSC to the BSC to transfer talker identity. */ +struct msgb *gsm0808_create_vgcs_additional_info(const struct gsm0808_talker_identity *ti) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS-ADDITIONAL-INFO"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_ADDL_INFO); + + /* Talker Identity, 3.2.2.91 */ + gsm0808_enc_talker_identity(msg, ti); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP VGCS/VBS AREA CELL INFO message, 3GPP TS 48.008 3.2.1.79. + * Sent from the BSC to the MSC to transfer additional infos about cells. */ +struct msgb *gsm0808_create_vgcs_vbs_area_cell_info(const struct gsm0808_vgcs_vbs_area_cell_info *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-AREA-CELL-INFO"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST); + + /* Cell Identifier List Segment, 3.2.2.27a */ + gsm0808_enc_cell_id_list_segment(msg, GSM0808_IE_CELL_ID_LIST_SEGMENT, ¶ms->cils); + + /* Assignment Requrirement, 3.2.2.52 */ + if (params->ass_req_present) + gsm0808_enc_assign_req(msg, params->ass_req); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP VGCS/VBS ASSIGNMENT STATUS message, 3GPP TS 48.008 3.2.1.80. + * Sent from the BSC to the MSC to indicate assignment status for each cell. */ +struct msgb *gsm0808_create_vgcs_vbs_assign_stat(const struct gsm0808_vgcs_vbs_assign_stat *params) +{ + struct msgb *msg; + uint8_t val; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS/VBS-ASSIGNMENT-STATUS"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_STATUS); + + /* Cell Identifier List Segment, 3.2.2.27b */ + if (params->cils_est_present) + gsm0808_enc_cell_id_list_segment(msg, GSM0808_IE_CELL_ID_LIST_SEG_EST_CELLS, ¶ms->cils_est); + /* Cell Identifier List Segment, 3.2.2.27c */ + if (params->cils_tbe_present) + gsm0808_enc_cell_id_list_segment(msg, GSM0808_IE_CELL_ID_LIST_SEG_CELLS_TBE, ¶ms->cils_tbe); + /* Cell Identifier List Segment, 3.2.2.27e */ + if (params->cils_rel_present) + gsm0808_enc_cell_id_list_segment(msg, GSM0808_IE_CELL_ID_LIST_SEG_REL_CELLS, ¶ms->cils_rel); + /* Cell Identifier List Segment, 3.2.2.27f */ + if (params->cils_ne_present) + gsm0808_enc_cell_id_list_segment(msg, GSM0808_IE_CELL_ID_LIST_SEG_NE_CELLS, ¶ms->cils_ne); + + /* VGCS/VBS Cell Status, 3.2.2.94 */ + if (params->cell_status_present) { + val = params->cell_status; + msgb_tlv_put(msg, GSM0808_IE_VGCS_VBS_CELL_STATUS, 1, &val); + } + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP VGCS SMS message, 3GPP TS 48.008 3.2.1.81. + * Sent from the MSC to the BSC to send an SMS to VGCS. */ +struct msgb *gsm0808_create_vgcs_sms(const struct gsm0808_sms_to_vgcs *sms) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS-SMS"); + if (!msg) + return NULL; + + /* SMS to VGCS, 3.2.2.92 */ + msgb_tlv_put(msg, GSM0808_IE_VGCS_VBS_CELL_STATUS, sms->sms_len, sms->sms); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/*! Create BSSMAP (VGCS/VBS) NOTIFICATION DATA message, 3GPP TS 48.008 3.2.1.82. + * Sent from the MSC to the BSC to send application specific data. */ +struct msgb *gsm0808_create_notification_data(const struct gsm0808_notification_data *params) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "BSSMAP-VGCS-SMS"); + if (!msg) + return NULL; + + /* Message Type, 3.2.2.1 */ + msgb_v_put(msg, BSS_MAP_MSG_NOTIFICATION_DATA); + + /* Application Data, 3.2.2.98 */ + msgb_tlv_put(msg, GSM0808_IE_APP_DATA, params->app_data.data_len, params->app_data.data); + + /* Data Identity, 3.2.2.99 */ + gsm0808_enc_data_identity(msg, ¶ms->data_ident); + + /* MSISDN, 3.2.2.101 */ + if (params->msisdn_present) + gsm0808_enc_msisdn(msg, params->msisdn); + + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + +/* Note that EMERGENCY RESET INDICATION and EMERGENCY RESET COMMAND cannot be implemented, due to lack of + * message type information in the specifications. */ + /* As per 3GPP TS 48.008 version 11.7.0 Release 11 */ static const struct tlv_definition bss_att_tlvdef = { .def = { @@ -1775,7 +2428,9 @@ static const struct value_string gsm0808_msgt_names[] = { { BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST, "VGCS/VBS ASSIGN REQ" }, { BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT, "VGCS/VBS ASSIGN RES" }, { BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE, "VGCS/VBS ASSIGN FAIL" }, + { BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_STATUS, "VGCS/VBS ASSIGN STATUS" }, { BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION, "VGCS/VBS QUEUING IND" }, + { BSS_MAP_MSG_VGCS_VBS_AREA_CELL_INFO, "VGCS/VBS AREA CELL INFO" }, { BSS_MAP_MSG_UPLINK_RQST, "UPLINK REQ" }, { BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE, "UPLINK REQ ACK" }, { BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION, "UPLINK REQ CONF" }, @@ -1784,6 +2439,7 @@ static const struct value_string gsm0808_msgt_names[] = { { BSS_MAP_MSG_UPLINK_RELEASE_CMD, "UPLINK REL CMD" }, { BSS_MAP_MSG_UPLINK_SEIZED_CMD, "UPLINK SEIZED CMD" }, { BSS_MAP_MSG_VGCS_ADDL_INFO, "VGCS ADDL INFO" }, + { BSS_MAP_MSG_VGCS_SMS, "VGCS SMS" }, { BSS_MAP_MSG_NOTIFICATION_DATA, "NOTIF DATA" }, { BSS_MAP_MSG_UPLINK_APP_DATA, "UPLINK APP DATA" }, diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 1eea819ee..29bf94fd5 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -209,6 +209,25 @@ gsm0808_create_handover_succeeded; gsm0808_create_handover_complete; gsm0808_create_handover_failure; gsm0808_create_handover_performed; +gsm0808_create_vgcs_vbs_setup; +gsm0808_create_vgcs_vbs_setup_ack; +gsm0808_create_vgcs_vbs_setup_refuse; +gsm0808_create_vgcs_vbs_assign_req; +gsm0808_create_vgcs_vbs_assign_res; +gsm0808_create_vgcs_vbs_assign_fail; +gsm0808_create_uplink_request; +gsm0808_create_uplink_request_ack; +gsm0808_create_uplink_request_cnf; +gsm0808_create_uplink_app_data; +gsm0808_create_uplink_release_ind; +gsm0808_create_uplink_reject_cmd; +gsm0808_create_uplink_release_cmd; +gsm0808_create_uplink_seized_cmd; +gsm0808_create_vgcs_additional_info; +gsm0808_create_vgcs_vbs_area_cell_info; +gsm0808_create_vgcs_vbs_assign_stat; +gsm0808_create_vgcs_sms; +gsm0808_create_notification_data; gsm0808_create_common_id; gsm0808_prepend_dtap_header; gsm0808_enc_cause;