From 6023bcae16b1dfb21f0b515de4aba8669e006b0f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 3 Apr 2017 16:37:38 +0200 Subject: xua_msg: Add concept of xua_msg_class and xua_msg_dialect A xua_msg_class repreents one xUA message class (like M3UA XFER or SUA CL). A dialect is then something like SUA or M3UA, each consisting of as many as 256 message classes. Each class contains value_strings of the individual messages, as well as constraint information on mandatory IEs for each message. Change-Id: Ib538aca295b7b50132bc814b2d7b56cbe5d65bfc --- include/osmocom/sigtran/xua_msg.h | 24 +++++++++ src/xua_msg.c | 106 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/include/osmocom/sigtran/xua_msg.h b/include/osmocom/sigtran/xua_msg.h index 23f92c5..6e98409 100644 --- a/include/osmocom/sigtran/xua_msg.h +++ b/include/osmocom/sigtran/xua_msg.h @@ -42,6 +42,23 @@ struct xua_msg_part { /* TODO: keep small data in the struct for perf reasons */ }; +struct xua_msg_class { + const char *name; + const struct value_string *msgt_names; + const struct value_string *iei_names; + const uint16_t *mand_ies[256]; +}; + +struct xua_dialect { + const char *name; + uint16_t port; + uint16_t ppid; + int log_subsys; + const struct xua_msg_class *class[256]; +}; + +extern const struct xua_dialect xua_dialect_sua; +extern const struct xua_dialect xua_dialect_m3ua; extern int DXUA; @@ -66,3 +83,10 @@ int xua_msg_add_u32(struct xua_msg *xua, uint16_t iei, uint32_t val); uint32_t xua_msg_part_get_u32(struct xua_msg_part *part); uint32_t xua_msg_get_u32(struct xua_msg *xua, uint16_t iei); int xua_msg_add_sccp_addr(struct xua_msg *xua, uint16_t iei, const struct osmo_sccp_addr *addr); + +const char *xua_class_msg_name(const struct xua_msg_class *xmc, uint16_t msg_type); +const char *xua_class_iei_name(const struct xua_msg_class *xmc, uint16_t iei); +char *xua_hdr_dump(struct xua_msg *xua, const struct xua_dialect *dialect); +char *xua_msg_dump(struct xua_msg *xua, const struct xua_dialect *dialect); +int xua_dialect_check_all_mand_ies(const struct xua_dialect *dialect, struct xua_msg *xua); + diff --git a/src/xua_msg.c b/src/xua_msg.c index 71511a9..1084622 100644 --- a/src/xua_msg.c +++ b/src/xua_msg.c @@ -301,3 +301,109 @@ int xua_msg_add_sccp_addr(struct xua_msg *xua, uint16_t iei, const struct osmo_s return rc; } + +const char *xua_class_msg_name(const struct xua_msg_class *xmc, uint16_t msg_type) +{ + static char class_buf[64]; + + if (xmc && xmc->msgt_names) + return get_value_string(xmc->msgt_names, msg_type); + else { + snprintf(class_buf, sizeof(class_buf), "Unknown 0x%04x", msg_type); + return class_buf; + } +} + +const char *xua_class_iei_name(const struct xua_msg_class *xmc, uint16_t iei) +{ + static char iei_buf[64]; + + if (xmc && xmc->iei_names) + return get_value_string(xmc->iei_names, iei); + else { + snprintf(iei_buf, sizeof(iei_buf), "Unknown 0x%04x", iei); + return iei_buf; + } +} + +char *xua_hdr_dump(struct xua_msg *xua, const struct xua_dialect *dialect) +{ + const struct xua_msg_class *xmc = NULL; + static char buf[128]; + + if (dialect) + xmc = dialect->class[xua->hdr.msg_class]; + if (!xmc) + snprintf(buf, sizeof(buf), "%u:%u", xua->hdr.msg_class, xua->hdr.msg_type); + else + snprintf(buf, sizeof(buf), "%s:%s", xmc->name, + xua_class_msg_name(xmc, xua->hdr.msg_type)); + return buf; +} + +int xua_dialect_check_all_mand_ies(const struct xua_dialect *dialect, struct xua_msg *xua) +{ + uint8_t msg_class = xua->hdr.msg_class; + uint8_t msg_type = xua->hdr.msg_type; + const struct xua_msg_class *xmc = dialect->class[msg_class]; + const uint16_t *ies; + uint16_t ie; + + /* unknown class? */ + if (!xmc) + return 1; + + ies = xmc->mand_ies[msg_type]; + /* no mandatory IEs? */ + if (!ies) + return 1; + + for (ie = *ies; ie; ie = *ies++) { + if (!xua_msg_find_tag(xua, ie)) { + LOGP(dialect->log_subsys, LOGL_ERROR, + "%s Message %s:%s should " + "contain IE %s, but doesn't\n", + dialect->name, xmc->name, + xua_class_msg_name(xmc, msg_type), + xua_class_iei_name(xmc, ie)); + return 0; + } + } + + return 1; +} + +static void append_to_buf(char *buf, bool *comma, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (!comma || *comma == true) { + strcat(buf, ","); + } else if (comma) + *comma = true; + vsprintf(buf+strlen(buf), fmt, ap); + va_end(ap); +} + +char *xua_msg_dump(struct xua_msg *xua, const struct xua_dialect *dialect) +{ + static char buf[1024]; + struct xua_msg_part *part; + const struct xua_msg_class *xmc = NULL; + + if (dialect) + xmc = dialect->class[xua->hdr.msg_class]; + + buf[0] = '\0'; + + append_to_buf(buf, NULL, "HDR=(%s,V=%u,LEN=%u)", + xua_hdr_dump(xua, dialect), + xua->hdr.version, xua->hdr.msg_length); + buf[0] = ' '; + llist_for_each_entry(part, &xua->headers, entry) + append_to_buf(buf, NULL, "\n\tPART(T=%s,L=%u,D=%s)", + xua_class_iei_name(xmc, part->tag), part->len, + osmo_hexdump_nospc(part->dat, part->len)); + return buf; +} -- cgit v1.2.3