<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/20333">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add BSSLAP coding for Location Services<br><br>BSSLAP: there are APDUs transferred in BSSMAP-LE Connection Oriented<br>Information messages on Lb between BSC and SMLC.<br>Add BSSLAP coding for these APDU messages:<br>- TA Layer3<br>- TA Request<br>- TA Response, possibly containing Location Estimate coded in GAD<br>- Reject<br>- Reset (for intra-BSS handover during TA Request)<br>- Abort (for inter-BSS handover)<br><br>Add encoding and decoding tests.<br><br>Change-Id: I6409c4bcac402dc7626a3afce9081c59cd715fe8<br>---<br>M include/Makefile.am<br>A include/osmocom/gsm/bsslap.h<br>A include/osmocom/gsm/protocol/gsm_48_071.h<br>A include/osmocom/gsm/protocol/gsm_49_031.h<br>M src/gsm/Makefile.am<br>A src/gsm/bsslap.c<br>M src/gsm/libosmogsm.map<br>M tests/Makefile.am<br>A tests/bsslap/bsslap_test.c<br>A tests/bsslap/bsslap_test.ok<br>M tests/testsuite.at<br>11 files changed, 698 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/Makefile.am b/include/Makefile.am</span><br><span>index fc1eec3..19d4043 100644</span><br><span>--- a/include/Makefile.am</span><br><span>+++ b/include/Makefile.am</span><br><span>@@ -92,6 +92,7 @@</span><br><span>                        osmocom/coding/gsm0503_interleaving.h \</span><br><span>                        osmocom/coding/gsm0503_coding.h \</span><br><span>                        osmocom/coding/gsm0503_amr_dtx.h \</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmocom/gsm/bsslap.h \</span><br><span>                        osmocom/gsm/gad.h \</span><br><span>                        osmocom/gsm/gsm0808.h \</span><br><span>                        osmocom/gsm/gsm29205.h \</span><br><span>@@ -134,6 +135,8 @@</span><br><span>                     osmocom/gsm/protocol/gsm_29_118.h \</span><br><span>                        osmocom/gsm/protocol/gsm_44_318.h \</span><br><span>                        osmocom/gsm/protocol/gsm_48_049.h \</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmocom/gsm/protocol/gsm_48_071.h \</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmocom/gsm/protocol/gsm_49_031.h \</span><br><span>                        osmocom/gsm/protocol/ipaccess.h \</span><br><span>                        osmocom/gsm/protocol/smpp34_osmocom.h \</span><br><span>                        osmocom/gsm/rsl.h \</span><br><span>diff --git a/include/osmocom/gsm/bsslap.h b/include/osmocom/gsm/bsslap.h</span><br><span>new file mode 100644</span><br><span>index 0000000..b2174b3</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/gsm/bsslap.h</span><br><span>@@ -0,0 +1,57 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \addtogroup bsslap</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @{</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \file bsslap.h</span><br><span style="color: hsl(120, 100%, 40%);">+ * Message encoding and decoding for 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Neels Hofmeyr <neels@hofmeyr.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_48_071.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_49_031.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_bsslap_err {</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       enum bsslap_msgt msg_type;</span><br><span style="color: hsl(120, 100%, 40%);">+    enum bsslap_iei iei;</span><br><span style="color: hsl(120, 100%, 40%);">+  enum lcs_cause cause;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *logmsg;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string osmo_bsslap_msgt_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+static inline const char *osmo_bsslap_msgt_name(enum bsslap_msgt val)</span><br><span style="color: hsl(120, 100%, 40%);">+{ return get_value_string(osmo_bsslap_msgt_names, val); }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string osmo_bsslap_iei_names[];</span><br><span style="color: hsl(120, 100%, 40%);">+static inline const char *osmo_bsslap_iei_name(enum bsslap_iei val)</span><br><span style="color: hsl(120, 100%, 40%);">+{ return get_value_string(osmo_bsslap_iei_names, val); }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_bsslap_enc(struct msgb *msg, const struct bsslap_pdu *pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_bsslap_dec(struct bsslap_pdu *pdu,</span><br><span style="color: hsl(120, 100%, 40%);">+                struct osmo_bsslap_err **err, void *err_ctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                  const uint8_t *data, size_t len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/include/osmocom/gsm/protocol/gsm_48_071.h b/include/osmocom/gsm/protocol/gsm_48_071.h</span><br><span>new file mode 100644</span><br><span>index 0000000..fb9653a</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/gsm/protocol/gsm_48_071.h</span><br><span>@@ -0,0 +1,122 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \defgroup bsslap 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP).</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @{</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \file gsm_48_071.h</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Neels Hofmeyr <neels@hofmeyr.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/protocol/gsm_04_08.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum bsslap_msgt {</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_MSGT_TA_REQUEST = 0x1,</span><br><span style="color: hsl(120, 100%, 40%);">+ BSSLAP_MSGT_TA_RESPONSE = 0x2,</span><br><span style="color: hsl(120, 100%, 40%);">+        BSSLAP_MSGT_REJECT = 0xa,</span><br><span style="color: hsl(120, 100%, 40%);">+     BSSLAP_MSGT_RESET = 0xb,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_MSGT_ABORT = 0xc,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_MSGT_TA_LAYER3 = 0xd,</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_MSGT_MS_POS_CMD = 0xf,</span><br><span style="color: hsl(120, 100%, 40%);">+ BSSLAP_MSGT_MS_POS_RESP = 0x10,</span><br><span style="color: hsl(120, 100%, 40%);">+       BSSLAP_MSGT_UTDOA_REQ = 0x11,</span><br><span style="color: hsl(120, 100%, 40%);">+ BSSLAP_MSGT_UTDOA_RESP = 0x12,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum bsslap_cause {</span><br><span style="color: hsl(120, 100%, 40%);">+     BSSLAP_CAUSE_CONGESTION = 0x0,</span><br><span style="color: hsl(120, 100%, 40%);">+        BSSLAP_CAUSE_CHAN_MODE_NOT_SUPP = 0x1,</span><br><span style="color: hsl(120, 100%, 40%);">+        BSSLAP_CAUSE_POS_PROC_NOT_SUPP = 0x2,</span><br><span style="color: hsl(120, 100%, 40%);">+ BSSLAP_CAUSE_OTHER_RADIO_EVT_FAIL = 0x3,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_CAUSE_INTRA_BSS_HO = 0x4,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_CAUSE_SUPERV_TIMER_EXPIRED = 0x5,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_CAUSE_INTER_BSS_HO = 0x6,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_CAUSE_LOSS_SIG_CONN_MS = 0x7,</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_CAUSE_INCORR_SERV_CELL_ID = 0x8,</span><br><span style="color: hsl(120, 100%, 40%);">+       BSSLAP_CAUSE_BSSAP_LE_SEGMENT_ERR = 0x9,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_CAUSE_CONCUR_POS_PROC_NOT_EN = 0xa,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum bsslap_iei {</span><br><span style="color: hsl(120, 100%, 40%);">+   BSSLAP_IEI_TA = 0x1,</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_IEI_CELL_ID = 0x9,</span><br><span style="color: hsl(120, 100%, 40%);">+     BSSLAP_IEI_CHAN_DESC = 0x10,</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_IEI_MEAS_REP = 0x14,</span><br><span style="color: hsl(120, 100%, 40%);">+   BSSLAP_IEI_CAUSE = 0x18,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_IEI_RRLP_FLAG = 0x19,</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_IEI_RRLP = 0x1b,</span><br><span style="color: hsl(120, 100%, 40%);">+       BSSLAP_IEI_CELL_ID_LIST = 0x1c,</span><br><span style="color: hsl(120, 100%, 40%);">+       BSSLAP_IEI_ENH_MEAS_REP = 0x1d,</span><br><span style="color: hsl(120, 100%, 40%);">+       BSSLAP_IEI_LAC = 0x1e,</span><br><span style="color: hsl(120, 100%, 40%);">+        BSSLAP_IEI_FREQ_LIST = 0x21,</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_IEI_MS_POWER = 0x22,</span><br><span style="color: hsl(120, 100%, 40%);">+   BSSLAP_IEI_DELTA_TIMER = 0x23,</span><br><span style="color: hsl(120, 100%, 40%);">+        BSSLAP_IEI_SERVING_CELL_ID = 0x24,</span><br><span style="color: hsl(120, 100%, 40%);">+    BSSLAP_IEI_ENCR_KEY = 0x25,</span><br><span style="color: hsl(120, 100%, 40%);">+   BSSLAP_IEI_CIPH_MODE_SET = 0x26,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_IEI_CHAN_MODE = 0x27,</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_IEI_MR_CONFIG = 0x28,</span><br><span style="color: hsl(120, 100%, 40%);">+  BSSLAP_IEI_POLLING_REPETITION = 0x29,</span><br><span style="color: hsl(120, 100%, 40%);">+ BSSLAP_IEI_PACKET_CHAN_DESC = 0x2a,</span><br><span style="color: hsl(120, 100%, 40%);">+   BSSLAP_IEI_TLLI = 0x2b,</span><br><span style="color: hsl(120, 100%, 40%);">+       BSSLAP_IEI_TFI = 0x2c,</span><br><span style="color: hsl(120, 100%, 40%);">+        BSSLAP_IEI_TBF_START_TIME = 0x2d,</span><br><span style="color: hsl(120, 100%, 40%);">+     BSSLAP_IEI_PWRUP_START_TIME = 0x2e,</span><br><span style="color: hsl(120, 100%, 40%);">+   BSSLAP_IEI_LONG_ENCR_KEY = 0x2f,</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSLAP_IEI_CONCUR_POS_PROC_F = 0x30,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bsslap_ta_response {</span><br><span style="color: hsl(120, 100%, 40%);">+       uint16_t cell_id;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t ta;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bool more_items; /*!< always set this to false */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bsslap_ta_layer3 {</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t ta;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bool more_items; /*!< always set this to false */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bsslap_reset {</span><br><span style="color: hsl(120, 100%, 40%);">+     uint16_t cell_id;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t ta;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm48_chan_desc chan_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+     enum bsslap_cause cause;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    bool more_items; /*!< always set this to false */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bsslap_pdu {</span><br><span style="color: hsl(120, 100%, 40%);">+       enum bsslap_msgt msg_type;</span><br><span style="color: hsl(120, 100%, 40%);">+    union {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* ta_request: a TA Request message consists only of the message type. */</span><br><span style="color: hsl(120, 100%, 40%);">+             struct bsslap_ta_response ta_response;</span><br><span style="color: hsl(120, 100%, 40%);">+                enum bsslap_cause reject;</span><br><span style="color: hsl(120, 100%, 40%);">+             struct bsslap_reset reset;</span><br><span style="color: hsl(120, 100%, 40%);">+            enum bsslap_cause abort;</span><br><span style="color: hsl(120, 100%, 40%);">+              struct bsslap_ta_layer3 ta_layer3;</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/include/osmocom/gsm/protocol/gsm_49_031.h b/include/osmocom/gsm/protocol/gsm_49_031.h</span><br><span>new file mode 100644</span><br><span>index 0000000..b44a07e</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/gsm/protocol/gsm_49_031.h</span><br><span>@@ -0,0 +1,61 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \defgroup bssmap_le 3GPP TS 49.031 BSSMAP-LE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @{</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \file gsm_49_031.h</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Neels Hofmeyr <neels@hofmeyr.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! 3GPP TS 49.031 10.13 LCS Cause, also in 3GPP TS 48.008 3.2.2.66, which simply refers to the former. */</span><br><span style="color: hsl(120, 100%, 40%);">+enum lcs_cause {</span><br><span style="color: hsl(120, 100%, 40%);">+    LCS_CAUSE_UNSPECIFIED = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+    LCS_CAUSE_SYSTEM_FAILURE = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+ LCS_CAUSE_PROTOCOL_ERROR = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+ LCS_CAUSE_DATA_MISSING_IN_REQ = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+    LCS_CAUSE_UNEXP_DATA_IN_REQ = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+      LCS_CAUSE_POS_METH_FAILURE = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+       LCS_CAUSE_TGT_MS_UNREACHABLE = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+     LCS_CAUSE_REQUEST_ABORTED = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+        LCS_CAUSE_FACILITY_NOTSUPP = 8,</span><br><span style="color: hsl(120, 100%, 40%);">+       LCS_CAUSE_INTER_BSC_HO = 9,</span><br><span style="color: hsl(120, 100%, 40%);">+   LCS_CAUSE_INTRA_BSC_HO = 10,</span><br><span style="color: hsl(120, 100%, 40%);">+  LCS_CAUSE_CONGESTION = 11,</span><br><span style="color: hsl(120, 100%, 40%);">+    LCS_CAUSE_INTER_NSE_CHG = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+ LCS_CAUSE_RA_UPDAT = 13,</span><br><span style="color: hsl(120, 100%, 40%);">+      LCS_CAUSE_PTMSI_REALLOC = 14,</span><br><span style="color: hsl(120, 100%, 40%);">+ LCS_CAUSE_GPRS_SUSPENSION = 15,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! 3GPP TS 49.031 10.13 LCS Cause, also in 3GPP TS 48.008 3.2.2.66, which simply refers to the former. */</span><br><span style="color: hsl(120, 100%, 40%);">+struct lcs_cause_ie {</span><br><span style="color: hsl(120, 100%, 40%);">+      bool present;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum lcs_cause cause_val;</span><br><span style="color: hsl(120, 100%, 40%);">+     bool diag_val_present;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t diag_val;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am</span><br><span>index 4fa940b..465bae1 100644</span><br><span>--- a/src/gsm/Makefile.am</span><br><span>+++ b/src/gsm/Makefile.am</span><br><span>@@ -33,7 +33,7 @@</span><br><span>                      gsup.c gsup_sms.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \</span><br><span>                  gsm23003.c gsm23236.c mncc.c bts_features.c oap_client.c \</span><br><span>                   gsm29118.c gsm48_rest_octets.c cbsp.c gsm48049.c i460_mux.c \</span><br><span style="color: hsl(0, 100%, 40%);">-                   gad.c</span><br><span style="color: hsl(120, 100%, 40%);">+                 gad.c bsslap.c</span><br><span> libgsmint_la_LDFLAGS = -no-undefined</span><br><span> libgsmint_la_LIBADD = $(top_builddir)/src/libosmocore.la</span><br><span> </span><br><span>diff --git a/src/gsm/bsslap.c b/src/gsm/bsslap.c</span><br><span>new file mode 100644</span><br><span>index 0000000..7886da6</span><br><span>--- /dev/null</span><br><span>+++ b/src/gsm/bsslap.c</span><br><span>@@ -0,0 +1,329 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 48.071 BSSLAP protocol definitions */</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: Neels Hofmeyr <neels@hofmeyr.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/bsslap.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/tlv.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \addtogroup bsslap</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @{</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \file bsslap.c</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Message encoding and decoding for 3GPP TS 48.071 BSSLAP protocol.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct tlv_definition osmo_bsslap_tlvdef = {</span><br><span style="color: hsl(120, 100%, 40%);">+       .def = {</span><br><span style="color: hsl(120, 100%, 40%);">+      [BSSLAP_IEI_TA] = { TLV_TYPE_TV },</span><br><span style="color: hsl(120, 100%, 40%);">+    [BSSLAP_IEI_CELL_ID] = { TLV_TYPE_FIXED, 2 },</span><br><span style="color: hsl(120, 100%, 40%);">+ [BSSLAP_IEI_CHAN_DESC] = { TLV_TYPE_FIXED, 3 },</span><br><span style="color: hsl(120, 100%, 40%);">+       [BSSLAP_IEI_MEAS_REP] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+     [BSSLAP_IEI_CAUSE] = { TLV_TYPE_TV },</span><br><span style="color: hsl(120, 100%, 40%);">+ [BSSLAP_IEI_RRLP_FLAG] = { TLV_TYPE_TV },</span><br><span style="color: hsl(120, 100%, 40%);">+     [BSSLAP_IEI_RRLP] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+ [BSSLAP_IEI_CELL_ID_LIST] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+ [BSSLAP_IEI_ENH_MEAS_REP] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+ [BSSLAP_IEI_LAC] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+  [BSSLAP_IEI_FREQ_LIST] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+    [BSSLAP_IEI_MS_POWER] = { TLV_TYPE_TV },</span><br><span style="color: hsl(120, 100%, 40%);">+      [BSSLAP_IEI_DELTA_TIMER] = { TLV_TYPE_TV },</span><br><span style="color: hsl(120, 100%, 40%);">+   [BSSLAP_IEI_SERVING_CELL_ID] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+      [BSSLAP_IEI_ENCR_KEY] = { TLV_TYPE_FIXED, 8 },</span><br><span style="color: hsl(120, 100%, 40%);">+        [BSSLAP_IEI_CIPH_MODE_SET] = { TLV_TYPE_TV },</span><br><span style="color: hsl(120, 100%, 40%);">+ [BSSLAP_IEI_CHAN_MODE] = { TLV_TYPE_TV, 2 },</span><br><span style="color: hsl(120, 100%, 40%);">+  [BSSLAP_IEI_MR_CONFIG] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+    [BSSLAP_IEI_POLLING_REPETITION] = { TLV_TYPE_TV },</span><br><span style="color: hsl(120, 100%, 40%);">+    [BSSLAP_IEI_PACKET_CHAN_DESC] = { TLV_TYPE_FIXED, 4 },</span><br><span style="color: hsl(120, 100%, 40%);">+        [BSSLAP_IEI_TLLI] = { TLV_TYPE_FIXED, 4 },</span><br><span style="color: hsl(120, 100%, 40%);">+    [BSSLAP_IEI_TFI] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+  [BSSLAP_IEI_TBF_START_TIME] = { TLV_TYPE_FIXED, 2 },</span><br><span style="color: hsl(120, 100%, 40%);">+  [BSSLAP_IEI_PWRUP_START_TIME] = { TLV_TYPE_TLV },</span><br><span style="color: hsl(120, 100%, 40%);">+     [BSSLAP_IEI_LONG_ENCR_KEY] = { TLV_TYPE_FIXED, 16 },</span><br><span style="color: hsl(120, 100%, 40%);">+  [BSSLAP_IEI_CONCUR_POS_PROC_F] = { TLV_TYPE_TV },</span><br><span style="color: hsl(120, 100%, 40%);">+     },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEC_ERR(RC, MSG_TYPE, IEI, CAUSE, fmt, args...) do { \</span><br><span style="color: hsl(120, 100%, 40%);">+              if (err && !*err) { \</span><br><span style="color: hsl(120, 100%, 40%);">+                 *err = talloc_zero(err_ctx, struct osmo_bsslap_err); \</span><br><span style="color: hsl(120, 100%, 40%);">+                        **err = (struct osmo_bsslap_err){ \</span><br><span style="color: hsl(120, 100%, 40%);">+                           .rc = (RC), \</span><br><span style="color: hsl(120, 100%, 40%);">+                         .msg_type = (MSG_TYPE), \</span><br><span style="color: hsl(120, 100%, 40%);">+                             .iei = (IEI), \</span><br><span style="color: hsl(120, 100%, 40%);">+                               .cause = (CAUSE), \</span><br><span style="color: hsl(120, 100%, 40%);">+                           .logmsg = talloc_asprintf(*err, "Error decoding BSSLAP%s%s%s%s%s: " fmt, \</span><br><span style="color: hsl(120, 100%, 40%);">+                                                    (MSG_TYPE) >= 0 ? " " : "", \</span><br><span style="color: hsl(120, 100%, 40%);">+                                                          (MSG_TYPE) >= 0 ? osmo_bsslap_msgt_name(MSG_TYPE) : "", \</span><br><span style="color: hsl(120, 100%, 40%);">+                                                        (IEI) >= 0 ? ": " : "", \</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      (IEI) >= 0 ? osmo_bsslap_iei_name(IEI) : "", \</span><br><span style="color: hsl(120, 100%, 40%);">+                                                   (IEI) >= 0 ? " IE" : "", \</span><br><span style="color: hsl(120, 100%, 40%);">+##args), \</span><br><span style="color: hsl(120, 100%, 40%);">+                       }; \</span><br><span style="color: hsl(120, 100%, 40%);">+          } \</span><br><span style="color: hsl(120, 100%, 40%);">+           return RC; \</span><br><span style="color: hsl(120, 100%, 40%);">+  } while(0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void osmo_bsslap_ie_enc_cell_id(struct msgb *msg, uint16_t cell_id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   msgb_put_u8(msg, BSSLAP_IEI_CELL_ID);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_put_u16(msg, cell_id);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int osmo_bsslap_ie_dec_cell_id(uint16_t *cell_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  enum bsslap_msgt msgt, enum bsslap_iei iei,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   struct osmo_bsslap_err **err, void *err_ctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     if (len != 2)</span><br><span style="color: hsl(120, 100%, 40%);">+         DEC_ERR(-EINVAL, msgt, iei, LCS_CAUSE_UNSPECIFIED, "Expected 2 bytes, got %zu", len);</span><br><span style="color: hsl(120, 100%, 40%);">+       *cell_id = osmo_load16be(data);</span><br><span style="color: hsl(120, 100%, 40%);">+       return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void osmo_bsslap_ie_enc_ta(struct msgb *msg, uint8_t ta)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    msgb_put_u8(msg, BSSLAP_IEI_TA);</span><br><span style="color: hsl(120, 100%, 40%);">+      msgb_put_u8(msg, ta);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int osmo_bsslap_ie_dec_ta(uint8_t *ta,</span><br><span style="color: hsl(120, 100%, 40%);">+                              enum bsslap_msgt msgt, enum bsslap_iei iei,</span><br><span style="color: hsl(120, 100%, 40%);">+                           struct osmo_bsslap_err **err, void *err_ctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                          const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  if (len != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+         DEC_ERR(-EINVAL, msgt, iei, LCS_CAUSE_UNSPECIFIED, "Expected 1 byte, got %zu", len);</span><br><span style="color: hsl(120, 100%, 40%);">+        *ta = data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void osmo_bsslap_ie_enc_cause(struct msgb *msg, enum bsslap_cause cause)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    msgb_put_u8(msg, BSSLAP_IEI_CAUSE);</span><br><span style="color: hsl(120, 100%, 40%);">+   msgb_put_u8(msg, cause);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int osmo_bsslap_ie_dec_cause(enum bsslap_cause *cause,</span><br><span style="color: hsl(120, 100%, 40%);">+                              enum bsslap_msgt msgt, enum bsslap_iei iei,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   struct osmo_bsslap_err **err, void *err_ctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (len != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+         DEC_ERR(-EINVAL, msgt, iei, LCS_CAUSE_UNSPECIFIED, "Expected 1 byte, got %zu", len);</span><br><span style="color: hsl(120, 100%, 40%);">+        *cause = data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void osmo_bsslap_ie_enc_chan_desc(struct msgb *msg, const struct gsm48_chan_desc *chan_desc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gsm48_chan_desc *put_chan_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+        msgb_put_u8(msg, BSSLAP_IEI_CHAN_DESC);</span><br><span style="color: hsl(120, 100%, 40%);">+       put_chan_desc = (void*)msgb_put(msg, sizeof(*chan_desc));</span><br><span style="color: hsl(120, 100%, 40%);">+     *put_chan_desc = *chan_desc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int osmo_bsslap_ie_dec_chan_desc(struct gsm48_chan_desc *chan_desc,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 enum bsslap_msgt msgt, enum bsslap_iei iei,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   struct osmo_bsslap_err **err, void *err_ctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (len != sizeof(*chan_desc))</span><br><span style="color: hsl(120, 100%, 40%);">+                DEC_ERR(-EINVAL, msgt, iei, LCS_CAUSE_UNSPECIFIED, "Expected %zu bytes, got %zu",</span><br><span style="color: hsl(120, 100%, 40%);">+                   sizeof(*chan_desc), len);</span><br><span style="color: hsl(120, 100%, 40%);">+     *chan_desc = *(struct gsm48_chan_desc*)data;</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Encode BSSLAP PDU and append to msgb (3GPP TS 48.071).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] msg  msgb to append to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] pdu  PDU data to encode.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return number of bytes written, negative on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_bsslap_enc(struct msgb *msg, const struct bsslap_pdu *pdu)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t *old_tail = msg->tail;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   msgb_put_u8(msg, pdu->msg_type);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (pdu->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case BSSLAP_MSGT_TA_REQUEST:</span><br><span style="color: hsl(120, 100%, 40%);">+          /* The TA Request message contains only the message type. */</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case BSSLAP_MSGT_TA_RESPONSE:</span><br><span style="color: hsl(120, 100%, 40%);">+         osmo_bsslap_ie_enc_cell_id(msg, pdu->ta_response.cell_id);</span><br><span style="color: hsl(120, 100%, 40%);">+         osmo_bsslap_ie_enc_ta(msg, pdu->ta_response.ta);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case BSSLAP_MSGT_REJECT:</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_bsslap_ie_enc_cause(msg, pdu->reject);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case BSSLAP_MSGT_RESET:</span><br><span style="color: hsl(120, 100%, 40%);">+               osmo_bsslap_ie_enc_cell_id(msg, pdu->reset.cell_id);</span><br><span style="color: hsl(120, 100%, 40%);">+               osmo_bsslap_ie_enc_ta(msg, pdu->reset.ta);</span><br><span style="color: hsl(120, 100%, 40%);">+         osmo_bsslap_ie_enc_chan_desc(msg, &pdu->reset.chan_desc);</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_bsslap_ie_enc_cause(msg, pdu->reset.cause);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case BSSLAP_MSGT_ABORT:</span><br><span style="color: hsl(120, 100%, 40%);">+               osmo_bsslap_ie_enc_cause(msg, pdu->abort);</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case BSSLAP_MSGT_TA_LAYER3:</span><br><span style="color: hsl(120, 100%, 40%);">+           osmo_bsslap_ie_enc_ta(msg, pdu->ta_layer3.ta);</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return -ENOTSUP;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+     return (msg->tail - old_tail);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Decode BSSLAP PDU (3GPP TS 48.071).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] pdu  Write decoded values here.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] err  Returned pointer to error info, dynamically allocated; NULL to not return any.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] err_ctx  Talloc context to allocate err from, if required.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] data  Pointer to BSSLAP PDU raw data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] len  Data length to decode.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_bsslap_dec(struct bsslap_pdu *pdu,</span><br><span style="color: hsl(120, 100%, 40%);">+              struct osmo_bsslap_err **err, void *err_ctx,</span><br><span style="color: hsl(120, 100%, 40%);">+                  const uint8_t *data, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       const uint8_t *ies_start;</span><br><span style="color: hsl(120, 100%, 40%);">+     int ies_len;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct tlv_parsed tp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       *pdu = (struct bsslap_pdu){};</span><br><span style="color: hsl(120, 100%, 40%);">+ if (err)</span><br><span style="color: hsl(120, 100%, 40%);">+              *err = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEC_IE_MANDATORY(IEI, DEC_FUN, DEC_FUN_ARG) do { \</span><br><span style="color: hsl(120, 100%, 40%);">+            const struct tlv_p_entry *e; \</span><br><span style="color: hsl(120, 100%, 40%);">+                int rc; \</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!(e = TLVP_GET(&tp, IEI))) \</span><br><span style="color: hsl(120, 100%, 40%);">+                  DEC_ERR(-EINVAL, pdu->msg_type, IEI, LCS_CAUSE_DATA_MISSING_IN_REQ, "missing mandatory IE"); \</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = DEC_FUN(DEC_FUN_ARG, pdu->msg_type, IEI, err, err_ctx, e->val, e->len); \</span><br><span style="color: hsl(120, 100%, 40%);">+               if (rc) \</span><br><span style="color: hsl(120, 100%, 40%);">+                     DEC_ERR(rc, pdu->msg_type, IEI, LCS_CAUSE_UNSPECIFIED, "cannot parse IE"); \</span><br><span style="color: hsl(120, 100%, 40%);">+     } while (0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (len < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+               DEC_ERR(-EINVAL, -1, -1, LCS_CAUSE_UNSPECIFIED, "PDU too short: %zu b", len);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     pdu->msg_type = data[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pdu->msg_type == BSSLAP_MSGT_TA_REQUEST) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* The TA Request message contains only the message type. */</span><br><span style="color: hsl(120, 100%, 40%);">+          return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ies_start = &data[1];</span><br><span style="color: hsl(120, 100%, 40%);">+     ies_len = len - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (tlv_parse2(&tp, 1, &osmo_bsslap_tlvdef, ies_start, ies_len, 0, 0) <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                DEC_ERR(-EINVAL, pdu->msg_type, -1, LCS_CAUSE_UNSPECIFIED, "failed to parse TLV structure");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (pdu->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ case BSSLAP_MSGT_TA_RESPONSE:</span><br><span style="color: hsl(120, 100%, 40%);">+         DEC_IE_MANDATORY(BSSLAP_IEI_CELL_ID, osmo_bsslap_ie_dec_cell_id, &pdu->ta_response.cell_id);</span><br><span style="color: hsl(120, 100%, 40%);">+           DEC_IE_MANDATORY(BSSLAP_IEI_TA, osmo_bsslap_ie_dec_ta, &pdu->ta_response.ta);</span><br><span style="color: hsl(120, 100%, 40%);">+          return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   case BSSLAP_MSGT_REJECT:</span><br><span style="color: hsl(120, 100%, 40%);">+              DEC_IE_MANDATORY(BSSLAP_IEI_CAUSE, osmo_bsslap_ie_dec_cause, &pdu->reject);</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   case BSSLAP_MSGT_RESET:</span><br><span style="color: hsl(120, 100%, 40%);">+               DEC_IE_MANDATORY(BSSLAP_IEI_CELL_ID, osmo_bsslap_ie_dec_cell_id, &pdu->reset.cell_id);</span><br><span style="color: hsl(120, 100%, 40%);">+         DEC_IE_MANDATORY(BSSLAP_IEI_TA, osmo_bsslap_ie_dec_ta, &pdu->reset.ta);</span><br><span style="color: hsl(120, 100%, 40%);">+                DEC_IE_MANDATORY(BSSLAP_IEI_CHAN_DESC, osmo_bsslap_ie_dec_chan_desc, &pdu->reset.chan_desc);</span><br><span style="color: hsl(120, 100%, 40%);">+           DEC_IE_MANDATORY(BSSLAP_IEI_CAUSE, osmo_bsslap_ie_dec_cause, &pdu->reset.cause);</span><br><span style="color: hsl(120, 100%, 40%);">+               return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   case BSSLAP_MSGT_ABORT:</span><br><span style="color: hsl(120, 100%, 40%);">+               DEC_IE_MANDATORY(BSSLAP_IEI_CAUSE, osmo_bsslap_ie_dec_cause, &pdu->abort);</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   case BSSLAP_MSGT_TA_LAYER3:</span><br><span style="color: hsl(120, 100%, 40%);">+           DEC_IE_MANDATORY(BSSLAP_IEI_TA, osmo_bsslap_ie_dec_ta, &pdu->ta_layer3.ta);</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   default:</span><br><span style="color: hsl(120, 100%, 40%);">+              DEC_ERR(-EINVAL, pdu->msg_type, -1, LCS_CAUSE_UNSPECIFIED, "Unsupported message type");</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string osmo_bsslap_msgt_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_MSGT_TA_REQUEST, "TA Request" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { BSSLAP_MSGT_TA_RESPONSE, "TA Response" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { BSSLAP_MSGT_REJECT, "Reject" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { BSSLAP_MSGT_RESET, "Reset" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { BSSLAP_MSGT_ABORT, "Abort" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { BSSLAP_MSGT_TA_LAYER3, "TA Layer3" },</span><br><span style="color: hsl(120, 100%, 40%);">+     { BSSLAP_MSGT_MS_POS_CMD, "MS Position Command" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { BSSLAP_MSGT_MS_POS_RESP, "MS Position Response" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_MSGT_UTDOA_REQ, "U-TDOA Request" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_MSGT_UTDOA_RESP, "U-TDOA Response" },</span><br><span style="color: hsl(120, 100%, 40%);">+      {}</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string osmo_bsslap_iei_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       { BSSLAP_IEI_TA, "Timing Advance" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_IEI_CELL_ID, "Cell Identity" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { BSSLAP_IEI_CHAN_DESC, "Channel Description" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { BSSLAP_IEI_MEAS_REP, "Measurement Report" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { BSSLAP_IEI_CAUSE, "Cause" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { BSSLAP_IEI_RRLP_FLAG, "RRLP Flag" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { BSSLAP_IEI_RRLP, "RRLP" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_IEI_CELL_ID_LIST, "Cell Identity List" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { BSSLAP_IEI_ENH_MEAS_REP, "Enhanced Measurement Report" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { BSSLAP_IEI_LAC, "Location Area Code" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { BSSLAP_IEI_FREQ_LIST, "Frequency List" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { BSSLAP_IEI_MS_POWER, "MS Power" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_IEI_DELTA_TIMER, "Delta Timer" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { BSSLAP_IEI_SERVING_CELL_ID, "Serving Cell Identifier" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { BSSLAP_IEI_ENCR_KEY, "Encryption Key" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { BSSLAP_IEI_CIPH_MODE_SET, "Cipher Mode Setting" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_IEI_CHAN_MODE, "Channel Mode" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { BSSLAP_IEI_MR_CONFIG, "MultiRate Configuration" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_IEI_POLLING_REPETITION, "Polling Repetition" },</span><br><span style="color: hsl(120, 100%, 40%);">+    { BSSLAP_IEI_PACKET_CHAN_DESC, "Packet Channel Description" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { BSSLAP_IEI_TLLI, "TLLI" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_IEI_TFI, "TFI" },</span><br><span style="color: hsl(120, 100%, 40%);">+  { BSSLAP_IEI_TBF_START_TIME, "TBF Starting Time" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { BSSLAP_IEI_PWRUP_START_TIME, "Powerup Starting Time" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { BSSLAP_IEI_LONG_ENCR_KEY, "Long Encryption Key" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { BSSLAP_IEI_CONCUR_POS_PROC_F, "Concurrent Positioning Flag" },</span><br><span style="color: hsl(120, 100%, 40%);">+    {}</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map</span><br><span>index a31f73a..257c3fa 100644</span><br><span>--- a/src/gsm/libosmogsm.map</span><br><span>+++ b/src/gsm/libosmogsm.map</span><br><span>@@ -705,6 +705,10 @@</span><br><span> osmo_nri_ranges_to_str_buf;</span><br><span> osmo_nri_ranges_to_str_c;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+osmo_bsslap_enc;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_bsslap_dec;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_bsslap_msgt_names;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> osmo_gad_enc;</span><br><span> osmo_gad_dec;</span><br><span> osmo_gad_to_str_buf;</span><br><span>diff --git a/tests/Makefile.am b/tests/Makefile.am</span><br><span>index c4e6b9f..fc99485 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -39,6 +39,7 @@</span><br><span>                  i460_mux/i460_mux_test                                        \</span><br><span>             bitgen/bitgen_test                                     \</span><br><span>             gad/gad_test                                           \</span><br><span style="color: hsl(120, 100%, 40%);">+              bsslap/bsslap_test                                     \</span><br><span>             $(NULL)</span><br><span> </span><br><span> if ENABLE_MSGFILE</span><br><span>@@ -285,6 +286,9 @@</span><br><span> gad_gad_test_SOURCES = gad/gad_test.c</span><br><span> gad_gad_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/gad.o</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+bsslap_bsslap_test_SOURCES = bsslap/bsslap_test.c</span><br><span style="color: hsl(120, 100%, 40%);">+bsslap_bsslap_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # The `:;' works around a Bash 3.2 bug when the output is not writeable.</span><br><span> $(srcdir)/package.m4: $(top_srcdir)/configure.ac</span><br><span>      :;{ \</span><br><span>@@ -366,6 +370,7 @@</span><br><span>       i460_mux/i460_mux_test.ok \</span><br><span>          bitgen/bitgen_test.ok \</span><br><span>              gad/gad_test.ok \</span><br><span style="color: hsl(120, 100%, 40%);">+             bsslap/bsslap_test.ok \</span><br><span>              $(NULL)</span><br><span> </span><br><span> if ENABLE_LIBSCTP</span><br><span>diff --git a/tests/bsslap/bsslap_test.c b/tests/bsslap/bsslap_test.c</span><br><span>new file mode 100644</span><br><span>index 0000000..43ea0d4</span><br><span>--- /dev/null</span><br><span>+++ b/tests/bsslap/bsslap_test.c</span><br><span>@@ -0,0 +1,103 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/msgb.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/gsm/bsslap.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bsslap_pdu bsslap_test_pdus[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg_type = BSSLAP_MSGT_TA_REQUEST,</span><br><span style="color: hsl(120, 100%, 40%);">+   },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg_type = BSSLAP_MSGT_TA_RESPONSE,</span><br><span style="color: hsl(120, 100%, 40%);">+          .ta_response = {</span><br><span style="color: hsl(120, 100%, 40%);">+                      .cell_id = 23,</span><br><span style="color: hsl(120, 100%, 40%);">+                        .ta = 42,</span><br><span style="color: hsl(120, 100%, 40%);">+             },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg_type = BSSLAP_MSGT_REJECT,</span><br><span style="color: hsl(120, 100%, 40%);">+               .reject = BSSLAP_CAUSE_OTHER_RADIO_EVT_FAIL,</span><br><span style="color: hsl(120, 100%, 40%);">+  },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg_type = BSSLAP_MSGT_RESET,</span><br><span style="color: hsl(120, 100%, 40%);">+                .reset = {</span><br><span style="color: hsl(120, 100%, 40%);">+                    .cell_id = 23,</span><br><span style="color: hsl(120, 100%, 40%);">+                        .ta = 42,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .chan_desc =  {</span><br><span style="color: hsl(120, 100%, 40%);">+                               .chan_nr = 23,</span><br><span style="color: hsl(120, 100%, 40%);">+                                .h0 = {</span><br><span style="color: hsl(120, 100%, 40%);">+                                       .tsc = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     .h = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       .arfcn_high = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      .arfcn_low = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+                               },</span><br><span style="color: hsl(120, 100%, 40%);">+                    },</span><br><span style="color: hsl(120, 100%, 40%);">+                    .cause = BSSLAP_CAUSE_INTRA_BSS_HO,</span><br><span style="color: hsl(120, 100%, 40%);">+           },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg_type = BSSLAP_MSGT_ABORT,</span><br><span style="color: hsl(120, 100%, 40%);">+                .abort = BSSLAP_CAUSE_LOSS_SIG_CONN_MS,</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg_type = BSSLAP_MSGT_TA_LAYER3,</span><br><span style="color: hsl(120, 100%, 40%);">+            .ta_layer3 = {</span><br><span style="color: hsl(120, 100%, 40%);">+                        .ta = 23,</span><br><span style="color: hsl(120, 100%, 40%);">+             },</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void test_bsslap_enc_dec()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct bsslap_pdu *pdu;</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("--- %s\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     for (pdu = bsslap_test_pdus; (pdu - bsslap_test_pdus) < ARRAY_SIZE(bsslap_test_pdus); pdu++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             struct msgb *msg = msgb_alloc(1024, __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+                struct bsslap_pdu dec_pdu;</span><br><span style="color: hsl(120, 100%, 40%);">+            struct osmo_bsslap_err *err;</span><br><span style="color: hsl(120, 100%, 40%);">+          int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+               void *loop_ctx = msg;</span><br><span style="color: hsl(120, 100%, 40%);">+         rc = osmo_bsslap_enc(msg, pdu);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (rc <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("[%ld] %s: ERROR: failed to encode pdu\n", (pdu - bsslap_test_pdus),</span><br><span style="color: hsl(120, 100%, 40%);">+                        osmo_bsslap_msgt_name(pdu->msg_type));</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto loop_end;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (rc != msg->len) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("[%ld] %s: ERROR: osmo_bsslap_enc() returned length %d but msgb has %d bytes\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                            (pdu - bsslap_test_pdus), osmo_bsslap_msgt_name(pdu->msg_type),</span><br><span style="color: hsl(120, 100%, 40%);">+                            rc, msg->len);</span><br><span style="color: hsl(120, 100%, 40%);">+                      goto loop_end;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           memset(&dec_pdu, 0xff, sizeof(dec_pdu));</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = osmo_bsslap_dec(&dec_pdu, &err, loop_ctx, msg->data, msg->len);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("[%ld] %s: ERROR: failed to decode pdu: %s\n", (pdu - bsslap_test_pdus),</span><br><span style="color: hsl(120, 100%, 40%);">+                            osmo_bsslap_msgt_name(pdu->msg_type), err->logmsg);</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("     encoded data: %s\n", osmo_hexdump(msg->data, msg->len));</span><br><span style="color: hsl(120, 100%, 40%);">+                 goto loop_end;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (memcmp(pdu, &dec_pdu, sizeof(dec_pdu))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("[%ld] %s: ERROR: decoded PDU != encoded PDU\n", (pdu - bsslap_test_pdus),</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmo_bsslap_msgt_name(pdu->msg_type));</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("     original struct: %s\n", osmo_hexdump((void*)pdu, sizeof(*pdu)));</span><br><span style="color: hsl(120, 100%, 40%);">+                       printf("      decoded struct: %s\n", osmo_hexdump((void*)&dec_pdu, sizeof(dec_pdu)));</span><br><span style="color: hsl(120, 100%, 40%);">+                   goto loop_end;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           printf("[%ld] %s: ok\n", (pdu - bsslap_test_pdus), osmo_bsslap_msgt_name(pdu->msg_type));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+loop_end:</span><br><span style="color: hsl(120, 100%, 40%);">+           msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int main()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ test_bsslap_enc_dec();</span><br><span style="color: hsl(120, 100%, 40%);">+        return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/bsslap/bsslap_test.ok b/tests/bsslap/bsslap_test.ok</span><br><span>new file mode 100644</span><br><span>index 0000000..f3199e1</span><br><span>--- /dev/null</span><br><span>+++ b/tests/bsslap/bsslap_test.ok</span><br><span>@@ -0,0 +1,7 @@</span><br><span style="color: hsl(120, 100%, 40%);">+--- test_bsslap_enc_dec</span><br><span style="color: hsl(120, 100%, 40%);">+[0] TA Request: ok</span><br><span style="color: hsl(120, 100%, 40%);">+[1] TA Response: ok</span><br><span style="color: hsl(120, 100%, 40%);">+[2] Reject: ok</span><br><span style="color: hsl(120, 100%, 40%);">+[3] Reset: ok</span><br><span style="color: hsl(120, 100%, 40%);">+[4] Abort: ok</span><br><span style="color: hsl(120, 100%, 40%);">+[5] TA Layer3: ok</span><br><span>diff --git a/tests/testsuite.at b/tests/testsuite.at</span><br><span>index e29c131..0923c25 100644</span><br><span>--- a/tests/testsuite.at</span><br><span>+++ b/tests/testsuite.at</span><br><span>@@ -409,3 +409,9 @@</span><br><span> cat $abs_srcdir/gad/gad_test.ok > expout</span><br><span> AT_CHECK([$abs_top_builddir/tests/gad/gad_test], [0], [expout], [ignore])</span><br><span> AT_CLEANUP</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AT_SETUP([bsslap])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_KEYWORDS([bsslap])</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/bsslap/bsslap_test.ok > expout</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CHECK([$abs_top_builddir/tests/bsslap/bsslap_test], [0], [expout], [ignore])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CLEANUP</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/20333">change 20333</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/20333"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I6409c4bcac402dc7626a3afce9081c59cd715fe8 </div>
<div style="display:none"> Gerrit-Change-Number: 20333 </div>
<div style="display:none"> Gerrit-PatchSet: 5 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>