#include #include #include "q931.h" #include "log.h" /* Table 4-3/Q.931 */ const struct tlv_definition q931_tlv_def = { .def = { /* fixed-length */ [0x80] = { TLV_TYPE_SINGLE_TV, 0 }, [0x90] = { TLV_TYPE_SINGLE_TV, 0 }, [Q931_IEI_MORE_DATA] = { TLV_TYPE_T, 0 }, [Q931_IEI_SENDING_COMPLETE] = { TLV_TYPE_T, 0 }, [0xB0] = { TLV_TYPE_SINGLE_TV, 0 }, [0xD0] = { TLV_TYPE_SINGLE_TV, 0 }, /* variable-length */ [Q931_IEI_SEGMENTED_MSG] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_BEARER_CAP] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_CAUSE] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_CALL_ID] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_CALL_STATE] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_CHANNEL_ID] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_PROGRESS_IND] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_NETWORK_SPEC_FAC] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_NOTIFICATION_IND] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_DISPLAY] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_DATE_TIME] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_KEYPAD_FACILITY] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_SIGNAL] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_INFORMATION_RATE] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_E2E_TRANSIT_DELAY] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_TRANSIT_DELAY_SEL_AND_IND] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_PKT_LAYER_BIN_PARAMS] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_PKT_LAYER_WIN_SIZE] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_PACKET_SIZE] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_CLOSED_USER_GROUP] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_REV_CHARGING_IND] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_CALLING_PARTY_NUM] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_CALLING_PARTY_SUBADDR]= { TLV_TYPE_TLV, 0 }, [Q931_IEI_CALLED_PARTY_NUM] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_CALLED_PARTY_SUBADDR] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_TRANSIT_NET_SEL] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_RESTART_IND] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_LOW_LAYER_COMPAT] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_HIGH_LAYER_COMPAT] = { TLV_TYPE_TLV, 0 }, [Q931_IEI_ESCAPE_FOR_EXT] = { TLV_TYPE_TLV, 0 }, }, }; /* parse one Q.931 message for signaling analysis */ int q931_msg_parse(struct q931_msg_parsed *out, const uint8_t *buf, size_t len) { uint8_t cref_len; const uint8_t *other_ie; size_t other_ie_len; int rc; memset(out, 0, sizeof(*out)); /* at least protocol discriminator + length of call-ref must be present */ if (len < 2) { LOGP(DQ931, LOGL_ERROR, "short Q.931 message: %s\n", osmo_hexdump(buf, len)); return -EMSGSIZE; } /* check protocol discriminator */ if (buf[0] != 0x08) { LOGP(DQ931, LOGL_ERROR, "unknoqn Q.931 protocol discrimnator 0x%02x: %s", buf[0], osmo_hexdump(buf, len)); return -EINVAL; } /* parse [variable length] call reference */ cref_len = buf[1] & 0x0F; if (len < 2U + cref_len) { LOGP(DQ931, LOGL_ERROR, "short Q.931 message: %s\n", osmo_hexdump(buf, len)); return -EMSGSIZE; } out->call_ref = q931_decode_callref(buf+1, 1+cref_len); /* parse message type */ if (len < 2U + cref_len + 1U) { LOGP(DQ931, LOGL_ERROR, "short Q.931 message: %s\n", osmo_hexdump(buf, len)); return -EMSGSIZE; } out->msg_type = buf[2+cref_len] & 0x7f; /* parse 'other IEs' */ other_ie = buf + 2 + cref_len + 1; other_ie_len = len - (2 + cref_len + 1); if (other_ie_len) { rc = tlv_parse(&out->ies, &q931_tlv_def, other_ie, other_ie_len, 0, 0); if (rc < 0) { LOGP(DQ931, LOGL_ERROR, "Can't TLV-parse Q.931 message: %s\n", osmo_hexdump(buf, len)); return rc; } } return 0; } /* Q.931 Section 4.3 */ uint32_t q931_decode_callref(const uint8_t *data, uint8_t len) { uint8_t len_of_callref; uint32_t callref = 0; bool flag = false; if (len < 1) goto err; len_of_callref = data[0] & 0x0f; if (len_of_callref == 0) goto err; if (len_of_callref > 4) goto err; if (len - 1 < len_of_callref) goto err; /* first octet contains flag, needs special handling */ if (data[1] & 0x80) flag = true; callref = data[1] & 0x7f; /* all further octets ... */ for (unsigned i = 1; i < len_of_callref; i++) callref = (callref << 8) | data[1+i]; if (flag) callref |= 0x80000000; return callref; err: LOGP(DQ931, LOGL_ERROR, "Unable to decode Q.931 call reference: %s\n", osmo_hexdump(data, len)); return 0; } /* Decode a (subset of) Q.931 channel identification IE from binary to struct representation */ int q931_decode_channel_id(struct q931_channel_id *out, const uint8_t *data, uint8_t len) { const uint8_t *cur = data; memset(out, 0, sizeof(*out)); if (len < 1) goto err; if (! (data[0] & 0x80)) goto err; if (data[0] & 0x40) { out->interface_id_present = true; cur++; if (len < 1 + (cur - data)) goto err; /* we only support single-octet interface ID */ if (!(*cur & 0x80)) goto err; out->interface_id = *cur & 0x7f; } if (data[0] & 0x20) out->interface_type_pri = true; if (data[0] & 0x08) out->exclusive = true; if (data[0] & 0x04) { out->d_channel = true; } else { switch (data[0] & 0x03) { case 0: out->info_chan_type = Q931_INFO_CHAN_T_NONE; break; case 1: if (out->interface_type_pri == false) { out->b_channel = 1; } else { /* Octet 3.2 */ cur++; if (len < 1 + (cur - data)) goto err; if (!(*cur & 0x80)) goto err; /* do we care about the coding standard? */ /* we only support single channel numbers */ if (*cur & 0x10) goto err; /* we only support B-channels */ if ((*cur & 0x0f) != 0x03) goto err; /* Octet 3.3 */ cur++; if (len < 1 + (cur - data)) goto err; /* we only support single channel numbers */ if (!(*cur & 0x80)) goto err; out->b_channel = *cur & 0x7f; } break; case 2: if (out->interface_type_pri == false) out->b_channel = 2; else goto err; break; case 3: out->info_chan_type = Q931_INFO_CHAN_T_ANY; break; } } return 0; err: LOGP(DQ931, LOGL_ERROR, "Unable to decode Q.931 channel id: %s\n", osmo_hexdump(data, len)); return -1; } /* Q.931 Section 4.5.8 */ int q931_decode_called_party(struct q931_party_number *out, const uint8_t *buf, size_t len) { memset(out, 0, sizeof(*out)); if (len < 1) goto err; /* Octet 3 */ if (!(*buf & 0x80)) goto err; out->type_of_number = (*buf >> 4) & 0x7; out->numbering_plan_id = *buf & 0xf; for (unsigned int i = 0; i < len - 1; i++) { if (i >= sizeof(out->digits)) goto err; out->digits[i] = buf[1+i] & 0x7f; } return 0; err: LOGP(DQ931, LOGL_ERROR, "Unable to decode Q.931 called party: %s\n", osmo_hexdump(buf, len)); return -1; } /* Q.931 Section 4.5.10 */ int q931_decode_calling_party(struct q931_party_number *out, const uint8_t *buf, size_t len) { const uint8_t *cur = buf; memset(out, 0, sizeof(*out)); if (len < 1) goto err; /* Octet 3 */ out->type_of_number = (*cur >> 4) & 0x7; out->numbering_plan_id = *cur & 0xf; if (!(*cur & 0x80)) { /* Octet 3a */ cur++; if (len < 2) goto err; if (!(*cur & 0x80)) goto err; out->presentation_ind = (*cur >> 5) & 0x3; out->screening_ind = *cur & 0x3; } cur++; for (unsigned int i = 0; i < len - (cur - buf); i++) { if (i >= sizeof(out->digits)) goto err; out->digits[i] = cur[i] & 0x7f; } return 0; err: LOGP(DQ931, LOGL_ERROR, "Unable to decode Q.931 calling party: %s\n", osmo_hexdump(buf, len)); return -1; }