<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/20819">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">lapdm: Split lapd_rx_u() spaghetti into one function per message type<br><br>Change-Id: Ia1a49f7ae1d133174fad7a396db72867612fa619<br>---<br>M src/gsm/lapd_core.c<br>1 file changed, 451 insertions(+), 402 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/19/20819/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/gsm/lapd_core.c b/src/gsm/lapd_core.c</span><br><span>index 6a56572..bcb64b0 100644</span><br><span>--- a/src/gsm/lapd_core.c</span><br><span>+++ b/src/gsm/lapd_core.c</span><br><span>@@ -814,422 +814,471 @@</span><br><span> </span><br><span> /* L1 -> L2 */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Receive a LAPD U (Unnumbered) message from L1 */</span><br><span style="color: hsl(0, 100%, 40%);">-static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span style="color: hsl(120, 100%, 40%);">+/* Receive a LAPD U SABM(E) message from L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int lapd_rx_u_sabm(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span> {</span><br><span> struct lapd_datalink *dl = lctx->dl;</span><br><span> int length = lctx->length;</span><br><span> int rc = 0;</span><br><span> uint8_t prim, op;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- switch (lctx->s_u) {</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_U_SABM:</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_U_SABME:</span><br><span style="color: hsl(0, 100%, 40%);">- prim = PRIM_DL_EST;</span><br><span style="color: hsl(0, 100%, 40%);">- op = PRIM_OP_INDICATION;</span><br><span style="color: hsl(120, 100%, 40%);">+ prim = PRIM_DL_EST;</span><br><span style="color: hsl(120, 100%, 40%);">+ op = PRIM_OP_INDICATION;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "SABM(E) received in state %s\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.7.1 */</span><br><span style="color: hsl(0, 100%, 40%);">- dl->seq_err_cond = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lctx->cr == dl->cr.rem2loc.resp) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "SABM response error\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.4.5 If SABM is received with L>N201 or with M bit</span><br><span style="color: hsl(0, 100%, 40%);">- * set, AN MDL-ERROR-INDICATION is sent to MM.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lctx->more || length > lctx->n201) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "SABM too large error\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EIO;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (dl->state) {</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_IDLE:</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_MF_EST:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "SABM command, multiple frame established state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- /* If link is lost on the remote side, we start over</span><br><span style="color: hsl(0, 100%, 40%);">- * and send DL-ESTABLISH indication again. */</span><br><span style="color: hsl(0, 100%, 40%);">- /* Additionally, continue in case of content resoltion</span><br><span style="color: hsl(0, 100%, 40%);">- * (GSM network). This happens, if the mobile has not</span><br><span style="color: hsl(0, 100%, 40%);">- * yet received UA or another mobile (collision) tries</span><br><span style="color: hsl(0, 100%, 40%);">- * to establish connection. The mobile must receive</span><br><span style="color: hsl(0, 100%, 40%);">- * UA again. */</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.2.1 */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!length) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* If no content resolution, this is a</span><br><span style="color: hsl(0, 100%, 40%);">- * re-establishment. */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "Remote reestablish\n");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!dl->cont_res) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "SABM command not allowed in state %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_state_name(dl->state));</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_SABM_MF, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* Ignore SABM if content differs from first SABM. */</span><br><span style="color: hsl(0, 100%, 40%);">- if (dl->mode == LAPD_MODE_NETWORK && length) {</span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef TEST_CONTENT_RESOLUTION_NETWORK</span><br><span style="color: hsl(0, 100%, 40%);">- dl->cont_res->data[0] ^= 0x01;</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">- if (memcmp(dl->cont_res->data, msg->data,</span><br><span style="color: hsl(0, 100%, 40%);">- length)) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "Another SABM with different content - "</span><br><span style="color: hsl(0, 100%, 40%);">- "ignoring!\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* send UA again */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_DISC_SENT:</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.6.2 send DM with F=P */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_send_dm(lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- /* stop Timer T200 */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_stop_t200(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return send_dl_simple(prim, op, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- /* collision: Send UA, but still wait for rx UA, then</span><br><span style="color: hsl(0, 100%, 40%);">- * change to MF_EST state.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- /* check for contention resoultion */</span><br><span style="color: hsl(0, 100%, 40%);">- if (dl->tx_hist[0].msg && dl->tx_hist[0].msg->len) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_NOTICE, "SABM not allowed during contention "</span><br><span style="color: hsl(0, 100%, 40%);">- "resolution (state=%s)\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_SABM_INFO_NOTALL, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* save message context for further use */</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(&dl->lctx, lctx, sizeof(dl->lctx));</span><br><span style="color: hsl(0, 100%, 40%);">-#ifndef TEST_CONTENT_RESOLUTION_NETWORK</span><br><span style="color: hsl(0, 100%, 40%);">- /* send UA response */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">- /* set Vs, Vr and Va to 0 */</span><br><span style="color: hsl(0, 100%, 40%);">- dl->v_send = dl->v_recv = dl->v_ack = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- /* clear tx_hist */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_hist(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* enter multiple-frame-established state */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_newstate(dl, LAPD_STATE_MF_EST);</span><br><span style="color: hsl(0, 100%, 40%);">- /* store content resolution data on network side</span><br><span style="color: hsl(0, 100%, 40%);">- * Note: cont_res will be removed when changing state again,</span><br><span style="color: hsl(0, 100%, 40%);">- * so it must be allocated AFTER lapd_dl_newstate(). */</span><br><span style="color: hsl(0, 100%, 40%);">- if (dl->mode == LAPD_MODE_NETWORK && length) {</span><br><span style="color: hsl(0, 100%, 40%);">- dl->cont_res = lapd_msgb_alloc(length, "CONT RES");</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(msgb_put(dl->cont_res, length), msg->l3h,</span><br><span style="color: hsl(0, 100%, 40%);">- length);</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_NOTICE, "Store content res.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* send notification to L3 */</span><br><span style="color: hsl(0, 100%, 40%);">- if (length == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.1.2 Normal establishment procedures */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_simple(prim, op, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.1.4 Contention resolution establishment */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_trim(msg, length);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_l3(prim, op, lctx, msg);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_U_DM:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "DM received in state %s\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lctx->cr == dl->cr.rem2loc.cmd) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "DM command error\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!lctx->p_f) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.1.2 DM responses with the F bit set to "0"</span><br><span style="color: hsl(0, 100%, 40%);">- * shall be ignored.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- switch (dl->state) {</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_SABM_SENT:</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_MF_EST:</span><br><span style="color: hsl(0, 100%, 40%);">- if (lctx->p_f) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "unsolicited DM response\n");</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_UNSOL_DM_RESP, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "unsolicited DM response, "</span><br><span style="color: hsl(0, 100%, 40%);">- "multiple frame established state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- /* reestablish */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!dl->reestablish) {</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_reestablish(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_TIMER_RECOV:</span><br><span style="color: hsl(0, 100%, 40%);">- /* FP = 0 (DM is normal in case PF = 1) */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!lctx->p_f) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "unsolicited DM response, multiple frame "</span><br><span style="color: hsl(0, 100%, 40%);">- "established state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- /* reestablish */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!dl->reestablish)</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return lapd_reestablish(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_DISC_SENT:</span><br><span style="color: hsl(0, 100%, 40%);">- /* stop Timer T200 */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_stop_t200(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* go to idle state */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_tx(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_send(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_IDLE:</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.5 all other frame types shall be discarded */</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "unsolicited DM response! (discarding)\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* stop timer T200 */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_stop_t200(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* go to idle state */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_U_UI:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "UI received\n");</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lctx->cr == dl->cr.rem2loc.resp) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "UI indicates response error\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.4.5 If UI is received with L>N201 or with M bit</span><br><span style="color: hsl(0, 100%, 40%);">- * set, AN MDL-ERROR-INDICATION is sent to MM.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- if (length > lctx->n201 || lctx->more) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "UI too large error (%d > N201(%d) or M=%d)\n",</span><br><span style="color: hsl(0, 100%, 40%);">- length, lctx->n201, lctx->more);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EIO;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* do some length checks */</span><br><span style="color: hsl(0, 100%, 40%);">- if (length == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.3.3 UI frames received with the length indicator</span><br><span style="color: hsl(0, 100%, 40%);">- * set to "0" shall be ignored</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "length=0 (discarding)\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_trim(msg, length);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_l3(PRIM_DL_UNIT_DATA, PRIM_OP_INDICATION, lctx,</span><br><span style="color: hsl(0, 100%, 40%);">- msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_U_DISC:</span><br><span style="color: hsl(0, 100%, 40%);">- prim = PRIM_DL_REL;</span><br><span style="color: hsl(0, 100%, 40%);">- op = PRIM_OP_INDICATION;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "DISC received in state %s\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(0, 100%, 40%);">- /* flush tx and send buffers */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_tx(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_send(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.7.1 */</span><br><span style="color: hsl(0, 100%, 40%);">- dl->seq_err_cond = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lctx->cr == dl->cr.rem2loc.resp) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "DISC response error\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (length > 0 || lctx->more) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.4.4 If a DISC or DM frame is received with L>0 or</span><br><span style="color: hsl(0, 100%, 40%);">- * with the M bit set to "1", an MDL-ERROR-INDICATION</span><br><span style="color: hsl(0, 100%, 40%);">- * primitive with cause "U frame with incorrect</span><br><span style="color: hsl(0, 100%, 40%);">- * parameters" is sent to the mobile management entity.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "U frame iwth incorrect parameters\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EIO;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- switch (dl->state) {</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_IDLE:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "DISC in idle state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- /* send DM with F=P */</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return lapd_send_dm(lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_SABM_SENT:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "DISC in SABM state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.6.2 send DM with F=P */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_send_dm(lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- /* stop Timer T200 */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_stop_t200(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* go to idle state */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION,</span><br><span style="color: hsl(0, 100%, 40%);">- lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_MF_EST:</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_TIMER_RECOV:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "DISC in est state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_DISC_SENT:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "DISC in disc state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- prim = PRIM_DL_REL;</span><br><span style="color: hsl(0, 100%, 40%);">- op = PRIM_OP_CONFIRM;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* send UA response */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(0, 100%, 40%);">- /* stop Timer T200 */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_stop_t200(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* enter idle state, keep tx-buffer with UA response */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(0, 100%, 40%);">- /* send notification to L3 */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_simple(prim, op, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_U_UA:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "UA received in state %s\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lctx->cr == dl->cr.rem2loc.cmd) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "UA indicates command error\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EINVAL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.4.5 If UA is received with L>N201 or with M bit</span><br><span style="color: hsl(0, 100%, 40%);">- * set, AN MDL-ERROR-INDICATION is sent to MM.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lctx->more || length > lctx->n201) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_ERROR, "UA too large error\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- return -EIO;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!lctx->p_f) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.1.2 A UA response with the F bit set to "0"</span><br><span style="color: hsl(0, 100%, 40%);">- * shall be ignored.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "F=0 (discarding)\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- switch (dl->state) {</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_SABM_SENT:</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_MF_EST:</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_TIMER_RECOV:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "unsolicited UA response! (discarding)\n");</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_UNSOL_UA_RESP, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_DISC_SENT:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "UA in disconnect state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- /* stop Timer T200 */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_stop_t200(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* go to idle state */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_tx(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_send(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_STATE_IDLE:</span><br><span style="color: hsl(0, 100%, 40%);">- /* 5.4.5 all other frame types shall be discarded */</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "unsolicited UA response! (discarding)\n");</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "UA in SABM state\n");</span><br><span style="color: hsl(0, 100%, 40%);">- /* stop Timer T200 */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_stop_t200(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* compare UA with SABME if contention resolution is applied */</span><br><span style="color: hsl(0, 100%, 40%);">- if (dl->tx_hist[0].msg->len) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (length != (dl->tx_hist[0].msg->len)</span><br><span style="color: hsl(0, 100%, 40%);">- || !!memcmp(dl->tx_hist[0].msg->data, msg->l3h,</span><br><span style="color: hsl(0, 100%, 40%);">- length)) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_INFO, "**** UA response mismatches ****\n");</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_simple(PRIM_DL_REL,</span><br><span style="color: hsl(0, 100%, 40%);">- PRIM_OP_INDICATION, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- /* go to idle state */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_tx(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_send(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- /* set Vs, Vr and Va to 0 */</span><br><span style="color: hsl(0, 100%, 40%);">- dl->v_send = dl->v_recv = dl->v_ack = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- /* clear tx_hist */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_flush_hist(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- /* enter multiple-frame-established state */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_dl_newstate(dl, LAPD_STATE_MF_EST);</span><br><span style="color: hsl(0, 100%, 40%);">- /* send outstanding frames, if any (resume / reconnect) */</span><br><span style="color: hsl(0, 100%, 40%);">- lapd_send_i(lctx, __LINE__);</span><br><span style="color: hsl(0, 100%, 40%);">- /* send notification to L3 */</span><br><span style="color: hsl(0, 100%, 40%);">- rc = send_dl_simple(PRIM_DL_EST, PRIM_OP_CONFIRM, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case LAPD_U_FRMR:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_NOTICE, "Frame reject received\n");</span><br><span style="color: hsl(0, 100%, 40%);">- /* send MDL ERROR INIDCATION to L3 */</span><br><span style="color: hsl(0, 100%, 40%);">- mdl_error(MDL_CAUSE_FRMR, lctx);</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_free(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- /* reestablish */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!dl->reestablish)</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");</span><br><span style="color: hsl(0, 100%, 40%);">- rc = lapd_reestablish(dl);</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- default:</span><br><span style="color: hsl(0, 100%, 40%);">- /* G.3.1 */</span><br><span style="color: hsl(0, 100%, 40%);">- LOGDL(dl, LOGL_NOTICE, "Unnumbered frame not allowed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "SABM(E) received in state %s\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.7.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+ dl->seq_err_cond = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lctx->cr == dl->cr.rem2loc.resp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "SABM response error\n");</span><br><span> msgb_free(msg);</span><br><span> mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span> return -EINVAL;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* G.4.5 If SABM is received with L>N201 or with M bit</span><br><span style="color: hsl(120, 100%, 40%);">+ * set, AN MDL-ERROR-INDICATION is sent to MM.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lctx->more || length > lctx->n201) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "SABM too large error\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EIO;</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%);">+ switch (dl->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_IDLE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_MF_EST:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "SABM command, multiple frame established state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If link is lost on the remote side, we start over</span><br><span style="color: hsl(120, 100%, 40%);">+ * and send DL-ESTABLISH indication again. */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Additionally, continue in case of content resoltion</span><br><span style="color: hsl(120, 100%, 40%);">+ * (GSM network). This happens, if the mobile has not</span><br><span style="color: hsl(120, 100%, 40%);">+ * yet received UA or another mobile (collision) tries</span><br><span style="color: hsl(120, 100%, 40%);">+ * to establish connection. The mobile must receive</span><br><span style="color: hsl(120, 100%, 40%);">+ * UA again. */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.2.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!length) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If no content resolution, this is a</span><br><span style="color: hsl(120, 100%, 40%);">+ * re-establishment. */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "Remote reestablish\n");</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%);">+ if (!dl->cont_res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "SABM command not allowed in state %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_state_name(dl->state));</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_SABM_MF, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ /* Ignore SABM if content differs from first SABM. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dl->mode == LAPD_MODE_NETWORK && length) {</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef TEST_CONTENT_RESOLUTION_NETWORK</span><br><span style="color: hsl(120, 100%, 40%);">+ dl->cont_res->data[0] ^= 0x01;</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ if (memcmp(dl->cont_res->data, msg->data,</span><br><span style="color: hsl(120, 100%, 40%);">+ length)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "Another SABM with different content - "</span><br><span style="color: hsl(120, 100%, 40%);">+ "ignoring!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ /* send UA again */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_DISC_SENT:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.6.2 send DM with F=P */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_send_dm(lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* stop Timer T200 */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_stop_t200(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return send_dl_simple(prim, op, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* collision: Send UA, but still wait for rx UA, then</span><br><span style="color: hsl(120, 100%, 40%);">+ * change to MF_EST state.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* check for contention resoultion */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dl->tx_hist[0].msg && dl->tx_hist[0].msg->len) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_NOTICE, "SABM not allowed during contention "</span><br><span style="color: hsl(120, 100%, 40%);">+ "resolution (state=%s)\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_SABM_INFO_NOTALL, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ /* save message context for further use */</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(&dl->lctx, lctx, sizeof(dl->lctx));</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef TEST_CONTENT_RESOLUTION_NETWORK</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send UA response */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ /* set Vs, Vr and Va to 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+ dl->v_send = dl->v_recv = dl->v_ack = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* clear tx_hist */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_hist(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* enter multiple-frame-established state */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_newstate(dl, LAPD_STATE_MF_EST);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* store content resolution data on network side</span><br><span style="color: hsl(120, 100%, 40%);">+ * Note: cont_res will be removed when changing state again,</span><br><span style="color: hsl(120, 100%, 40%);">+ * so it must be allocated AFTER lapd_dl_newstate(). */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dl->mode == LAPD_MODE_NETWORK && length) {</span><br><span style="color: hsl(120, 100%, 40%);">+ dl->cont_res = lapd_msgb_alloc(length, "CONT RES");</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(msgb_put(dl->cont_res, length), msg->l3h,</span><br><span style="color: hsl(120, 100%, 40%);">+ length);</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_NOTICE, "Store content res.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send notification to L3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (length == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.1.2 Normal establishment procedures */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = send_dl_simple(prim, op, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.1.4 Contention resolution establishment */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_trim(msg, length);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = send_dl_l3(prim, op, lctx, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Receive a LAPD U DM message from L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int lapd_rx_u_dm(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lapd_datalink *dl = lctx->dl;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "DM received in state %s\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lctx->cr == dl->cr.rem2loc.cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "DM command error\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!lctx->p_f) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.1.2 DM responses with the F bit set to "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ * shall be ignored.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ switch (dl->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_SABM_SENT:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_MF_EST:</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lctx->p_f) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "unsolicited DM response\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_UNSOL_DM_RESP, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "unsolicited DM response, "</span><br><span style="color: hsl(120, 100%, 40%);">+ "multiple frame established state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* reestablish */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dl->reestablish) {</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_reestablish(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_TIMER_RECOV:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FP = 0 (DM is normal in case PF = 1) */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!lctx->p_f) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "unsolicited DM response, multiple frame "</span><br><span style="color: hsl(120, 100%, 40%);">+ "established state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_UNSOL_DM_RESP_MF, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* reestablish */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dl->reestablish)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_reestablish(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_DISC_SENT:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* stop Timer T200 */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_stop_t200(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* go to idle state */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_tx(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_send(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_IDLE:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.5 all other frame types shall be discarded */</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "unsolicited DM response! (discarding)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ /* stop timer T200 */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_stop_t200(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* go to idle state */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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%);">+/* Receive a LAPD U UI message from L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int lapd_rx_u_ui(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lapd_datalink *dl = lctx->dl;</span><br><span style="color: hsl(120, 100%, 40%);">+ int length = lctx->length;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "UI received\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lctx->cr == dl->cr.rem2loc.resp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "UI indicates response error\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</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%);">+ /* G.4.5 If UI is received with L>N201 or with M bit</span><br><span style="color: hsl(120, 100%, 40%);">+ * set, AN MDL-ERROR-INDICATION is sent to MM.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (length > lctx->n201 || lctx->more) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "UI too large error (%d > N201(%d) or M=%d)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ length, lctx->n201, lctx->more);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EIO;</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%);">+ /* do some length checks */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (length == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.3.3 UI frames received with the length indicator</span><br><span style="color: hsl(120, 100%, 40%);">+ * set to "0" shall be ignored</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "length=0 (discarding)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ msgb_trim(msg, length);</span><br><span style="color: hsl(120, 100%, 40%);">+ return send_dl_l3(PRIM_DL_UNIT_DATA, PRIM_OP_INDICATION, lctx, 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%);">+/* Receive a LAPD U DISC message from L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int lapd_rx_u_disc(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lapd_datalink *dl = lctx->dl;</span><br><span style="color: hsl(120, 100%, 40%);">+ int length = lctx->length;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t prim, op;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ prim = PRIM_DL_REL;</span><br><span style="color: hsl(120, 100%, 40%);">+ op = PRIM_OP_INDICATION;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "DISC received in state %s\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* flush tx and send buffers */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_tx(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_send(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.7.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+ dl->seq_err_cond = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lctx->cr == dl->cr.rem2loc.resp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "DISC response error\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (length > 0 || lctx->more) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* G.4.4 If a DISC or DM frame is received with L>0 or</span><br><span style="color: hsl(120, 100%, 40%);">+ * with the M bit set to "1", an MDL-ERROR-INDICATION</span><br><span style="color: hsl(120, 100%, 40%);">+ * primitive with cause "U frame with incorrect</span><br><span style="color: hsl(120, 100%, 40%);">+ * parameters" is sent to the mobile management entity.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "U frame iwth incorrect parameters\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (dl->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_IDLE:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "DISC in idle state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send DM with F=P */</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_send_dm(lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_SABM_SENT:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "DISC in SABM state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.6.2 send DM with F=P */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_send_dm(lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* stop Timer T200 */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_stop_t200(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* go to idle state */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return send_dl_simple(PRIM_DL_REL, PRIM_OP_INDICATION,</span><br><span style="color: hsl(120, 100%, 40%);">+ lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_MF_EST:</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_TIMER_RECOV:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "DISC in est state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_DISC_SENT:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "DISC in disc state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ prim = PRIM_DL_REL;</span><br><span style="color: hsl(120, 100%, 40%);">+ op = PRIM_OP_CONFIRM;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ /* send UA response */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_send_ua(lctx, length, msg->l3h);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* stop Timer T200 */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_stop_t200(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* enter idle state, keep tx-buffer with UA response */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send notification to L3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = send_dl_simple(prim, op, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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%);">+/* Receive a LAPD U UA message from L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int lapd_rx_u_ua(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lapd_datalink *dl = lctx->dl;</span><br><span style="color: hsl(120, 100%, 40%);">+ int length = lctx->length;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "UA received in state %s\n", lapd_state_name(dl->state));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* G.2.2 Wrong value of the C/R bit */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lctx->cr == dl->cr.rem2loc.cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "UA indicates command error\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</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%);">+ /* G.4.5 If UA is received with L>N201 or with M bit</span><br><span style="color: hsl(120, 100%, 40%);">+ * set, AN MDL-ERROR-INDICATION is sent to MM.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lctx->more || length > lctx->n201) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_ERROR, "UA too large error\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_UFRM_INC_PARAM, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EIO;</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 (!lctx->p_f) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.1.2 A UA response with the F bit set to "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ * shall be ignored.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "F=0 (discarding)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ switch (dl->state) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_SABM_SENT:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_MF_EST:</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_TIMER_RECOV:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "unsolicited UA response! (discarding)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_UNSOL_UA_RESP, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_DISC_SENT:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "UA in disconnect state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ /* stop Timer T200 */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_stop_t200(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* go to idle state */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_tx(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_send(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = send_dl_simple(PRIM_DL_REL, PRIM_OP_CONFIRM, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_STATE_IDLE:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* 5.4.5 all other frame types shall be discarded */</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "unsolicited UA response! (discarding)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</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%);">+ LOGDL(dl, LOGL_INFO, "UA in SABM state\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ /* stop Timer T200 */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_stop_t200(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* compare UA with SABME if contention resolution is applied */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dl->tx_hist[0].msg->len) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (length != (dl->tx_hist[0].msg->len)</span><br><span style="color: hsl(120, 100%, 40%);">+ || !!memcmp(dl->tx_hist[0].msg->data, msg->l3h,</span><br><span style="color: hsl(120, 100%, 40%);">+ length)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_INFO, "**** UA response mismatches ****\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = send_dl_simple(PRIM_DL_REL,</span><br><span style="color: hsl(120, 100%, 40%);">+ PRIM_OP_INDICATION, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* go to idle state */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_tx(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_send(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_newstate(dl, LAPD_STATE_IDLE);</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%);">+ /* set Vs, Vr and Va to 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+ dl->v_send = dl->v_recv = dl->v_ack = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* clear tx_hist */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_flush_hist(dl);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* enter multiple-frame-established state */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_dl_newstate(dl, LAPD_STATE_MF_EST);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send outstanding frames, if any (resume / reconnect) */</span><br><span style="color: hsl(120, 100%, 40%);">+ lapd_send_i(lctx, __LINE__);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send notification to L3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = send_dl_simple(PRIM_DL_EST, PRIM_OP_CONFIRM, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc;</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%);">+/* Receive a LAPD U FRMR message from L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int lapd_rx_u_frmr(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct lapd_datalink *dl = lctx->dl;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_NOTICE, "Frame reject received\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send MDL ERROR INIDCATION to L3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_FRMR, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* reestablish */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dl->reestablish)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(dl, LOGL_NOTICE, "Performing reestablishment\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_reestablish(dl);</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%);">+/* Receive a LAPD U (Unnumbered) message from L1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (lctx->s_u) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_U_SABM:</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_U_SABME:</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_rx_u_sabm(msg, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_U_DM:</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_rx_u_dm(msg, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_U_UI:</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_rx_u_ui(msg, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_U_DISC:</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_rx_u_disc(msg, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_U_UA:</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_rx_u_ua(msg, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ case LAPD_U_FRMR:</span><br><span style="color: hsl(120, 100%, 40%);">+ return lapd_rx_u_frmr(msg, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* G.3.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGDL(lctx->dl, LOGL_NOTICE, "Unnumbered frame not allowed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_free(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mdl_error(MDL_CAUSE_FRM_UNIMPL, lctx);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</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> /* Receive a LAPD S (Supervisory) message from L1 */</span><br><span> static int lapd_rx_s(struct msgb *msg, struct lapd_msg_ctx *lctx)</span><br><span> {</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/20819">change 20819</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/+/20819"/><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: Ia1a49f7ae1d133174fad7a396db72867612fa619 </div>
<div style="display:none"> Gerrit-Change-Number: 20819 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>