162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 562306a36Sopenharmony_ci * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/errno.h> 862306a36Sopenharmony_ci#include <linux/types.h> 962306a36Sopenharmony_ci#include <linux/socket.h> 1062306a36Sopenharmony_ci#include <linux/in.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/timer.h> 1362306a36Sopenharmony_ci#include <linux/string.h> 1462306a36Sopenharmony_ci#include <linux/sockios.h> 1562306a36Sopenharmony_ci#include <linux/net.h> 1662306a36Sopenharmony_ci#include <net/ax25.h> 1762306a36Sopenharmony_ci#include <linux/inet.h> 1862306a36Sopenharmony_ci#include <linux/netdevice.h> 1962306a36Sopenharmony_ci#include <linux/skbuff.h> 2062306a36Sopenharmony_ci#include <net/sock.h> 2162306a36Sopenharmony_ci#include <net/tcp_states.h> 2262306a36Sopenharmony_ci#include <linux/uaccess.h> 2362306a36Sopenharmony_ci#include <linux/fcntl.h> 2462306a36Sopenharmony_ci#include <linux/mm.h> 2562306a36Sopenharmony_ci#include <linux/interrupt.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* 2862306a36Sopenharmony_ci * State machine for state 1, Awaiting Connection State. 2962306a36Sopenharmony_ci * The handling of the timer(s) is in file ax25_ds_timer.c. 3062306a36Sopenharmony_ci * Handling of state 0 and connection release is in ax25.c. 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_cistatic int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci switch (frametype) { 3562306a36Sopenharmony_ci case AX25_SABM: 3662306a36Sopenharmony_ci ax25->modulus = AX25_MODULUS; 3762306a36Sopenharmony_ci ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; 3862306a36Sopenharmony_ci ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); 3962306a36Sopenharmony_ci break; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci case AX25_SABME: 4262306a36Sopenharmony_ci ax25->modulus = AX25_EMODULUS; 4362306a36Sopenharmony_ci ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW]; 4462306a36Sopenharmony_ci ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); 4562306a36Sopenharmony_ci break; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci case AX25_DISC: 4862306a36Sopenharmony_ci ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE); 4962306a36Sopenharmony_ci break; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci case AX25_UA: 5262306a36Sopenharmony_ci ax25_calculate_rtt(ax25); 5362306a36Sopenharmony_ci ax25_stop_t1timer(ax25); 5462306a36Sopenharmony_ci ax25_start_t3timer(ax25); 5562306a36Sopenharmony_ci ax25_start_idletimer(ax25); 5662306a36Sopenharmony_ci ax25->vs = 0; 5762306a36Sopenharmony_ci ax25->va = 0; 5862306a36Sopenharmony_ci ax25->vr = 0; 5962306a36Sopenharmony_ci ax25->state = AX25_STATE_3; 6062306a36Sopenharmony_ci ax25->n2count = 0; 6162306a36Sopenharmony_ci if (ax25->sk != NULL) { 6262306a36Sopenharmony_ci bh_lock_sock(ax25->sk); 6362306a36Sopenharmony_ci ax25->sk->sk_state = TCP_ESTABLISHED; 6462306a36Sopenharmony_ci /* 6562306a36Sopenharmony_ci * For WAIT_SABM connections we will produce an accept 6662306a36Sopenharmony_ci * ready socket here 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ci if (!sock_flag(ax25->sk, SOCK_DEAD)) 6962306a36Sopenharmony_ci ax25->sk->sk_state_change(ax25->sk); 7062306a36Sopenharmony_ci bh_unlock_sock(ax25->sk); 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci ax25_dama_on(ax25); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /* according to DK4EG's spec we are required to 7562306a36Sopenharmony_ci * send a RR RESPONSE FINAL NR=0. 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci ax25_std_enquiry_response(ax25); 7962306a36Sopenharmony_ci break; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci case AX25_DM: 8262306a36Sopenharmony_ci if (pf) 8362306a36Sopenharmony_ci ax25_disconnect(ax25, ECONNREFUSED); 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci default: 8762306a36Sopenharmony_ci if (pf) 8862306a36Sopenharmony_ci ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND); 8962306a36Sopenharmony_ci break; 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci return 0; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/* 9662306a36Sopenharmony_ci * State machine for state 2, Awaiting Release State. 9762306a36Sopenharmony_ci * The handling of the timer(s) is in file ax25_ds_timer.c 9862306a36Sopenharmony_ci * Handling of state 0 and connection release is in ax25.c. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_cistatic int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci switch (frametype) { 10362306a36Sopenharmony_ci case AX25_SABM: 10462306a36Sopenharmony_ci case AX25_SABME: 10562306a36Sopenharmony_ci ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); 10662306a36Sopenharmony_ci ax25_dama_off(ax25); 10762306a36Sopenharmony_ci break; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci case AX25_DISC: 11062306a36Sopenharmony_ci ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); 11162306a36Sopenharmony_ci ax25_dama_off(ax25); 11262306a36Sopenharmony_ci ax25_disconnect(ax25, 0); 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci case AX25_DM: 11662306a36Sopenharmony_ci case AX25_UA: 11762306a36Sopenharmony_ci if (pf) { 11862306a36Sopenharmony_ci ax25_dama_off(ax25); 11962306a36Sopenharmony_ci ax25_disconnect(ax25, 0); 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci case AX25_I: 12462306a36Sopenharmony_ci case AX25_REJ: 12562306a36Sopenharmony_ci case AX25_RNR: 12662306a36Sopenharmony_ci case AX25_RR: 12762306a36Sopenharmony_ci if (pf) { 12862306a36Sopenharmony_ci ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); 12962306a36Sopenharmony_ci ax25_dama_off(ax25); 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci break; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci default: 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci return 0; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/* 14162306a36Sopenharmony_ci * State machine for state 3, Connected State. 14262306a36Sopenharmony_ci * The handling of the timer(s) is in file ax25_timer.c 14362306a36Sopenharmony_ci * Handling of state 0 and connection release is in ax25.c. 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_cistatic int ax25_ds_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int ns, int nr, int pf, int type) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci int queued = 0; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci switch (frametype) { 15062306a36Sopenharmony_ci case AX25_SABM: 15162306a36Sopenharmony_ci case AX25_SABME: 15262306a36Sopenharmony_ci if (frametype == AX25_SABM) { 15362306a36Sopenharmony_ci ax25->modulus = AX25_MODULUS; 15462306a36Sopenharmony_ci ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW]; 15562306a36Sopenharmony_ci } else { 15662306a36Sopenharmony_ci ax25->modulus = AX25_EMODULUS; 15762306a36Sopenharmony_ci ax25->window = ax25->ax25_dev->values[AX25_VALUES_EWINDOW]; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); 16062306a36Sopenharmony_ci ax25_stop_t1timer(ax25); 16162306a36Sopenharmony_ci ax25_start_t3timer(ax25); 16262306a36Sopenharmony_ci ax25_start_idletimer(ax25); 16362306a36Sopenharmony_ci ax25->condition = 0x00; 16462306a36Sopenharmony_ci ax25->vs = 0; 16562306a36Sopenharmony_ci ax25->va = 0; 16662306a36Sopenharmony_ci ax25->vr = 0; 16762306a36Sopenharmony_ci ax25_requeue_frames(ax25); 16862306a36Sopenharmony_ci ax25_dama_on(ax25); 16962306a36Sopenharmony_ci break; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci case AX25_DISC: 17262306a36Sopenharmony_ci ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE); 17362306a36Sopenharmony_ci ax25_dama_off(ax25); 17462306a36Sopenharmony_ci ax25_disconnect(ax25, 0); 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci case AX25_DM: 17862306a36Sopenharmony_ci ax25_dama_off(ax25); 17962306a36Sopenharmony_ci ax25_disconnect(ax25, ECONNRESET); 18062306a36Sopenharmony_ci break; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci case AX25_RR: 18362306a36Sopenharmony_ci case AX25_RNR: 18462306a36Sopenharmony_ci if (frametype == AX25_RR) 18562306a36Sopenharmony_ci ax25->condition &= ~AX25_COND_PEER_RX_BUSY; 18662306a36Sopenharmony_ci else 18762306a36Sopenharmony_ci ax25->condition |= AX25_COND_PEER_RX_BUSY; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci if (ax25_validate_nr(ax25, nr)) { 19062306a36Sopenharmony_ci if (ax25_check_iframes_acked(ax25, nr)) 19162306a36Sopenharmony_ci ax25->n2count=0; 19262306a36Sopenharmony_ci if (type == AX25_COMMAND && pf) 19362306a36Sopenharmony_ci ax25_ds_enquiry_response(ax25); 19462306a36Sopenharmony_ci } else { 19562306a36Sopenharmony_ci ax25_ds_nr_error_recovery(ax25); 19662306a36Sopenharmony_ci ax25->state = AX25_STATE_1; 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci break; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci case AX25_REJ: 20162306a36Sopenharmony_ci ax25->condition &= ~AX25_COND_PEER_RX_BUSY; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (ax25_validate_nr(ax25, nr)) { 20462306a36Sopenharmony_ci if (ax25->va != nr) 20562306a36Sopenharmony_ci ax25->n2count=0; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci ax25_frames_acked(ax25, nr); 20862306a36Sopenharmony_ci ax25_calculate_rtt(ax25); 20962306a36Sopenharmony_ci ax25_stop_t1timer(ax25); 21062306a36Sopenharmony_ci ax25_start_t3timer(ax25); 21162306a36Sopenharmony_ci ax25_requeue_frames(ax25); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (type == AX25_COMMAND && pf) 21462306a36Sopenharmony_ci ax25_ds_enquiry_response(ax25); 21562306a36Sopenharmony_ci } else { 21662306a36Sopenharmony_ci ax25_ds_nr_error_recovery(ax25); 21762306a36Sopenharmony_ci ax25->state = AX25_STATE_1; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci break; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci case AX25_I: 22262306a36Sopenharmony_ci if (!ax25_validate_nr(ax25, nr)) { 22362306a36Sopenharmony_ci ax25_ds_nr_error_recovery(ax25); 22462306a36Sopenharmony_ci ax25->state = AX25_STATE_1; 22562306a36Sopenharmony_ci break; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci if (ax25->condition & AX25_COND_PEER_RX_BUSY) { 22862306a36Sopenharmony_ci ax25_frames_acked(ax25, nr); 22962306a36Sopenharmony_ci ax25->n2count = 0; 23062306a36Sopenharmony_ci } else { 23162306a36Sopenharmony_ci if (ax25_check_iframes_acked(ax25, nr)) 23262306a36Sopenharmony_ci ax25->n2count = 0; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci if (ax25->condition & AX25_COND_OWN_RX_BUSY) { 23562306a36Sopenharmony_ci if (pf) ax25_ds_enquiry_response(ax25); 23662306a36Sopenharmony_ci break; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci if (ns == ax25->vr) { 23962306a36Sopenharmony_ci ax25->vr = (ax25->vr + 1) % ax25->modulus; 24062306a36Sopenharmony_ci queued = ax25_rx_iframe(ax25, skb); 24162306a36Sopenharmony_ci if (ax25->condition & AX25_COND_OWN_RX_BUSY) 24262306a36Sopenharmony_ci ax25->vr = ns; /* ax25->vr - 1 */ 24362306a36Sopenharmony_ci ax25->condition &= ~AX25_COND_REJECT; 24462306a36Sopenharmony_ci if (pf) { 24562306a36Sopenharmony_ci ax25_ds_enquiry_response(ax25); 24662306a36Sopenharmony_ci } else { 24762306a36Sopenharmony_ci if (!(ax25->condition & AX25_COND_ACK_PENDING)) { 24862306a36Sopenharmony_ci ax25->condition |= AX25_COND_ACK_PENDING; 24962306a36Sopenharmony_ci ax25_start_t2timer(ax25); 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci } else { 25362306a36Sopenharmony_ci if (ax25->condition & AX25_COND_REJECT) { 25462306a36Sopenharmony_ci if (pf) ax25_ds_enquiry_response(ax25); 25562306a36Sopenharmony_ci } else { 25662306a36Sopenharmony_ci ax25->condition |= AX25_COND_REJECT; 25762306a36Sopenharmony_ci ax25_ds_enquiry_response(ax25); 25862306a36Sopenharmony_ci ax25->condition &= ~AX25_COND_ACK_PENDING; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci case AX25_FRMR: 26462306a36Sopenharmony_ci case AX25_ILLEGAL: 26562306a36Sopenharmony_ci ax25_ds_establish_data_link(ax25); 26662306a36Sopenharmony_ci ax25->state = AX25_STATE_1; 26762306a36Sopenharmony_ci break; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci default: 27062306a36Sopenharmony_ci break; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci return queued; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci/* 27762306a36Sopenharmony_ci * Higher level upcall for a LAPB frame 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ciint ax25_ds_frame_in(ax25_cb *ax25, struct sk_buff *skb, int type) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci int queued = 0, frametype, ns, nr, pf; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci frametype = ax25_decode(ax25, skb, &ns, &nr, &pf); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci switch (ax25->state) { 28662306a36Sopenharmony_ci case AX25_STATE_1: 28762306a36Sopenharmony_ci queued = ax25_ds_state1_machine(ax25, skb, frametype, pf, type); 28862306a36Sopenharmony_ci break; 28962306a36Sopenharmony_ci case AX25_STATE_2: 29062306a36Sopenharmony_ci queued = ax25_ds_state2_machine(ax25, skb, frametype, pf, type); 29162306a36Sopenharmony_ci break; 29262306a36Sopenharmony_ci case AX25_STATE_3: 29362306a36Sopenharmony_ci queued = ax25_ds_state3_machine(ax25, skb, frametype, ns, nr, pf, type); 29462306a36Sopenharmony_ci break; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci return queued; 29862306a36Sopenharmony_ci} 299