aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Willmann <dwillmann@sysmocom.de>2021-02-12 01:57:52 +0100
committerdaniel <dwillmann@sysmocom.de>2021-02-12 14:19:20 +0000
commitfa632b8e80edad72b4413aac6886030c806929b9 (patch)
tree6a74d818aaf9354ba1a78229ea3c00029c59293b /src
parent1ff86f7cec32d39b84effa896569f8fc7ca703d2 (diff)
bssgp2_enc_status: Truncate STATUS message to maximum PDU length
Diffstat (limited to 'src')
-rw-r--r--src/gb/bssgp_bvc_fsm.c2
-rw-r--r--src/gb/gprs_bssgp2.c19
2 files changed, 16 insertions, 5 deletions
diff --git a/src/gb/bssgp_bvc_fsm.c b/src/gb/bssgp_bvc_fsm.c
index d2ee1462..a0359386 100644
--- a/src/gb/bssgp_bvc_fsm.c
+++ b/src/gb/bssgp_bvc_fsm.c
@@ -238,7 +238,7 @@ static void _tx_status(struct osmo_fsm_inst *fi, enum gprs_bssgp_cause cause, co
if (cause == BSSGP_CAUSE_UNKNOWN_BVCI || cause == BSSGP_CAUSE_BVCI_BLOCKED)
bvci = &bfp->bvci;
- tx = bssgp2_enc_status(cause, bvci, rx);
+ tx = bssgp2_enc_status(cause, bvci, rx, bfp->max_pdu_len);
if (msgb_bvci(rx) == 0)
fi_tx_sig(fi, tx);
diff --git a/src/gb/gprs_bssgp2.c b/src/gb/gprs_bssgp2.c
index 0f519adb..8e2ba66c 100644
--- a/src/gb/gprs_bssgp2.c
+++ b/src/gb/gprs_bssgp2.c
@@ -217,8 +217,9 @@ struct msgb *bssgp2_enc_bvc_reset_ack(uint16_t bvci, const struct gprs_ra_id *ra
/*! Encode BSSGP STATUS PDU as per TS 48.018 Section 10.4.14.
* \param[in] cause BSSGP Cause value
* \param[in] bvci optional BVCI - only encoded if non-NULL
- * \param[in] msg optional message buffer containing PDU in error - only encoded if non-NULL */
-struct msgb *bssgp2_enc_status(uint8_t cause, const uint16_t *bvci, const struct msgb *orig_msg)
+ * \param[in] msg optional message buffer containing PDU in error - only encoded if non-NULL
+ * \param[in] max_pdu_len Maximum BSSGP PDU size the NS layer accepts */
+struct msgb *bssgp2_enc_status(uint8_t cause, const uint16_t *bvci, const struct msgb *orig_msg, uint16_t max_pdu_len)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph;
@@ -229,12 +230,22 @@ struct msgb *bssgp2_enc_status(uint8_t cause, const uint16_t *bvci, const struct
bgph = (struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
bgph->pdu_type = BSSGP_PDUT_STATUS;
msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause);
+ /* FIXME: Require/encode BVCI only if cause is BVCI unknown/blocked
+ * See 3GPP TS 48.018 Ch. 10.4.14 */
if (bvci) {
uint16_t _bvci = osmo_htons(*bvci);
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
}
- if (orig_msg)
- msgb_tvlv_put(msg, BSSGP_IE_PDU_IN_ERROR, msgb_bssgp_len(orig_msg), msgb_bssgph(orig_msg));
+ if (orig_msg) {
+ uint32_t orig_len, max_orig_len;
+ /* Calculate how big the reply would be: the BSSGP msg so far + size of the PDU IN ERROR including tvl */
+ orig_len = msgb_bssgp_len(orig_msg);
+ max_orig_len = msgb_length(msg) + TVLV_GROSS_LEN(orig_len);
+ /* Truncate the difference between max_orig_len and mtu */
+ if (max_orig_len > max_pdu_len)
+ orig_len -= max_orig_len - max_pdu_len;
+ msgb_tvlv_put(msg, BSSGP_IE_PDU_IN_ERROR, orig_len, msgb_bssgph(orig_msg));
+ }
return msg;
}