aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-05-25 16:21:35 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-07-31 16:58:26 +0200
commit0655cac6f1fbb0a669f064780a171a363ce8ef83 (patch)
tree17bda895ab0b476e73d74e9fdb6deb21dd38689b /src
parentb05d72d21b8cc91126cf45525f9010df6142e1c2 (diff)
sysmobts: Verify the structure of IPA and OML messages
Extend the router to verify that the message received is properly encoded. The code can deal with the basic structure of ETSI OML and vendor specific messages for ip.access and the osmocom project.
Diffstat (limited to 'src')
-rw-r--r--src/common/Makefile.am2
-rw-r--r--src/common/msg_utils.c174
-rw-r--r--src/common/oml.c12
-rw-r--r--src/osmo-bts-sysmo/oml_router.c18
4 files changed, 198 insertions, 8 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 716fad94..ea2a742b 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -5,4 +5,4 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS)
noinst_LIBRARIES = libbts.a
libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
rsl.c vty.c paging.c measurement.c amr.c lchan.c \
- load_indication.c pcu_sock.c handover.c \ No newline at end of file
+ load_indication.c pcu_sock.c handover.c msg_utils.c
diff --git a/src/common/msg_utils.c b/src/common/msg_utils.c
new file mode 100644
index 00000000..2d5ebd9b
--- /dev/null
+++ b/src/common/msg_utils.c
@@ -0,0 +1,174 @@
+/* (C) 2014 by sysmocom s.f.m.c. GmbH
+ *
+ * All Rights Reserved
+ *
+ * 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 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 <osmo-bts/msg_utils.h>
+#include <osmo-bts/logging.h>
+#include <osmo-bts/oml.h>
+
+#include <osmocom/gsm/protocol/ipaccess.h>
+#include <osmocom/gsm/protocol/gsm_12_21.h>
+#include <osmocom/core/msgb.h>
+
+#include <arpa/inet.h>
+
+
+static int check_fom(struct abis_om_hdr *omh, size_t len)
+{
+ if (omh->length != len) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect OM hdr length value %d %zu\n",
+ omh->length, len);
+ return -1;
+ }
+
+ if (len < sizeof(struct abis_om_fom_hdr)) {
+ LOGP(DL1C, LOGL_ERROR, "FOM header insufficient space %zu %zu\n",
+ len, sizeof(struct abis_om_fom_hdr));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int check_manuf(struct msgb *msg, struct abis_om_hdr *omh, size_t msg_size)
+{
+ int type;
+ size_t size;
+
+ if (msg_size < 1) {
+ LOGP(DL1C, LOGL_ERROR, "No ManId Length Indicator %zu\n",
+ msg_size);
+ return -1;
+ }
+
+ if (omh->data[0] >= msg_size - 1) {
+ LOGP(DL1C, LOGL_ERROR,
+ "Insufficient message space for this ManId Length %d %zu\n",
+ omh->data[0], msg_size - 1);
+ return -1;
+ }
+
+ if (omh->data[0] == sizeof(oml_ipa_magic) &&
+ strncmp(oml_ipa_magic, (const char *)omh->data + 1,
+ sizeof(oml_ipa_magic)) == 0) {
+ type = OML_MSG_TYPE_IPA;
+ size = sizeof(oml_ipa_magic) + 1;
+ } else if (omh->data[0] == sizeof(oml_osmo_magic) &&
+ strncmp(oml_osmo_magic, (const char *) omh->data + 1,
+ sizeof(oml_osmo_magic)) == 0) {
+ type = OML_MSG_TYPE_OSMO;
+ size = sizeof(oml_osmo_magic) + 1;
+ } else {
+ LOGP(DL1C, LOGL_ERROR, "Manuf Label Unknown\n");
+ return -1;
+ }
+
+ /* we have verified that the vendor string fits */
+ msg->l3h = omh->data + size;
+ if (check_fom(omh, msgb_l3len(msg)) != 0)
+ return -1;
+ return type;
+}
+
+/**
+ * Return 0 in case the IPA structure is okay and in this
+ * case the l2h will be set to the beginning of the data.
+ */
+int msg_verify_ipa_structure(struct msgb *msg)
+{
+ struct ipaccess_head *hh;
+
+ if (msgb_l1len(msg) < sizeof(struct ipaccess_head)) {
+ LOGP(DL1C, LOGL_ERROR,
+ "Ipa header insufficient space %d %d\n",
+ msgb_l1len(msg), sizeof(struct ipaccess_head));
+ return -1;
+ }
+
+ hh = (struct ipaccess_head *) msg->l1h;
+
+ if (hh->proto != IPAC_PROTO_OML) {
+ LOGP(DL1C, LOGL_ERROR,
+ "Incorrect ipa header protocol 0x%x 0x%x\n",
+ hh->proto, IPAC_PROTO_OML);
+ return -1;
+ }
+
+ if (ntohs(hh->len) != msgb_l1len(msg) - sizeof(struct ipaccess_head)) {
+ LOGP(DL1C, LOGL_ERROR,
+ "Incorrect ipa header msg size %d %d\n",
+ ntohs(hh->len), msgb_l1len(msg) - sizeof(struct ipaccess_head));
+ return -1;
+ }
+
+ msg->l2h = hh->data;
+ return 0;
+}
+
+/**
+ * \brief Verify the structure of the OML message and set l3h
+ *
+ * This function verifies that the data in \param in msg is a proper
+ * OML message. This code assumes that msg->l2h points to the
+ * beginning of the OML message. In the successful case the msg->l3h
+ * will be set and will point to the FOM header. The value is undefined
+ * in all other cases.
+ *
+ * \param msg The message to analyze starting from msg->l2h.
+ * \return In case the structure is correct a positive number will be
+ * returned and msg->l3h will point to the FOM. The number is a
+ * classification of the vendor type of the message.
+ */
+int msg_verify_oml_structure(struct msgb *msg)
+{
+ struct abis_om_hdr *omh;
+
+ if (msgb_l2len(msg) < sizeof(*omh)) {
+ LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n",
+ msgb_l2len(msg), sizeof(*omh));
+ return -1;
+ }
+
+ omh = (struct abis_om_hdr *) msg->l2h;
+ if (omh->mdisc != ABIS_OM_MDISC_FOM &&
+ omh->mdisc != ABIS_OM_MDISC_MANUF) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x\n",
+ omh->mdisc);
+ return -1;
+ }
+
+ if (omh->placement != ABIS_OM_PLACEMENT_ONLY) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n",
+ omh->placement, ABIS_OM_PLACEMENT_ONLY);
+ return -1;
+ }
+
+ if (omh->sequence != 0) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n",
+ omh->sequence);
+ return -1;
+ }
+
+ if (omh->mdisc == ABIS_OM_MDISC_MANUF)
+ return check_manuf(msg, omh, msgb_l2len(msg) - sizeof(*omh));
+
+ msg->l3h = omh->data;
+ if (check_fom(omh, msgb_l3len(msg)) != 0)
+ return -1;
+ return OML_MSG_TYPE_ETSI;
+}
diff --git a/src/common/oml.c b/src/common/oml.c
index b7c12f7c..2d690d63 100644
--- a/src/common/oml.c
+++ b/src/common/oml.c
@@ -92,7 +92,9 @@ static struct tlv_definition abis_nm_att_tlvdef_ipa = {
};
/* ip.access nanoBTS specific commands */
-static const char ipaccess_magic[] = "com.ipaccess";
+const char oml_ipa_magic[] = "com.ipaccess";
+const char oml_osmo_magic[] = "org.osmocom";
+
static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg);
/*
@@ -165,9 +167,9 @@ int oml_send_msg(struct msgb *msg, int is_manuf)
if (is_manuf) {
/* length byte, string + 0 termination */
- uint8_t *manuf = msgb_push(msg, 1 + sizeof(ipaccess_magic));
- manuf[0] = strlen(ipaccess_magic)+1;
- memcpy(manuf+1, ipaccess_magic, strlen(ipaccess_magic));
+ uint8_t *manuf = msgb_push(msg, 1 + sizeof(oml_ipa_magic));
+ manuf[0] = strlen(oml_ipa_magic)+1;
+ memcpy(manuf+1, oml_ipa_magic, strlen(oml_ipa_magic));
}
/* Push the main OML header and send it off */
@@ -1048,7 +1050,7 @@ static int down_mom(struct gsm_bts *bts, struct msgb *msg)
return -EIO;
}
- if (strncmp((char *)&oh->data[1], ipaccess_magic, idstrlen)) {
+ if (strncmp((char *)&oh->data[1], oml_ipa_magic, idstrlen)) {
LOGP(DOML, LOGL_ERROR, "Manufacturer OML message != ipaccess not supported\n");
return -EINVAL;
}
diff --git a/src/osmo-bts-sysmo/oml_router.c b/src/osmo-bts-sysmo/oml_router.c
index 64b36840..4af20d50 100644
--- a/src/osmo-bts-sysmo/oml_router.c
+++ b/src/osmo-bts-sysmo/oml_router.c
@@ -24,6 +24,7 @@
#include <osmo-bts/bts.h>
#include <osmo-bts/logging.h>
#include <osmo-bts/oml.h>
+#include <osmo-bts/msg_utils.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/select.h>
@@ -51,9 +52,22 @@ static int oml_router_read_cb(struct osmo_fd *fd, unsigned int what)
goto err;
}
- msgb_put(msg, rc);
+ msg->l1h = msgb_put(msg, rc);
+ rc = msg_verify_ipa_structure(msg);
+ if (rc < 0) {
+ LOGP(DL1C, LOGL_ERROR,
+ "OML Router: Invalid IPA message rc(%d)\n", rc);
+ goto err;
+ }
+
+ rc = msg_verify_oml_structure(msg);
+ if (rc < 0) {
+ LOGP(DL1C, LOGL_ERROR,
+ "OML Router: Invalid OML message rc(%d)\n", rc);
+ goto err;
+ }
- /* todo analyze and dispatch message */
+ /* todo dispatch message */
err:
msgb_free(msg);