/* * Process an incoming LAPB frame */ void lapb_data_input(lapb_cb *lapb, struct sk_buff *skb) { struct lapb_frame frame; lapb_decode(lapb, skb, &frame); switch (lapb->state) { case LAPB_STATE_0: lapb_state0_machine(lapb, skb, &frame); break; case LAPB_STATE_1: lapb_state1_machine(lapb, skb, &frame); break; case LAPB_STATE_2: lapb_state2_machine(lapb, skb, &frame); break; case LAPB_STATE_3: lapb_state3_machine(lapb, skb, &frame); break; case LAPB_STATE_4: lapb_state4_machine(lapb, skb, &frame); break; } lapb_kick(lapb); }
int lapb_data_request(void *token, struct sk_buff *skb) { lapb_cb *lapb; if ((lapb = lapb_tokentostruct(token)) == NULL) return LAPB_BADTOKEN; if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4) return LAPB_NOTCONNECTED; skb_queue_tail(&lapb->write_queue, skb); lapb_kick(lapb); return LAPB_OK; }
void lapb_t201timer_expiry(void * lapb_ptr) { struct lapb_cs *lapb = lapb_ptr; if (!lapb) return; struct lapb_cs_internal * lapb_int = lapb_get_internal(lapb); lapb_int->RC++; lapb->callbacks->debug(3, "[LAPB] S%d Timer_201 expired(%d of %d)", lapb_int->state, lapb_int->RC, lapb->N201); switch (lapb_int->state) { /* * If we are a DCE, keep going DM .. DM .. DM */ case LAPB_STATE_0: if (lapb_is_dce(lapb)) { lapb_int->RC = 0; lapb->callbacks->debug(2, "[LAPB] S0 TX DM(0)"); lapb_send_control(lapb, LAPB_DM, LAPB_POLLOFF, LAPB_RESPONSE); }; break; /* * Awaiting connection state, send SABM(E), up to N2 times. */ case LAPB_STATE_1: if (lapb_int->RC >= lapb->N201) { lapb_stop_t201timer(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); lapb_reset(lapb, LAPB_STATE_0); } else { if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S1 TX SABME(1)"); lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { lapb->callbacks->debug(2, "[LAPB] S1 TX SABM(1)"); lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); }; }; break; /* * Awaiting disconnection state, send DISC, up to N2 times. */ case LAPB_STATE_2: if (lapb_int->RC >= lapb->N201) { lapb_stop_t201timer(lapb); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); lapb_reset(lapb, LAPB_STATE_0); } else { lapb->callbacks->debug(2, "[LAPB] S2 TX DISC(1)"); lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND); }; break; /* * Data transfer state, restransmit I frames, up to N2 times. */ case LAPB_STATE_3: lapb_requeue_frames(lapb); if (lapb_int->RC >= lapb->N201) { lapb_stop_t201timer(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); lapb_reset(lapb, LAPB_STATE_0); } else { if (lapb_int->condition & LAPB_FRMR_CONDITION) lapb_transmit_frmr(lapb); else lapb_kick(lapb); }; break; /* * Frame reject state, restransmit FRMR frames, up to N2 times. */ case LAPB_STATE_4: if (lapb_int->RC >= lapb->N201) { lapb_stop_t201timer(lapb); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_TIMEDOUT); lapb_reset(lapb, LAPB_STATE_0); } else { lapb_transmit_frmr(lapb); }; break; }; }