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

</div><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;"><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: 2 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>