aboutsummaryrefslogtreecommitdiffstats
path: root/src/xua_msg.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-03-23 12:19:00 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-03-23 12:28:06 +0100
commit7046633c02d15939d4953f1860f38be28f42667e (patch)
treed3af5fcf1c4d886f654d27cc747e8ce4decb1ae2 /src/xua_msg.c
parent4d244d3c31486f4e353dc997c92fa46129d82406 (diff)
xua: Generalize the m2ua_msg and call it xua_msg
Generalize, this requires various API modifications but that is the most sane path forward.
Diffstat (limited to 'src/xua_msg.c')
-rw-r--r--src/xua_msg.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/src/xua_msg.c b/src/xua_msg.c
new file mode 100644
index 0000000..e10b942
--- /dev/null
+++ b/src/xua_msg.c
@@ -0,0 +1,184 @@
+/* Routines for generating and parsing messages */
+/* (C) 2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sigtran/xua_msg.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/talloc.h>
+
+#include <arpa/inet.h>
+
+#include <string.h>
+
+static void *tall_xua;
+static int DXUA = -1;
+
+struct xua_msg *xua_msg_alloc(void)
+{
+ struct xua_msg *msg;
+
+ msg = talloc_zero(tall_xua, struct xua_msg);
+ if (!msg) {
+ LOGP(DXUA, LOGL_ERROR, "Failed to allocate.\n");
+ return NULL;
+ }
+
+ INIT_LLIST_HEAD(&msg->headers);
+ return msg;
+}
+
+void xua_msg_free(struct xua_msg *msg)
+{
+ talloc_free(msg);
+}
+
+int xua_msg_add_data(struct xua_msg *msg, uint16_t tag,
+ uint16_t len, uint8_t *dat)
+{
+ struct xua_msg_part *part;
+
+ part = talloc_zero(msg, struct xua_msg_part);
+ if (!part)
+ return -1;
+
+ part->tag = tag;
+ part->len = len;
+
+ /* do we have any data? */
+ if (part->len != 0) {
+ part->dat = talloc_memdup(part, dat, len);
+ if (!part->dat) {
+ talloc_free(part);
+ return -1;
+ }
+ }
+
+ llist_add_tail(&part->entry, &msg->headers);
+ return 0;
+}
+
+struct xua_msg_part *xua_msg_find_tag(struct xua_msg *xua, uint16_t tag)
+{
+ struct xua_msg_part *part;
+
+ llist_for_each_entry(part, &xua->headers, entry)
+ if (part->tag == tag)
+ return part;
+
+ return NULL;
+}
+
+struct xua_msg *xua_from_msg(const int version, uint16_t len, uint8_t *data)
+{
+ struct xua_parameter_hdr *par;
+ struct xua_common_hdr *hdr;
+ struct xua_msg *msg;
+ uint16_t pos, par_len, padding;
+ int rc;
+
+ msg = xua_msg_alloc();
+ if (!msg)
+ return NULL;
+
+ if (len < sizeof(*hdr))
+ goto fail;
+
+ hdr = (struct xua_common_hdr *) data;
+ if (hdr->version != version)
+ goto fail;
+ if (ntohl(hdr->msg_length) > len)
+ goto fail;
+
+ msg->hdr = *hdr;
+ pos = sizeof(*hdr);
+
+ while (pos + sizeof(*par) < len) {
+ par = (struct xua_parameter_hdr *) &data[pos];
+ par_len = ntohs(par->len);
+
+ if (pos + par_len > len || par_len < 4)
+ goto fail;
+
+ rc = xua_msg_add_data(msg, ntohs(par->tag),
+ par_len - 4, par->data);
+ if (rc != 0)
+ goto fail;
+
+ pos += par_len;
+
+ /* move over the padding */
+ padding = (4 - (par_len % 4)) & 0x3;
+ pos += padding;
+ }
+
+ /* TODO: parse */
+ return msg;
+
+fail:
+ LOGP(DXUA, LOGL_ERROR, "Failed to parse.\n");
+ xua_msg_free(msg);
+ return NULL;
+}
+
+struct msgb *xua_to_msg(const int version, struct xua_msg *xua)
+{
+ struct xua_msg_part *part;
+ struct xua_common_hdr *hdr;
+ struct msgb *msg;
+ uint8_t rest;
+
+ msg = msgb_alloc_headroom(2048, 512, "xua msg");
+ if (!msg) {
+ LOGP(DXUA, LOGL_ERROR, "Failed to allocate.\n");
+ return NULL;
+ }
+
+ msg->l2h = msgb_put(msg, sizeof(*hdr));
+ hdr = (struct xua_common_hdr *) msg->l2h;
+ memcpy(hdr, &xua->hdr, sizeof(*hdr));
+
+ /* make sure that is right */
+ hdr->version = version;
+ hdr->spare = 0;
+
+ llist_for_each_entry(part, &xua->headers, entry) {
+ msgb_put_u16(msg, part->tag);
+ msgb_put_u16(msg, part->len + 4);
+ if (part->dat) {
+ uint8_t *dat = msgb_put(msg, part->len);
+ memcpy(dat, part->dat, part->len);
+
+ /* padding */
+ rest = (4 - (part->len % 4)) & 0x3;
+ if (rest > 0) {
+ dat = msgb_put(msg, rest);
+ memset(dat, 0, rest);
+ }
+ }
+ }
+
+ /* update the size of the data */
+ hdr->msg_length = htonl(msgb_l2len(msg));
+ return msg;
+}
+
+void xua_set_log_area(int log_area)
+{
+ DXUA = log_area;
+}