#pragma once /* q931.c - Q.931 protocol definitions * * (C) 2022 by Harald Welte * * All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ * * 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. */ #include #include #include /* Table 4-2/Q.931 - Message types */ enum q931_msg_type { /* Call establishment messages */ Q931_MSGT_ALERTING = 0x01, Q931_MSGT_CALL_PROCEEDING = 0x02, Q931_MSGT_CONNECT = 0x07, Q931_MSGT_CONNECT_ACK = 0x0f, Q931_MSGT_PROGRESS = 0x03, Q931_MSGT_SETUP = 0x05, Q931_MSGT_SETUP_ACK = 0x0d, /* Call information phase messages */ Q931_MSGT_RESUME = 0x26, Q931_MSGT_RESUME_ACK = 0x2e, Q931_MSGT_RESUME_REJ = 0x22, Q931_MSGT_SUSPEND = 0x25, Q931_MSGT_SUSPEND_ACK = 0x2d, Q931_MSGT_SUSPEND_REJ = 0x21, Q931_MSGT_USER_INFO = 0x20, /* Call clearing messages */ Q931_MSGT_DISCONNECT = 0x45, Q931_MSGT_RELEASE = 0x4d, Q931_MSGT_RELEASE_COMPLETE = 0x5a, Q931_MSGT_RESTART = 0x46, Q931_MSGT_RESTART_ACK = 0x4e, /* Miscellaneous messages */ Q931_MSGT_SEGMENT = 0x60, Q931_MSGT_CONGESTION_CTRL = 0x79, Q931_MSGT_INFORMATION = 0x7b, Q931_MSGT_NOTIFY = 0x6e, Q931_MSGT_STATUS = 0x7d, Q931_MSGT_STATUS_ENQIURY = 0x75, }; extern const struct value_string q931_msg_type_vals[]; /* Table 4-3/Q.931 */ enum q931_iei { /* reserved */ /* shift */ Q931_IEI_MORE_DATA = 0xa0, Q931_IEI_SENDING_COMPLETE = 0xa1, /* contentionlevel */ /* repeat indicator */ /* Veriable length IEs */ Q931_IEI_SEGMENTED_MSG = 0x00, Q931_IEI_BEARER_CAP = 0x04, Q931_IEI_CAUSE = 0x08, Q931_IEI_CALL_ID = 0x10, Q931_IEI_CALL_STATE = 0x14, Q931_IEI_CHANNEL_ID = 0x18, Q931_IEI_PROGRESS_IND = 0x1e, Q931_IEI_NETWORK_SPEC_FAC = 0x20, Q931_IEI_NOTIFICATION_IND = 0x27, Q931_IEI_DISPLAY = 0x28, Q931_IEI_DATE_TIME = 0x29, Q931_IEI_KEYPAD_FACILITY = 0x2c, Q931_IEI_SIGNAL = 0x34, Q931_IEI_INFORMATION_RATE = 0x40, Q931_IEI_E2E_TRANSIT_DELAY = 0x42, Q931_IEI_TRANSIT_DELAY_SEL_AND_IND = 0x43, Q931_IEI_PKT_LAYER_BIN_PARAMS = 0x44, Q931_IEI_PKT_LAYER_WIN_SIZE = 0x45, Q931_IEI_PACKET_SIZE = 0x46, Q931_IEI_CLOSED_USER_GROUP = 0x47, Q931_IEI_REV_CHARGING_IND = 0x4a, Q931_IEI_CALLING_PARTY_NUM = 0x6c, Q931_IEI_CALLING_PARTY_SUBADDR = 0x6d, Q931_IEI_CALLED_PARTY_NUM = 0x70, Q931_IEI_CALLED_PARTY_SUBADDR = 0x71, Q931_IEI_TRANSIT_NET_SEL = 0x78, Q931_IEI_RESTART_IND = 0x79, Q931_IEI_LOW_LAYER_COMPAT = 0x7c, Q931_IEI_HIGH_LAYER_COMPAT = 0x7d, Q931_IEI_ESCAPE_FOR_EXT = 0x7f, }; struct q931_msg_parsed { uint8_t msg_type; uint32_t call_ref; struct tlv_parsed ies; }; int q931_msg_parse(struct q931_msg_parsed *out, const uint8_t *buf, size_t len); uint32_t q931_decode_callref(const uint8_t *data, uint8_t len); /* Q.931 Section 4.5.13 */ enum q931_info_chan_type { Q931_INFO_CHAN_T_NONE, Q931_INFO_CHAN_T_ANY, Q931_INFO_CHAN_T_SPECIFIC, }; /* decoded version of (simplified) Q.931 Channel Identification IE */ struct q931_channel_id { bool interface_id_present; uint32_t interface_id; bool interface_type_pri; bool exclusive; bool d_channel; enum q931_info_chan_type info_chan_type; uint32_t b_channel; /* 1..2 on BRI; 1..31 on PRI */ }; int q931_decode_channel_id(struct q931_channel_id *out, const uint8_t *data, uint8_t len); struct q931_party_number { uint8_t type_of_number; uint8_t numbering_plan_id; uint8_t presentation_ind; uint8_t screening_ind; char digits[32]; }; int q931_decode_called_party(struct q931_party_number *out, const uint8_t *buf, size_t len); int q931_decode_calling_party(struct q931_party_number *out, const uint8_t *buf, size_t len);