commit b32fa16b54f363a3b858b0469311e648e466aec3 Author: Harald Welte Date: Sat Feb 4 21:33:14 2023 +0100 initial very early WIP for parsing T.62 messages/parameters diff --git a/src/t62.c b/src/t62.c new file mode 100644 index 0000000..ce38151 --- /dev/null +++ b/src/t62.c @@ -0,0 +1,129 @@ +#include + +#include "t62.h" + +/* T.61 Table 1 */ +const struct value_string t62_session_element_id_str[] = { + { T62_SID_CSS, "Command Session Start" }, + { T62_SID_CSE, "Command Session End" }, + { T62_SID_CSA, "Command Session Abort" }, + { T62_SID_CSCC, "Command Session Change Control" }, + { T62_SID_CSUI, "Command Session User Information" }, + { T62_SID_RSSP, "Response Session Start Positive" }, + { T62_SID_RSSN, "Response Session Start Negative" }, + { T62_SID_RSEP, "Response Session End Positive" }, + { T62_SID_RSAP, "Response Session Abort Positive" }, + { T62_SID_RSCCP,"Response Session Change Control Positive" }, + { T62_SID_RSUI, "Response Session User Information" }, + { 0, NULL } +}; + +/* T.62 Table 2 */ +const struct value_string t62_command_resp_str[] = { + { T62_DCID_CDS, "Command Document Start" }, + { T62_DCID_CDC, "Command Document Continue" }, + { T62_DCID_CDE, "Command Document End" }, + { T62_DCID_CDR, "Command Document Resynchronize" }, + { T62_DCID_CDD, "Command Document Discard" }, + { T62_DCID_CDPB, "Command Document Page Boundary" }, + { T62_DCID_CDCL, "Command Document Capability List" }, + { T62_DCID_CDUI, "Command Document User Information" }, + { T62_DRID_RDEP, "Response Document End Positive" }, + { T62_DRID_RDRP, "Response Document Resynchronize Positive" }, + { T62_DRID_RDDP, "Response Document Discard Positive" }, + { T62_DRID_RDPBP, "Response Document Page Boundary Positive" }, + { T62_DRID_RDPBN, "Response Document Page Boundary Negative" }, + { T62_DRID_RDCLP, "Response Document Capability List Positive" }, + { T62_DRID_RDGR, "Response Document General Reject" }, + { 0, NULL } +}; + + +struct t62_part { + struct llist_head list; + struct t62_part *parent; + + uint8_t id; + const uint8_t *data; + uint16_t data_len; + + struct llist_head children; +}; + +static struct t62_part *t62_part_alloc(void *ctx, struct t62_part *parent) +{ + struct t62_part *part = talloc_zero(ctx, struct t62_part); + if (!part) + return NULL; + if (parent) { + part->parent = parent; + llist_add_tail(&part->list, &parent->children); + } + INIT_LLIST_HEAD(&part->children); + return part; +} + +static void t62_part_free(struct t62_part *part) +{ + if (part->parent) + llist_del(&part->list); + talloc_free(part); +} + +/*! parse one T.62 parameter from msg starting at cur. Recurse if parameter is Parameter Group. + * \param[in] msg message buffer holding input data + * \param[in] cur pointer pointing to first byte of param (PI/PGI) inside msg + * \param[in] parent optional pointer to parent t62_part (in case of nesting) + * \returns parsed t62_param or NULL in case of error. */ +struct t62_part *t62_parse_param(struct msgb *msg, uint8_t *cur, struct llist_head *parent) +{ + struct t62_part *part = t62_part_alloc(parent, parent); + uint8_t pi; + uint16_t len; + + /* FIXME: check msgb->length overflow everywhere below */ + + pi = *cur++; + if (*cur <= 254) { + /* 8-bit length */ + len = *cur++; + } else { + /* 16-bit length */ + cur++; + len = *cur++ << 8; + len |= *cur++; + } + + part->id = pi; + if (len) { + part->data = cur; + part->data_len = len; + if (is_pgi(pi)) { + /* recurse if it's a group */ + rc = t62_parse_param(msg, cur, part); + if (rc < 0) { + t62_part_free(part); + return NULL; + } + } + } + return part; +} + +int t62_parse(struct msgb *msg, struct llist_head *parent) +{ + uint8_t *cur; + uint8_t ci; + uint16_t len; + + cur = msgb_l3h(msg); + + root_part = t62_parse_param(msg, cur, NULL); + if (!root_part) + return -1; + + /* check if there's user information after all (recursive) parts */ + if (cur + root_part->data_len < msgb_l3len(msg)) { + /* FIXME */ + } +} diff --git a/src/t62.h b/src/t62.h new file mode 100644 index 0000000..75cd18e --- /dev/null +++ b/src/t62.h @@ -0,0 +1,108 @@ + +/* T.62 Table 4 */ +enum t62_session_element_id { + T62_SID_CSS = 0x0d, + T62_SID_CSE = 0x09, + T62_SID_CSA = 0x19, + T62_SID_CSCC = 0x15, + T62_SID_CSUI = 0x01, + T62_SID_RSSP = 0x0e, + T62_SID_RSSN = 0x0c, + T62_SID_RSEP = 0x0a, + T62_SID_RSAP = 0x1a, + T62_SID_RSCCP = 0x16, + T62_SID_RSUI = 0x02, +}; + +/* T.62 Table 5 */ +enum t62_document_cmd_id { + T62_DCID_CDS = 0x2d, + T62_DCID_CDC = 0x1d, + T62_DCID_CDE = 0x29, + T62_DCID_CDR = 0x19, + T62_DCID_CDD = 0x39, + T62_DCID_CDPB = 0x31, + T62_DCID_CDCL = 0x3d, + T62_DCID_CDUI = 0x01, +}; + +/* T.62 Table 6 */ +enum t62_document_cmd_id { + T62_DRID_RDEP = 0x2a, + T62_DRID_RDRP = 0x1a, + T62_DRID_RDDP = 0x3a, + T62_DRID_RDPBP = 0x32, + T62_DRID_RDPBN = 0x30, + T62_DRID_RDCLP = 0x3e, + T62_DRID_RDGR = 0x00, +}; + +/* T.62 Table 7 + 8 */ +enum t62_param_group_id { + T62_PGI_RES_FOR_EXT = 0x00, + T62_PGI_SESSION_REF = 0x01, + T62_PGI_NON_BASIC_SESSION_CAP = 0x02, + T62_PGI_NON_BASIC_TELETEX_CAP = 0x41, + T62_PGI_SESSION_USER_DATA = 0xc1, + T62_PGI_DOCUMENT_LINKING = 0x21, + T62_PGI_DOCUMENT_LINKING = 0x21, + +}; +/* T.62 Table 7 + 8 */ +enum t62_param_id { + /* T62_PGI_SESSION_REF */ + T62_PI_TI_OF_CALLED = 0x09, + T62_PI_TI_OF_CALLING = 0x0a, + T62_PI_DATE_AND_TIME = 0x0b, + T62_PI_ADDL_SESSION_REF_NR = 0x0c, + T62_PI_DOCUMENT_REF_NR = 0x29, + T62_PI_CHECKPOINT_REF_NR = 0x2a, + /* T62_PGI_NON_BASIC_SESSION_CAP */ + T62_PI_MISC_SESSION_CAP = 0x0d, + T62_PI_WINDOW_SIZE = 0x0e, + /* No PGI associated with these PIs */ + T62_PI_SERVICE_ID = 0x08, + T62_PI_SESSION_CTRL_FUNCT = 0x10, + T62_PI_SESSION_TERM_PARAM = 0x11, + T62_PI_INACTIVITY_TIMER = 0x12, + T62_PI_SESSION_SERVICE_FUNCT = 0x14, + T62_PI_SERVICE_INTERWORKING_ID = 0x28, + T62_PI_ACCEPT_OF_CDCL_PARAMS = 0x2c, + T62_PI_STORAGE_CAPACITY_NEGOT = 0x2d, + T62_PI_RX_ABILITY_JEOPARDIZED = 0x2e, + T62_PI_RESERVED = 0x2f, + T62_PI_DOCUMENT_TYPE_ID = 0x30, + T62_PI_REFLECT_PARAMETER_VALUES = 0x31, + T62_PI_REASON = 0x32, + /* T62_PGI_NON_BASIC_TELETEX_CAP */ + T62_PI_GRAPHIC_CHARACTER_SET = 0x41, + T62_PI_CONTROL_CHARACTER_SET = 0x49, + T62_PI_TELETEX_PAGE_FORMAT = 0x4a, + T62_PI_MISC_TELETEX_TERM_CAP = 0x4b, + T62_PI_CHARACTER_BOX_HEIGHT = 0x4d, + T62_PI_CHARACTER_BOX_WIDTH = 0x4e, +}; + +/* TODO: Table 9/10: Mandatory PI for each procedure */ + +/* 5.7.2.7 */ +enum t62_service_id { + T62_SERVICE_ID_TELEMATIC = 0x01, +}; + +/* 5.7.2.10 (reason) */ +enum t62_reason { + T62_REASON_NO_SPECIFIC_REASON = 0x00, + T62_REASON_TEMP_UNABLE_TO_ENTER_CONTINUE_SESSION = 0x01, + T62_REASON_EXPL_TEXT_MESSAGE_ONLY_FOR_USE_WITH_RSSN = 0x02, + T62_REASON_SEQUENCE_ERROR = 0x03, + T62_REASON_LOCAL_TERMINAL_ERROR = 0x05, + T62_REASON_UNRECOVERABLE_PROCEDURAL_ERROR = 0x06, +}; + +/* 5.7.3.7 Document type identifier */ +enum t62_document_type_id { + T62_DOC_T_OPERATOR = 0x01, + T62_DOC_T_CONTROL = 0x02, + T62_DOC_T_MONITOR = 0x03, +};