aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2019-04-23 23:21:14 +0200
committerHarald Welte <laforge@gnumonks.org>2019-04-24 15:42:27 +0200
commit1f60bbe8a218f6948520c41e6671fec59c53ef04 (patch)
treead2916b26ec6add426d85cf4d20deeb47fc6166e
parent3a0b772d6c71308180de31e87e2bda9d8428f8d0 (diff)
gprs_llc: Correctly refuse any ABM command (SABM, DISC) with DM
According to Section 6.4.1.4 of 3GPP TS 04.64 The DM unnumbered response shall be used by an LLE to report to its peer that the LLE is in a state such that ABM operation cannot be performed. An LLE shall transmit a DM response to any valid command received that it cannot action. Closes: OS#3953 Change-Id: Ie8b8e16d5a68f19f21dc4fdb5703c8a794e0173c
-rw-r--r--src/gprs/gprs_llc.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/gprs/gprs_llc.c b/src/gprs/gprs_llc.c
index 654f2c0..2ec7100 100644
--- a/src/gprs/gprs_llc.c
+++ b/src/gprs/gprs_llc.c
@@ -44,6 +44,7 @@
static struct gprs_llc_llme *llme_alloc(uint32_t tlli);
static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
int command);
+static int gprs_llc_tx_dm(struct gprs_llc_lle *lle);
static int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi,
int command, enum gprs_llc_u_cmd u_cmd, int pf_bit);
@@ -676,6 +677,18 @@ static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
return gprs_llc_tx_u(msg, lle->sapi, command, GPRS_LLC_U_XID, 1);
}
+static int gprs_llc_tx_dm(struct gprs_llc_lle *lle)
+{
+ struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_DM");
+
+ /* copy identifiers from LLE to ensure lower layers can route */
+ msgb_tlli(msg) = lle->llme->tlli;
+ msgb_bvci(msg) = lle->llme->bvci;
+ msgb_nsei(msg) = lle->llme->nsei;
+
+ return gprs_llc_tx_u(msg, lle->sapi, 0, GPRS_LLC_U_DM_RESP, 1);
+}
+
/* encrypt information field + FCS, if needed! */
static int apply_gea(struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu,
uint32_t oc, uint8_t sapi, uint8_t *fcs, uint8_t *data)
@@ -802,6 +815,8 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
struct gprs_llc_lle *lle)
{
switch (gph->cmd) {
+#if 0
+ /* we don't fully imoplement ABM, so refuse it properly (OS#3953) */
case GPRS_LLC_SABM: /* Section 6.4.1.1 */
lle->v_sent = lle->v_ack = lle->v_recv = 0;
if (lle->state == GPRS_LLES_ASSIGNED_ADM) {
@@ -827,6 +842,13 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
break;
case GPRS_LLC_FRMR: /* Section 6.4.1.5 */
break;
+#else
+ case GPRS_LLC_SABM:
+ case GPRS_LLC_DISC:
+ /* send DM to properly signal we don't do ABM */
+ gprs_llc_tx_dm(lle);
+ break;
+#endif
case GPRS_LLC_XID: /* Section 6.4.1.6 */
rx_llc_xid(lle, gph);
break;