llc: move the type 2 sockets out of tree

802.2 LLC is only used in tree by protocols which need the
connectionless type 1 subset: STP, which carries the bridge's BPDUs,
GARP, which sends its own UI PDUs, and SNAP. The llc2 module on top of
the core - the type 2 connection state machine, the type 1 SAP state
machine, the station component and the PF_LLC socket family - has no
in-kernel users and nobody who can test it; what we get instead is a
slow trickle of drive-by fixes.

There was a recent patch from Ernestas Kulik indicating potential
real life use, but it was new/experimental and that person is
not responding to off-list pings.

Let LLC2 follow AX.25, hamradio and AppleTalk out of the Linux tree.
We will maintain the code at: github.com/linux-netdev/mod-orphan
for anyone interested in playing with it.

PF_LLC goes in full, both the class two SOCK_STREAM and the class one
SOCK_DGRAM half, and so do /proc/net/llc/ and /proc/sys/net/llc/. Note
that the kernel also stops answering XID and TEST commands, addressed
to a SAP or to the station - those are type 1, but they lived in the
module, and they got answered whether or not any socket was open.
Nothing in tree asks for them; what the core keeps is SAP registration
and the UI path the in-tree users need.

Retain the uAPI for now, like we did for AppleTalk. Only the socket ABI
half of it is vestigial: STP, GARP, the bridge and openvswitch use the
SAP numbers it defines. Cleaning up what the core no longer needs
follows in the next patch.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20260928190800.2521749-2-kuba@kernel.org
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Jakub Kicinski 2026-09-28 12:07:58 -07:00 committed by Paolo Abeni
parent 1b8a3f9052
commit 003f21868b
34 changed files with 1 additions and 12183 deletions

View File

@ -321,7 +321,6 @@ CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_LLC2=m
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_PRIO=m

View File

@ -337,7 +337,6 @@ CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_LLC2=m
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_PRIO=m

View File

@ -90,7 +90,6 @@ CONFIG_ATM=y
CONFIG_ATM_BR2684=m
CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_LLC2=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y

View File

@ -135,7 +135,6 @@ CONFIG_ATM=y
CONFIG_ATM_BR2684=m
CONFIG_BRIDGE=m
CONFIG_VLAN_8021Q=m
CONFIG_LLC2=m
CONFIG_DEV_APPLETALK=m
CONFIG_IPDDP=m
CONFIG_IPDDP_ENCAP=y

View File

@ -70,7 +70,6 @@ CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_RAW=m
CONFIG_BRIDGE=y
CONFIG_VLAN_8021Q=y
CONFIG_LLC2=m
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_PRIO=m

View File

@ -35,7 +35,6 @@ CONFIG_INET=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_DIAG=m
CONFIG_LLC2=m
# CONFIG_WIRELESS is not set
CONFIG_EISA=y
CONFIG_PCI=y

View File

@ -9,9 +9,4 @@
#include <uapi/linux/llc.h>
#define LLC_SAP_DYN_START 0xC0
#define LLC_SAP_DYN_STOP 0xDE
#define LLC_SAP_DYN_TRIES 4
#define llc_ui_skb_cb(__skb) ((struct sockaddr_llc *)&((__skb)->cb[0]))
#endif /* __LINUX_LLC_H */

View File

@ -130,30 +130,4 @@ struct llc_sap *llc_sap_find(unsigned char sap_value);
int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
const unsigned char *dmac, unsigned char dsap);
void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
void llc_station_init(void);
void llc_station_exit(void);
#ifdef CONFIG_PROC_FS
int llc_proc_init(void);
void llc_proc_exit(void);
#else
#define llc_proc_init() (0)
#define llc_proc_exit() do { } while(0)
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_SYSCTL
int llc_sysctl_init(void);
void llc_sysctl_exit(void);
extern int sysctl_llc2_ack_timeout;
extern int sysctl_llc2_busy_timeout;
extern int sysctl_llc2_p_timeout;
extern int sysctl_llc2_rej_timeout;
#else
#define llc_sysctl_init() (0)
#define llc_sysctl_exit() do { } while(0)
#endif /* CONFIG_SYSCTL */
#endif /* LLC_H */

View File

@ -1,180 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_C_AC_H
#define LLC_C_AC_H
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
/* Connection component state transition actions */
/*
* Connection state transition actions
* (Fb = F bit; Pb = P bit; Xb = X bit)
*/
#include <linux/types.h>
struct sk_buff;
struct sock;
struct timer_list;
#define LLC_CONN_AC_CLR_REMOTE_BUSY 1
#define LLC_CONN_AC_CONN_IND 2
#define LLC_CONN_AC_CONN_CONFIRM 3
#define LLC_CONN_AC_DATA_IND 4
#define LLC_CONN_AC_DISC_IND 5
#define LLC_CONN_AC_RESET_IND 6
#define LLC_CONN_AC_RESET_CONFIRM 7
#define LLC_CONN_AC_REPORT_STATUS 8
#define LLC_CONN_AC_CLR_REMOTE_BUSY_IF_Fb_EQ_1 9
#define LLC_CONN_AC_STOP_REJ_TMR_IF_DATA_FLAG_EQ_2 10
#define LLC_CONN_AC_SEND_DISC_CMD_Pb_SET_X 11
#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_Pb 12
#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_1 13
#define LLC_CONN_AC_SEND_DM_RSP_Fb_SET_F_FLAG 14
#define LLC_CONN_AC_SEND_FRMR_RSP_Fb_SET_X 15
#define LLC_CONN_AC_RESEND_FRMR_RSP_Fb_SET_0 16
#define LLC_CONN_AC_RESEND_FRMR_RSP_Fb_SET_Pb 17
#define LLC_CONN_AC_SEND_I_CMD_Pb_SET_1 18
#define LLC_CONN_AC_RESEND_I_CMD_Pb_SET_1 19
#define LLC_CONN_AC_RESEND_I_CMD_Pb_SET_1_OR_SEND_RR 20
#define LLC_CONN_AC_SEND_I_XXX_Xb_SET_0 21
#define LLC_CONN_AC_RESEND_I_XXX_Xb_SET_0 22
#define LLC_CONN_AC_RESEND_I_XXX_Xb_SET_0_OR_SEND_RR 23
#define LLC_CONN_AC_RESEND_I_RSP_Fb_SET_1 24
#define LLC_CONN_AC_SEND_REJ_CMD_Pb_SET_1 25
#define LLC_CONN_AC_SEND_REJ_RSP_Fb_SET_1 26
#define LLC_CONN_AC_SEND_REJ_XXX_Xb_SET_0 27
#define LLC_CONN_AC_SEND_RNR_CMD_Pb_SET_1 28
#define LLC_CONN_AC_SEND_RNR_RSP_Fb_SET_1 29
#define LLC_CONN_AC_SEND_RNR_XXX_Xb_SET_0 30
#define LLC_CONN_AC_SET_REMOTE_BUSY 31
#define LLC_CONN_AC_OPTIONAL_SEND_RNR_XXX_Xb_SET_0 32
#define LLC_CONN_AC_SEND_RR_CMD_Pb_SET_1 33
#define LLC_CONN_AC_SEND_ACK_CMD_Pb_SET_1 34
#define LLC_CONN_AC_SEND_RR_RSP_Fb_SET_1 35
#define LLC_CONN_AC_SEND_ACK_RSP_Fb_SET_1 36
#define LLC_CONN_AC_SEND_RR_XXX_Xb_SET_0 37
#define LLC_CONN_AC_SEND_ACK_XXX_Xb_SET_0 38
#define LLC_CONN_AC_SEND_SABME_CMD_Pb_SET_X 39
#define LLC_CONN_AC_SEND_UA_RSP_Fb_SET_Pb 40
#define LLC_CONN_AC_SEND_UA_RSP_Fb_SET_F_FLAG 41
#define LLC_CONN_AC_S_FLAG_SET_0 42
#define LLC_CONN_AC_S_FLAG_SET_1 43
#define LLC_CONN_AC_START_P_TMR 44
#define LLC_CONN_AC_START_ACK_TMR 45
#define LLC_CONN_AC_START_REJ_TMR 46
#define LLC_CONN_AC_START_ACK_TMR_IF_NOT_RUNNING 47
#define LLC_CONN_AC_STOP_ACK_TMR 48
#define LLC_CONN_AC_STOP_P_TMR 49
#define LLC_CONN_AC_STOP_REJ_TMR 50
#define LLC_CONN_AC_STOP_ALL_TMRS 51
#define LLC_CONN_AC_STOP_OTHER_TMRS 52
#define LLC_CONN_AC_UPDATE_Nr_RECEIVED 53
#define LLC_CONN_AC_UPDATE_P_FLAG 54
#define LLC_CONN_AC_DATA_FLAG_SET_2 55
#define LLC_CONN_AC_DATA_FLAG_SET_0 56
#define LLC_CONN_AC_DATA_FLAG_SET_1 57
#define LLC_CONN_AC_DATA_FLAG_SET_1_IF_DATA_FLAG_EQ_0 58
#define LLC_CONN_AC_P_FLAG_SET_0 59
#define LLC_CONN_AC_P_FLAG_SET_P 60
#define LLC_CONN_AC_REMOTE_BUSY_SET_0 61
#define LLC_CONN_AC_RETRY_CNT_SET_0 62
#define LLC_CONN_AC_RETRY_CNT_INC_BY_1 63
#define LLC_CONN_AC_Vr_SET_0 64
#define LLC_CONN_AC_Vr_INC_BY_1 65
#define LLC_CONN_AC_Vs_SET_0 66
#define LLC_CONN_AC_Vs_SET_Nr 67
#define LLC_CONN_AC_F_FLAG_SET_P 68
#define LLC_CONN_AC_STOP_SENDACK_TMR 70
#define LLC_CONN_AC_START_SENDACK_TMR_IF_NOT_RUNNING 71
typedef int (*llc_conn_action_t)(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_data_ind(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_rst_confirm(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_s_flag_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_s_flag_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ac_stop_ack_timer(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_stop_rej_timer(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_data_flag_2(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_data_flag_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_data_flag_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ac_set_p_flag_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_remote_busy_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_retry_cnt_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_cause_flag_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_cause_flag_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_inc_retry_cnt_by_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_vr_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_inc_vr_by_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_vs_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb);
int llc_conn_disc(struct sock *sk, struct sk_buff *skb);
int llc_conn_reset(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb);
u8 llc_circular_between(u8 a, u8 b, u8 c);
int llc_conn_ac_send_ack_if_needed(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_rst_sendack_flag(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_send_i_as_ack(struct sock *sk, struct sk_buff *skb);
void llc_conn_busy_tmr_cb(struct timer_list *t);
void llc_conn_pf_cycle_tmr_cb(struct timer_list *t);
void llc_conn_ack_tmr_cb(struct timer_list *t);
void llc_conn_rej_tmr_cb(struct timer_list *t);
void llc_conn_set_p_flag(struct sock *sk, u8 value);
#endif /* LLC_C_AC_H */

View File

@ -1,217 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_C_EV_H
#define LLC_C_EV_H
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <net/sock.h>
/* Connection component state transition event qualifiers */
/* Types of events (possible values in 'ev->type') */
#define LLC_CONN_EV_TYPE_SIMPLE 1
#define LLC_CONN_EV_TYPE_CONDITION 2
#define LLC_CONN_EV_TYPE_PRIM 3
#define LLC_CONN_EV_TYPE_PDU 4 /* command/response PDU */
#define LLC_CONN_EV_TYPE_ACK_TMR 5
#define LLC_CONN_EV_TYPE_P_TMR 6
#define LLC_CONN_EV_TYPE_REJ_TMR 7
#define LLC_CONN_EV_TYPE_BUSY_TMR 8
#define LLC_CONN_EV_TYPE_RPT_STATUS 9
#define LLC_CONN_EV_TYPE_SENDACK_TMR 10
#define NBR_CONN_EV 5
/* Connection events which cause state transitions when fully qualified */
#define LLC_CONN_EV_CONN_REQ 1
#define LLC_CONN_EV_CONN_RESP 2
#define LLC_CONN_EV_DATA_REQ 3
#define LLC_CONN_EV_DISC_REQ 4
#define LLC_CONN_EV_RESET_REQ 5
#define LLC_CONN_EV_RESET_RESP 6
#define LLC_CONN_EV_LOCAL_BUSY_DETECTED 7
#define LLC_CONN_EV_LOCAL_BUSY_CLEARED 8
#define LLC_CONN_EV_RX_BAD_PDU 9
#define LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X 10
#define LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X 11
#define LLC_CONN_EV_RX_FRMR_RSP_Fbit_SET_X 12
#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X 13
#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X_UNEXPD_Ns 14
#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_X_INVAL_Ns 15
#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X 16
#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_UNEXPD_Ns 17
#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_INVAL_Ns 18
#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_X 19
#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X 20
#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_X 21
#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_X 22
#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_X 23
#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_X 24
#define LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X 25
#define LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X 26
#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_X 27
#define LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_X 28
#define LLC_CONN_EV_RX_XXX_YYY 29
#define LLC_CONN_EV_RX_ZZZ_CMD_Pbit_SET_X_INVAL_Nr 30
#define LLC_CONN_EV_RX_ZZZ_RSP_Fbit_SET_X_INVAL_Nr 31
#define LLC_CONN_EV_P_TMR_EXP 32
#define LLC_CONN_EV_ACK_TMR_EXP 33
#define LLC_CONN_EV_REJ_TMR_EXP 34
#define LLC_CONN_EV_BUSY_TMR_EXP 35
#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_1 36
#define LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_0 37
#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns 38
#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns 39
#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns 40
#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns 41
#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 42
#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 43
#define LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 44
#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 45
#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 46
#define LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 47
#define LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 48
#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 49
#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 50
#define LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 51
#define LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 52
#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 53
#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 54
#define LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 55
#define LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 56
#define LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 57
#define LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_1 58
#define LLC_CONN_EV_TX_BUFF_FULL 59
#define LLC_CONN_EV_INIT_P_F_CYCLE 100
/*
* Connection event qualifiers; for some events a certain combination of
* these qualifiers must be TRUE before event recognized valid for state;
* these constants act as indexes into the Event Qualifier function
* table
*/
#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_1 1
#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_0 2
#define LLC_CONN_EV_QFY_DATA_FLAG_EQ_2 3
#define LLC_CONN_EV_QFY_P_FLAG_EQ_1 4
#define LLC_CONN_EV_QFY_P_FLAG_EQ_0 5
#define LLC_CONN_EV_QFY_P_FLAG_EQ_Fbit 6
#define LLC_CONN_EV_QFY_REMOTE_BUSY_EQ_0 7
#define LLC_CONN_EV_QFY_RETRY_CNT_LT_N2 8
#define LLC_CONN_EV_QFY_RETRY_CNT_GTE_N2 9
#define LLC_CONN_EV_QFY_S_FLAG_EQ_1 10
#define LLC_CONN_EV_QFY_S_FLAG_EQ_0 11
#define LLC_CONN_EV_QFY_INIT_P_F_CYCLE 12
struct llc_conn_state_ev {
u8 type;
u8 prim;
u8 prim_type;
u8 reason;
u8 status;
u8 ind_prim;
u8 cfm_prim;
};
static __inline__ struct llc_conn_state_ev *llc_conn_ev(struct sk_buff *skb)
{
return (struct llc_conn_state_ev *)skb->cb;
}
typedef int (*llc_conn_ev_t)(struct sock *sk, struct sk_buff *skb);
typedef int (*llc_conn_ev_qfyr_t)(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb);
/* NOT_USED functions and their variations */
int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb);
/* Available connection action qualifiers */
int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk,
struct sk_buff *skb);
int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, struct sk_buff *skb);
int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, struct sk_buff *skb);
static __inline__ int llc_conn_space(struct sock *sk, struct sk_buff *skb)
{
return atomic_read(&sk->sk_rmem_alloc) + skb->truesize <
(unsigned int)sk->sk_rcvbuf;
}
#endif /* LLC_C_EV_H */

View File

@ -1,46 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_C_ST_H
#define LLC_C_ST_H
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <net/llc_c_ac.h>
#include <net/llc_c_ev.h>
/* Connection component state management */
/* connection states */
#define LLC_CONN_OUT_OF_SVC 0 /* prior to allocation */
#define LLC_CONN_STATE_ADM 1 /* disc, initial state */
#define LLC_CONN_STATE_SETUP 2 /* disconnected state */
#define LLC_CONN_STATE_NORMAL 3 /* connected state */
#define LLC_CONN_STATE_BUSY 4 /* connected state */
#define LLC_CONN_STATE_REJ 5 /* connected state */
#define LLC_CONN_STATE_AWAIT 6 /* connected state */
#define LLC_CONN_STATE_AWAIT_BUSY 7 /* connected state */
#define LLC_CONN_STATE_AWAIT_REJ 8 /* connected state */
#define LLC_CONN_STATE_D_CONN 9 /* disconnected state */
#define LLC_CONN_STATE_RESET 10 /* disconnected state */
#define LLC_CONN_STATE_ERROR 11 /* disconnected state */
#define LLC_CONN_STATE_TEMP 12 /* disconnected state */
#define NBR_CONN_STATES 12 /* size of state table */
#define NO_STATE_CHANGE 100
/* Connection state table structure */
struct llc_conn_state_trans {
llc_conn_ev_t ev;
u8 next_state;
const llc_conn_ev_qfyr_t *ev_qualifiers;
const llc_conn_action_t *ev_actions;
};
struct llc_conn_state {
u8 current_state;
const struct llc_conn_state_trans **transitions;
};
extern struct llc_conn_state llc_conn_state_table[];
#endif /* LLC_C_ST_H */

View File

@ -1,114 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_CONN_H
#define LLC_CONN_H
/*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001, 2002 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/timer.h>
#include <net/llc_if.h>
#include <net/sock.h>
#include <linux/llc.h>
#define LLC_EVENT 1
#define LLC_PACKET 2
#define LLC2_P_TIME 2
#define LLC2_ACK_TIME 1
#define LLC2_REJ_TIME 3
#define LLC2_BUSY_TIME 3
struct llc_timer {
struct timer_list timer;
unsigned long expire; /* timer expire time */
};
struct llc_sock {
/* struct sock must be the first member of llc_sock */
struct sock sk;
struct sockaddr_llc addr; /* address sock is bound to */
u8 state; /* state of connection */
struct llc_sap *sap; /* pointer to parent SAP */
struct llc_addr laddr; /* lsap/mac pair */
struct llc_addr daddr; /* dsap/mac pair */
struct net_device *dev; /* device to send to remote */
netdevice_tracker dev_tracker;
u32 copied_seq; /* head of yet unread data */
u8 retry_count; /* number of retries */
u8 ack_must_be_send;
u8 first_pdu_Ns;
u8 npta;
struct llc_timer ack_timer;
struct llc_timer pf_cycle_timer;
struct llc_timer rej_sent_timer;
struct llc_timer busy_state_timer; /* ind busy clr at remote LLC */
u8 vS; /* seq# next in-seq I-PDU tx'd*/
u8 vR; /* seq# next in-seq I-PDU rx'd*/
u32 n2; /* max nbr re-tx's for timeout*/
u32 n1; /* max nbr octets in I PDU */
u8 k; /* tx window size; max = 127 */
u8 rw; /* rx window size; max = 127 */
u8 p_flag; /* state flags */
u8 f_flag;
u8 s_flag;
u8 data_flag;
u8 remote_busy_flag;
u8 cause_flag;
struct sk_buff_head pdu_unack_q; /* PUDs sent/waiting ack */
u16 link; /* network layer link number */
u8 X; /* a temporary variable */
u8 ack_pf; /* this flag indicates what is
the P-bit of acknowledge */
u8 failed_data_req; /* recognize that already exist a
failed llc_data_req_handler
(tx_buffer_full or unacceptable
state */
u8 dec_step;
u8 inc_cntr;
u8 dec_cntr;
u8 connect_step;
u8 last_nr; /* NR of last pdu received */
u32 rx_pdu_hdr; /* used for saving header of last pdu
received and caused sending FRMR.
Used for resending FRMR */
u32 cmsg_flags;
struct hlist_node dev_hash_node;
};
static inline struct llc_sock *llc_sk(const struct sock *sk)
{
return (struct llc_sock *)sk;
}
static __inline__ void llc_set_backlog_type(struct sk_buff *skb, char type)
{
skb->cb[sizeof(skb->cb) - 1] = type;
}
static __inline__ char llc_backlog_type(struct sk_buff *skb)
{
return skb->cb[sizeof(skb->cb) - 1];
}
struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority,
struct proto *prot, int kern);
void llc_sk_stop_all_timers(struct sock *sk, bool sync);
void llc_sk_free(struct sock *sk);
void llc_sk_reset(struct sock *sk);
/* Access to a connection */
int llc_conn_state_process(struct sock *sk, struct sk_buff *skb);
void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb);
void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb);
void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit);
void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit);
int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr, u16 *how_many_unacked);
struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
struct llc_addr *laddr, const struct net *net);
void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk);
void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
u8 llc_data_accept_state(u8 state);
void llc_build_offset_table(void);
#endif /* LLC_CONN_H */

View File

@ -1,63 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_IF_H
#define LLC_IF_H
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
/* Defines LLC interface to network layer */
/* Available primitives */
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/llc.h>
#include <linux/etherdevice.h>
#include <net/llc.h>
#define LLC_DATAUNIT_PRIM 1
#define LLC_CONN_PRIM 2
#define LLC_DATA_PRIM 3
#define LLC_DISC_PRIM 4
#define LLC_RESET_PRIM 5
#define LLC_FLOWCONTROL_PRIM 6 /* Not supported at this time */
#define LLC_DISABLE_PRIM 7
#define LLC_XID_PRIM 8
#define LLC_TEST_PRIM 9
#define LLC_SAP_ACTIVATION 10
#define LLC_SAP_DEACTIVATION 11
#define LLC_NBR_PRIMITIVES 11
#define LLC_IND 1
#define LLC_CONFIRM 2
/* Primitive type */
#define LLC_PRIM_TYPE_REQ 1
#define LLC_PRIM_TYPE_IND 2
#define LLC_PRIM_TYPE_RESP 3
#define LLC_PRIM_TYPE_CONFIRM 4
/* Reset reasons, remote entity or local LLC */
#define LLC_RESET_REASON_REMOTE 1
#define LLC_RESET_REASON_LOCAL 2
/* Disconnect reasons */
#define LLC_DISC_REASON_RX_DM_RSP_PDU 0
#define LLC_DISC_REASON_RX_DISC_CMD_PDU 1
#define LLC_DISC_REASON_ACK_TMR_EXP 2
/* Confirm reasons */
#define LLC_STATUS_CONN 0 /* connect confirm & reset confirm */
#define LLC_STATUS_DISC 1 /* connect confirm & reset confirm */
#define LLC_STATUS_FAILED 2 /* connect confirm & reset confirm */
#define LLC_STATUS_IMPOSSIBLE 3 /* connect confirm */
#define LLC_STATUS_RECEIVED 4 /* data conn */
#define LLC_STATUS_REMOTE_BUSY 5 /* data conn */
#define LLC_STATUS_REFUSE 6 /* data conn */
#define LLC_STATUS_CONFLICT 7 /* disconnect conn */
#define LLC_STATUS_RESET_DONE 8 /* */
int llc_establish_connection(struct sock *sk, const u8 *lmac, u8 *dmac,
u8 dsap);
int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb);
int llc_send_disc(struct sock *sk);
#endif /* LLC_IF_H */

View File

@ -1,35 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_S_AC_H
#define LLC_S_AC_H
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
struct llc_sap;
struct sk_buff;
/* SAP component actions */
#define SAP_ACT_UNITDATA_IND 1
#define SAP_ACT_SEND_UI 2
#define SAP_ACT_SEND_XID_C 3
#define SAP_ACT_SEND_XID_R 4
#define SAP_ACT_SEND_TEST_C 5
#define SAP_ACT_SEND_TEST_R 6
#define SAP_ACT_REPORT_STATUS 7
#define SAP_ACT_XID_IND 8
#define SAP_ACT_TEST_IND 9
/* All action functions must look like this */
typedef int (*llc_sap_action_t)(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_report_status(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb);
#endif /* LLC_S_AC_H */

View File

@ -1,61 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_S_EV_H
#define LLC_S_EV_H
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/skbuff.h>
#include <net/llc.h>
/* Defines SAP component events */
/* Types of events (possible values in 'ev->type') */
#define LLC_SAP_EV_TYPE_SIMPLE 1
#define LLC_SAP_EV_TYPE_CONDITION 2
#define LLC_SAP_EV_TYPE_PRIM 3
#define LLC_SAP_EV_TYPE_PDU 4 /* command/response PDU */
#define LLC_SAP_EV_TYPE_ACK_TMR 5
#define LLC_SAP_EV_TYPE_RPT_STATUS 6
#define LLC_SAP_EV_ACTIVATION_REQ 1
#define LLC_SAP_EV_RX_UI 2
#define LLC_SAP_EV_UNITDATA_REQ 3
#define LLC_SAP_EV_XID_REQ 4
#define LLC_SAP_EV_RX_XID_C 5
#define LLC_SAP_EV_RX_XID_R 6
#define LLC_SAP_EV_TEST_REQ 7
#define LLC_SAP_EV_RX_TEST_C 8
#define LLC_SAP_EV_RX_TEST_R 9
#define LLC_SAP_EV_DEACTIVATION_REQ 10
struct llc_sap_state_ev {
u8 prim;
u8 prim_type;
u8 type;
u8 reason;
u8 ind_cfm_flag;
struct llc_addr saddr;
struct llc_addr daddr;
};
static __inline__ struct llc_sap_state_ev *llc_sap_ev(struct sk_buff *skb)
{
return (struct llc_sap_state_ev *)skb->cb;
}
struct llc_sap;
typedef int (*llc_sap_ev_t)(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb);
int llc_sap_ev_deactivation_req(struct llc_sap *sap, struct sk_buff *skb);
#endif /* LLC_S_EV_H */

View File

@ -1,32 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_S_ST_H
#define LLC_S_ST_H
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/types.h>
#include <net/llc_s_ac.h>
#include <net/llc_s_ev.h>
struct llc_sap_state_trans;
#define LLC_NR_SAP_STATES 2 /* size of state table */
/* structures and types */
/* SAP state table structure */
struct llc_sap_state_trans {
llc_sap_ev_t ev;
u8 next_state;
const llc_sap_action_t *ev_actions;
};
struct llc_sap_state {
u8 curr_state;
const struct llc_sap_state_trans **transitions;
};
/* only access to SAP state table */
extern struct llc_sap_state llc_sap_state_table[LLC_NR_SAP_STATES];
#endif /* LLC_S_ST_H */

View File

@ -1,26 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef LLC_SAP_H
#define LLC_SAP_H
#include <asm/types.h>
/*
* Copyright (c) 1997 by Procom Technology,Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
struct llc_sap;
struct net_device;
struct sk_buff;
struct sock;
void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
void llc_save_primitive(struct sock *sk, struct sk_buff *skb,
unsigned char prim);
struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
u8 type, u32 data_size);
void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb,
unsigned char *dmac, unsigned char dsap);
void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
unsigned char *dmac, unsigned char dsap);
#endif /* LLC_SAP_H */

View File

@ -1,10 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
config LLC
tristate
config LLC2
tristate "ANSI/IEEE 802.2 LLC type 2 Support"
select LLC
help
This is a Logical Link Layer type 2, connection oriented support.
Select this if you want to have support for PF_LLC sockets.

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
###########################################################################
# Makefile for the Linux 802.2 LLC (fully-functional) layer.
# Makefile for the Linux 802.2 LLC layer.
#
# Copyright (c) 1997 by Procom Technology,Inc.
# 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
@ -9,11 +9,3 @@
obj-$(CONFIG_LLC) += llc.o
llc-y := llc_core.o llc_input.o llc_output.o
obj-$(CONFIG_LLC2) += llc2.o
llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \
llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o
llc2-$(CONFIG_PROC_FS) += llc_proc.o
llc2-$(CONFIG_SYSCTL) += sysctl_net_llc.o

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,742 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* llc_c_ev.c - Connection component state transition event qualifiers
*
* A 'state' consists of a number of possible event matching functions,
* the actions associated with each being executed when that event is
* matched; a 'state machine' accepts events in a serial fashion from an
* event queue. Each event is passed to each successive event matching
* function until a match is made (the event matching function returns
* success, or '0') or the list of event matching functions is exhausted.
* If a match is made, the actions associated with the event are executed
* and the state is changed to that event's transition state. Before some
* events are recognized, even after a match has been made, a certain
* number of 'event qualifier' functions must also be executed. If these
* all execute successfully, then the event is finally executed.
*
* These event functions must return 0 for success, to show a matched
* event, of 1 if the event does not match. Event qualifier functions
* must return a 0 for success or a non-zero for failure. Each function
* is simply responsible for verifying one single thing and returning
* either a success or failure.
*
* All of followed event functions are described in 802.2 LLC Protocol
* standard document except two functions that we added that will explain
* in their comments, at below.
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/netdevice.h>
#include <net/llc_conn.h>
#include <net/llc_sap.h>
#include <net/sock.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_ev.h>
#include <net/llc_pdu.h>
#if 1
#define dprintk(args...) printk(KERN_DEBUG args)
#else
#define dprintk(args...)
#endif
/**
* llc_util_ns_inside_rx_window - check if sequence number is in rx window
* @ns: sequence number of received pdu.
* @vr: sequence number which receiver expects to receive.
* @rw: receive window size of receiver.
*
* Checks if sequence number of received PDU is in range of receive
* window. Returns 0 for success, 1 otherwise
*/
static u16 llc_util_ns_inside_rx_window(u8 ns, u8 vr, u8 rw)
{
return !llc_circular_between(vr, ns,
(vr + rw - 1) % LLC_2_SEQ_NBR_MODULO);
}
/**
* llc_util_nr_inside_tx_window - check if sequence number is in tx window
* @sk: current connection.
* @nr: N(R) of received PDU.
*
* This routine checks if N(R) of received PDU is in range of transmit
* window; on the other hand checks if received PDU acknowledges some
* outstanding PDUs that are in transmit window. Returns 0 for success, 1
* otherwise.
*/
static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr)
{
u8 nr1, nr2;
struct sk_buff *skb;
struct llc_pdu_sn *pdu;
struct llc_sock *llc = llc_sk(sk);
int rc = 0;
if (llc->dev->flags & IFF_LOOPBACK)
goto out;
rc = 1;
if (skb_queue_empty(&llc->pdu_unack_q))
goto out;
skb = skb_peek(&llc->pdu_unack_q);
pdu = llc_pdu_sn_hdr(skb);
nr1 = LLC_I_GET_NS(pdu);
skb = skb_peek_tail(&llc->pdu_unack_q);
pdu = llc_pdu_sn_hdr(skb);
nr2 = LLC_I_GET_NS(pdu);
rc = !llc_circular_between(nr1, nr, (nr2 + 1) % LLC_2_SEQ_NBR_MODULO);
out:
return rc;
}
int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->prim == LLC_CONN_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
}
int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->prim == LLC_DATA_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
}
int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->prim == LLC_DISC_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
}
int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->prim == LLC_RESET_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
}
int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1;
}
int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1;
}
int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb)
{
return 1;
}
int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC ? 0 : 1;
}
int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM ? 0 : 1;
}
int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR ? 0 : 1;
}
int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) &&
LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_0(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) &&
LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_1(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
const u8 vr = llc_sk(sk)->vR;
const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_0(pdu) && ns != vr &&
!llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
}
int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
const u8 vr = llc_sk(sk)->vR;
const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_1(pdu) && ns != vr &&
!llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
}
int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
struct sk_buff *skb)
{
const struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb);
const u8 vr = llc_sk(sk)->vR;
const u8 ns = LLC_I_GET_NS(pdu);
const u16 rc = LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
ns != vr &&
llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
if (!rc)
dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
__func__, llc_sk(sk)->state, ns, vr);
return rc;
}
int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) &&
LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_0(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_1(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) &&
LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
}
int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
const u8 vr = llc_sk(sk)->vR;
const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_0(pdu) && ns != vr &&
!llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
}
int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
const u8 vr = llc_sk(sk)->vR;
const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
LLC_I_PF_IS_1(pdu) && ns != vr &&
!llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
}
int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
const u8 vr = llc_sk(sk)->vR;
const u8 ns = LLC_I_GET_NS(pdu);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
!llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
}
int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
const u8 vr = llc_sk(sk)->vR;
const u8 ns = LLC_I_GET_NS(pdu);
const u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
ns != vr &&
llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
if (!rc)
dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
__func__, llc_sk(sk)->state, ns, vr);
return rc;
}
int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) &&
LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1;
}
int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) &&
LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1;
}
int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
}
int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
}
int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
}
int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) &&
LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1;
}
int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) &&
LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1;
}
int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1;
}
int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1;
}
int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) &&
LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RR ? 0 : 1;
}
int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) &&
LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RR ? 0 : 1;
}
int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) &&
LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_0(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1;
}
int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
return llc_conn_space(sk, skb) &&
LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
LLC_S_PF_IS_1(pdu) &&
LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1;
}
int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
{
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME ? 0 : 1;
}
int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_UA ? 0 : 1;
}
int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
{
u16 rc = 1;
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
if (LLC_PDU_IS_CMD(pdu)) {
if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
if (LLC_I_PF_IS_1(pdu))
rc = 0;
} else if (LLC_PDU_TYPE_IS_U(pdu) && LLC_U_PF_IS_1(pdu))
rc = 0;
}
return rc;
}
int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
{
u16 rc = 1;
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
if (LLC_PDU_IS_CMD(pdu)) {
if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu))
rc = 0;
else if (LLC_PDU_TYPE_IS_U(pdu))
switch (LLC_U_PDU_CMD(pdu)) {
case LLC_2_PDU_CMD_SABME:
case LLC_2_PDU_CMD_DISC:
rc = 0;
break;
}
}
return rc;
}
int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
{
u16 rc = 1;
const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
if (LLC_PDU_IS_RSP(pdu)) {
if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu))
rc = 0;
else if (LLC_PDU_TYPE_IS_U(pdu))
switch (LLC_U_PDU_RSP(pdu)) {
case LLC_2_PDU_RSP_UA:
case LLC_2_PDU_RSP_DM:
case LLC_2_PDU_RSP_FRMR:
rc = 0;
break;
}
}
return rc;
}
int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
struct sk_buff *skb)
{
u16 rc = 1;
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
const u8 vs = llc_sk(sk)->vS;
const u8 nr = LLC_I_GET_NR(pdu);
if (LLC_PDU_IS_CMD(pdu) &&
(LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
__func__, llc_sk(sk)->state, vs, nr);
rc = 0;
}
return rc;
}
int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
struct sk_buff *skb)
{
u16 rc = 1;
const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
const u8 vs = llc_sk(sk)->vS;
const u8 nr = LLC_I_GET_NR(pdu);
if (LLC_PDU_IS_RSP(pdu) &&
(LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
rc = 0;
dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
__func__, llc_sk(sk)->state, vs, nr);
}
return rc;
}
int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb)
{
return 0;
}
int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type != LLC_CONN_EV_TYPE_P_TMR;
}
int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type != LLC_CONN_EV_TYPE_ACK_TMR;
}
int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type != LLC_CONN_EV_TYPE_REJ_TMR;
}
int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR;
}
int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb)
{
return 1;
}
int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb)
{
const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
ev->prim_type == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1;
}
/* Event qualifier functions
*
* these functions simply verify the value of a state flag associated with
* the connection and return either a 0 for success or a non-zero value
* for not-success; verify the event is the type we expect
*/
int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk, struct sk_buff *skb)
{
return llc_sk(sk)->data_flag != 1;
}
int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, struct sk_buff *skb)
{
return llc_sk(sk)->data_flag;
}
int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, struct sk_buff *skb)
{
return llc_sk(sk)->data_flag != 2;
}
int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb)
{
return llc_sk(sk)->p_flag != 1;
}
/**
* llc_conn_ev_qlfy_last_frame_eq_1 - checks if frame is last in tx window
* @sk: current connection structure.
* @skb: current event.
*
* This function determines when frame which is sent, is last frame of
* transmit window, if it is then this function return zero else return
* one. This function is used for sending last frame of transmit window
* as I-format command with p-bit set to one. Returns 0 if frame is last
* frame, 1 otherwise.
*/
int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk, struct sk_buff *skb)
{
return !(skb_queue_len(&llc_sk(sk)->pdu_unack_q) + 1 == llc_sk(sk)->k);
}
/**
* llc_conn_ev_qlfy_last_frame_eq_0 - checks if frame isn't last in tx window
* @sk: current connection structure.
* @skb: current event.
*
* This function determines when frame which is sent, isn't last frame of
* transmit window, if it isn't then this function return zero else return
* one. Returns 0 if frame isn't last frame, 1 otherwise.
*/
int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk, struct sk_buff *skb)
{
return skb_queue_len(&llc_sk(sk)->pdu_unack_q) + 1 == llc_sk(sk)->k;
}
int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct sk_buff *skb)
{
return llc_sk(sk)->p_flag;
}
int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb)
{
u8 f_bit;
llc_pdu_decode_pf_bit(skb, &f_bit);
return llc_sk(sk)->p_flag == f_bit ? 0 : 1;
}
int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk, struct sk_buff *skb)
{
return llc_sk(sk)->remote_busy_flag;
}
int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, struct sk_buff *skb)
{
return !llc_sk(sk)->remote_busy_flag;
}
int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, struct sk_buff *skb)
{
return !(llc_sk(sk)->retry_count < llc_sk(sk)->n2);
}
int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, struct sk_buff *skb)
{
return !(llc_sk(sk)->retry_count >= llc_sk(sk)->n2);
}
int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb)
{
return !llc_sk(sk)->s_flag;
}
int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb)
{
return llc_sk(sk)->s_flag;
}
int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, struct sk_buff *skb)
{
return !llc_sk(sk)->cause_flag;
}
int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, struct sk_buff *skb)
{
return llc_sk(sk)->cause_flag;
}
int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->status = LLC_STATUS_CONN;
return 0;
}
int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->status = LLC_STATUS_DISC;
return 0;
}
int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->status = LLC_STATUS_FAILED;
return 0;
}
int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk,
struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->status = LLC_STATUS_REMOTE_BUSY;
return 0;
}
int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->status = LLC_STATUS_REFUSE;
return 0;
}
int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->status = LLC_STATUS_CONFLICT;
return 0;
}
int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->status = LLC_STATUS_RESET_DONE;
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,151 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* llc_if.c - Defines LLC interface to upper layer
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/gfp.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/errno.h>
#include <net/llc_if.h>
#include <net/llc_sap.h>
#include <net/llc_s_ev.h>
#include <net/llc_conn.h>
#include <net/sock.h>
#include <net/llc_c_ev.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_st.h>
#include <net/tcp_states.h>
/**
* llc_build_and_send_pkt - Connection data sending for upper layers.
* @sk: connection
* @skb: packet to send
*
* This function is called when upper layer wants to send data using
* connection oriented communication mode. During sending data, connection
* will be locked and received frames and expired timers will be queued.
* Returns 0 for success, -ECONNABORTED when the connection already
* closed and -EBUSY when sending data is not permitted in this state or
* LLC has send an I pdu with p bit set to 1 and is waiting for it's
* response.
*
* This function always consumes a reference to the skb.
*/
int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev;
int rc = -ECONNABORTED;
struct llc_sock *llc = llc_sk(sk);
if (unlikely(llc->state == LLC_CONN_STATE_ADM))
goto out_free;
rc = -EBUSY;
if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */
llc->p_flag)) {
llc->failed_data_req = 1;
goto out_free;
}
ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->prim = LLC_DATA_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ;
skb->dev = llc->dev;
return llc_conn_state_process(sk, skb);
out_free:
kfree_skb(skb);
return rc;
}
/**
* llc_establish_connection - Called by upper layer to establish a conn
* @sk: connection
* @lmac: local mac address
* @dmac: destination mac address
* @dsap: destination sap
*
* Upper layer calls this to establish an LLC connection with a remote
* machine. This function packages a proper event and sends it connection
* component state machine. Success or failure of connection
* establishment will inform to upper layer via calling it's confirm
* function and passing proper information.
*/
int llc_establish_connection(struct sock *sk, const u8 *lmac, u8 *dmac, u8 dsap)
{
int rc = -EISCONN;
struct llc_addr laddr, daddr;
struct sk_buff *skb;
struct llc_sock *llc = llc_sk(sk);
struct sock *existing;
laddr.lsap = llc->sap->laddr.lsap;
daddr.lsap = dsap;
memcpy(daddr.mac, dmac, sizeof(daddr.mac));
memcpy(laddr.mac, lmac, sizeof(laddr.mac));
existing = llc_lookup_established(llc->sap, &daddr, &laddr, sock_net(sk));
if (existing) {
if (existing->sk_state == TCP_ESTABLISHED) {
sk = existing;
goto out_put;
} else
sock_put(existing);
}
sock_hold(sk);
rc = -ENOMEM;
skb = alloc_skb(0, GFP_ATOMIC);
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->prim = LLC_CONN_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ;
skb_set_owner_w(skb, sk);
rc = llc_conn_state_process(sk, skb);
}
out_put:
sock_put(sk);
return rc;
}
/**
* llc_send_disc - Called by upper layer to close a connection
* @sk: connection to be closed
*
* Upper layer calls this when it wants to close an established LLC
* connection with a remote machine. This function packages a proper event
* and sends it to connection component state machine. Returns 0 for
* success, 1 otherwise.
*/
int llc_send_disc(struct sock *sk)
{
u16 rc = 1;
struct llc_conn_state_ev *ev;
struct sk_buff *skb;
sock_hold(sk);
if (sk->sk_type != SOCK_STREAM || sk->sk_state != TCP_ESTABLISHED ||
llc_sk(sk)->state == LLC_CONN_STATE_ADM ||
llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC)
goto out;
/*
* Postpone unassigning the connection from its SAP and returning the
* connection until all ACTIONs have been completely executed
*/
skb = alloc_skb(0, GFP_ATOMIC);
if (!skb)
goto out;
skb_set_owner_w(skb, sk);
sk->sk_state = TCP_CLOSING;
ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->prim = LLC_DISC_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ;
rc = llc_conn_state_process(sk, skb);
out:
sock_put(sk);
return rc;
}

View File

@ -11,7 +11,6 @@
#include <net/net_namespace.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
#include <net/llc_sap.h>
#if 0
#define dprintk(args...) printk(KERN_DEBUG args)

View File

@ -1,366 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* llc_pdu.c - access to PDU internals
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/netdevice.h>
#include <net/llc_pdu.h>
static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type);
static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu);
void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type)
{
llc_pdu_un_hdr(skb)->ssap |= pdu_type;
}
/**
* llc_pdu_set_pf_bit - sets poll/final bit in LLC header
* @skb: Frame to set bit in
* @bit_value: poll/final bit (0 or 1).
*
* This function sets poll/final bit in LLC header (based on type of PDU).
* in I or S pdus, p/f bit is right bit of fourth byte in header. in U
* pdus p/f bit is fifth bit of third byte.
*/
void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value)
{
u8 pdu_type;
struct llc_pdu_sn *pdu;
llc_pdu_decode_pdu_type(skb, &pdu_type);
pdu = llc_pdu_sn_hdr(skb);
switch (pdu_type) {
case LLC_PDU_TYPE_I:
case LLC_PDU_TYPE_S:
pdu->ctrl_2 = (pdu->ctrl_2 & 0xFE) | bit_value;
break;
case LLC_PDU_TYPE_U:
pdu->ctrl_1 |= (pdu->ctrl_1 & 0xEF) | (bit_value << 4);
break;
}
}
/**
* llc_pdu_decode_pf_bit - extracs poll/final bit from LLC header
* @skb: input skb that p/f bit must be extracted from it
* @pf_bit: poll/final bit (0 or 1)
*
* This function extracts poll/final bit from LLC header (based on type of
* PDU). In I or S pdus, p/f bit is right bit of fourth byte in header. In
* U pdus p/f bit is fifth bit of third byte.
*/
void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
{
u8 pdu_type;
struct llc_pdu_sn *pdu;
llc_pdu_decode_pdu_type(skb, &pdu_type);
pdu = llc_pdu_sn_hdr(skb);
switch (pdu_type) {
case LLC_PDU_TYPE_I:
case LLC_PDU_TYPE_S:
*pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
break;
case LLC_PDU_TYPE_U:
*pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
break;
}
}
/**
* llc_pdu_init_as_disc_cmd - Builds DISC PDU
* @skb: Address of the skb to build
* @p_bit: The P bit to set in the PDU
*
* Builds a pdu frame as a DISC command.
*/
void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
{
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_CMD_DISC;
pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
}
/**
* llc_pdu_init_as_i_cmd - builds I pdu
* @skb: Address of the skb to build
* @p_bit: The P bit to set in the PDU
* @ns: The sequence number of the data PDU
* @nr: The seq. number of the expected I PDU from the remote
*
* Builds a pdu frame as an I command.
*/
void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_I;
pdu->ctrl_2 = 0;
pdu->ctrl_2 |= (p_bit & LLC_I_PF_BIT_MASK); /* p/f bit */
pdu->ctrl_1 |= (ns << 1) & 0xFE; /* set N(S) in bits 2..8 */
pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
}
/**
* llc_pdu_init_as_rej_cmd - builds REJ PDU
* @skb: Address of the skb to build
* @p_bit: The P bit to set in the PDU
* @nr: The seq. number of the expected I PDU from the remote
*
* Builds a pdu frame as a REJ command.
*/
void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_CMD_REJ;
pdu->ctrl_2 = 0;
pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
}
/**
* llc_pdu_init_as_rnr_cmd - builds RNR pdu
* @skb: Address of the skb to build
* @p_bit: The P bit to set in the PDU
* @nr: The seq. number of the expected I PDU from the remote
*
* Builds a pdu frame as an RNR command.
*/
void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_CMD_RNR;
pdu->ctrl_2 = 0;
pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
}
/**
* llc_pdu_init_as_rr_cmd - Builds RR pdu
* @skb: Address of the skb to build
* @p_bit: The P bit to set in the PDU
* @nr: The seq. number of the expected I PDU from the remote
*
* Builds a pdu frame as an RR command.
*/
void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_CMD_RR;
pdu->ctrl_2 = p_bit & LLC_S_PF_BIT_MASK;
pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
}
/**
* llc_pdu_init_as_sabme_cmd - builds SABME pdu
* @skb: Address of the skb to build
* @p_bit: The P bit to set in the PDU
*
* Builds a pdu frame as an SABME command.
*/
void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
{
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_CMD_SABME;
pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
}
/**
* llc_pdu_init_as_dm_rsp - builds DM response pdu
* @skb: Address of the skb to build
* @f_bit: The F bit to set in the PDU
*
* Builds a pdu frame as a DM response.
*/
void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit)
{
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_RSP_DM;
pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
}
/**
* llc_pdu_init_as_frmr_rsp - builds FRMR response PDU
* @skb: Address of the frame to build
* @prev_pdu: The rejected PDU frame
* @f_bit: The F bit to set in the PDU
* @vs: tx state vari value for the data link conn at the rejecting LLC
* @vr: rx state var value for the data link conn at the rejecting LLC
* @vzyxw: completely described in the IEEE Std 802.2 document (Pg 55)
*
* Builds a pdu frame as a FRMR response.
*/
void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
u8 f_bit, u8 vs, u8 vr, u8 vzyxw)
{
struct llc_frmr_info *frmr_info;
u8 prev_pf = 0;
u8 *ctrl;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_RSP_FRMR;
pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
frmr_info = (struct llc_frmr_info *)&pdu->ctrl_2;
ctrl = (u8 *)&prev_pdu->ctrl_1;
FRMR_INFO_SET_REJ_CNTRL(frmr_info,ctrl);
FRMR_INFO_SET_Vs(frmr_info, vs);
FRMR_INFO_SET_Vr(frmr_info, vr);
prev_pf = llc_pdu_get_pf_bit(prev_pdu);
FRMR_INFO_SET_C_R_BIT(frmr_info, prev_pf);
FRMR_INFO_SET_INVALID_PDU_CTRL_IND(frmr_info, vzyxw);
FRMR_INFO_SET_INVALID_PDU_INFO_IND(frmr_info, vzyxw);
FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw);
FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw);
FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw);
skb_put(skb, sizeof(struct llc_frmr_info));
}
/**
* llc_pdu_init_as_rr_rsp - builds RR response pdu
* @skb: Address of the skb to build
* @f_bit: The F bit to set in the PDU
* @nr: The seq. number of the expected data PDU from the remote
*
* Builds a pdu frame as an RR response.
*/
void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_RSP_RR;
pdu->ctrl_2 = 0;
pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
}
/**
* llc_pdu_init_as_rej_rsp - builds REJ response pdu
* @skb: Address of the skb to build
* @f_bit: The F bit to set in the PDU
* @nr: The seq. number of the expected data PDU from the remote
*
* Builds a pdu frame as a REJ response.
*/
void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_RSP_REJ;
pdu->ctrl_2 = 0;
pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
}
/**
* llc_pdu_init_as_rnr_rsp - builds RNR response pdu
* @skb: Address of the frame to build
* @f_bit: The F bit to set in the PDU
* @nr: The seq. number of the expected data PDU from the remote
*
* Builds a pdu frame as an RNR response.
*/
void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
{
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_S;
pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR;
pdu->ctrl_2 = 0;
pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
}
/**
* llc_pdu_init_as_ua_rsp - builds UA response pdu
* @skb: Address of the frame to build
* @f_bit: The F bit to set in the PDU
*
* Builds a pdu frame as a UA response.
*/
void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
{
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
pdu->ctrl_1 = LLC_PDU_TYPE_U;
pdu->ctrl_1 |= LLC_2_PDU_RSP_UA;
pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
}
/**
* llc_pdu_decode_pdu_type - designates PDU type
* @skb: input skb that type of it must be designated.
* @type: type of PDU (output argument).
*
* This function designates type of PDU (I, S or U).
*/
static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type)
{
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
if (pdu->ctrl_1 & 1) {
if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
*type = LLC_PDU_TYPE_U;
else
*type = LLC_PDU_TYPE_S;
} else
*type = LLC_PDU_TYPE_I;
}
/**
* llc_pdu_get_pf_bit - extracts p/f bit of input PDU
* @pdu: pointer to LLC header.
*
* This function extracts p/f bit of input PDU. at first examines type of
* PDU and then extracts p/f bit. Returns the p/f bit.
*/
static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu)
{
u8 pdu_type;
u8 pf_bit = 0;
if (pdu->ctrl_1 & 1) {
if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
pdu_type = LLC_PDU_TYPE_U;
else
pdu_type = LLC_PDU_TYPE_S;
} else
pdu_type = LLC_PDU_TYPE_I;
switch (pdu_type) {
case LLC_PDU_TYPE_I:
case LLC_PDU_TYPE_S:
pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
break;
case LLC_PDU_TYPE_U:
pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
break;
}
return pf_bit;
}

View File

@ -1,245 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* proc_llc.c - proc interface for LLC
*
* Copyright (c) 2001 by Jay Schulist <jschlst@samba.org>
* 2002-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/errno.h>
#include <linux/seq_file.h>
#include <linux/export.h>
#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/llc.h>
#include <net/llc_c_ac.h>
#include <net/llc_c_ev.h>
#include <net/llc_c_st.h>
#include <net/llc_conn.h>
static void llc_ui_format_mac(struct seq_file *seq, const u8 *addr)
{
seq_printf(seq, "%pM", addr);
}
static struct sock *llc_get_sk_idx(loff_t pos)
{
struct llc_sap *sap;
struct sock *sk = NULL;
int i;
list_for_each_entry_rcu(sap, &llc_sap_list, node) {
spin_lock_bh(&sap->sk_lock);
for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++) {
struct hlist_nulls_head *head = &sap->sk_laddr_hash[i];
struct hlist_nulls_node *node;
sk_nulls_for_each(sk, node, head) {
if (!pos)
goto found; /* keep the lock */
--pos;
}
}
spin_unlock_bh(&sap->sk_lock);
}
sk = NULL;
found:
return sk;
}
static void *llc_seq_start(struct seq_file *seq, loff_t *pos) __acquires(RCU)
{
loff_t l = *pos;
rcu_read_lock_bh();
return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN;
}
static struct sock *laddr_hash_next(struct llc_sap *sap, int bucket)
{
struct hlist_nulls_node *node;
struct sock *sk = NULL;
while (++bucket < LLC_SK_LADDR_HASH_ENTRIES)
sk_nulls_for_each(sk, node, &sap->sk_laddr_hash[bucket])
goto out;
out:
return sk;
}
static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct sock* sk, *next;
struct llc_sock *llc;
struct llc_sap *sap;
++*pos;
if (v == SEQ_START_TOKEN) {
sk = llc_get_sk_idx(0);
goto out;
}
sk = v;
next = sk_nulls_next(sk);
if (next) {
sk = next;
goto out;
}
llc = llc_sk(sk);
sap = llc->sap;
sk = laddr_hash_next(sap, llc_sk_laddr_hashfn(sap, &llc->laddr));
if (sk)
goto out;
spin_unlock_bh(&sap->sk_lock);
list_for_each_entry_continue_rcu(sap, &llc_sap_list, node) {
spin_lock_bh(&sap->sk_lock);
sk = laddr_hash_next(sap, -1);
if (sk)
break; /* keep the lock */
spin_unlock_bh(&sap->sk_lock);
}
out:
return sk;
}
static void llc_seq_stop(struct seq_file *seq, void *v)
{
if (v && v != SEQ_START_TOKEN) {
struct sock *sk = v;
struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
spin_unlock_bh(&sap->sk_lock);
}
rcu_read_unlock_bh();
}
static int llc_seq_socket_show(struct seq_file *seq, void *v)
{
struct sock* sk;
struct llc_sock *llc;
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "SKt Mc local_mac_sap remote_mac_sap "
" tx_queue rx_queue st uid link\n");
goto out;
}
sk = v;
llc = llc_sk(sk);
/* FIXME: check if the address is multicast */
seq_printf(seq, "%2X %2X ", sk->sk_type, 0);
if (llc->dev)
llc_ui_format_mac(seq, llc->dev->dev_addr);
else {
u8 addr[6] = {0,0,0,0,0,0};
llc_ui_format_mac(seq, addr);
}
seq_printf(seq, "@%02X ", llc->sap->laddr.lsap);
llc_ui_format_mac(seq, llc->daddr.mac);
seq_printf(seq, "@%02X %8d %8d %2d %3u %4d\n", llc->daddr.lsap,
sk_wmem_alloc_get(sk),
sk_rmem_alloc_get(sk) - llc->copied_seq,
sk->sk_state,
from_kuid_munged(seq_user_ns(seq), sk_uid(sk)),
llc->link);
out:
return 0;
}
static const char *const llc_conn_state_names[] = {
[LLC_CONN_STATE_ADM] = "adm",
[LLC_CONN_STATE_SETUP] = "setup",
[LLC_CONN_STATE_NORMAL] = "normal",
[LLC_CONN_STATE_BUSY] = "busy",
[LLC_CONN_STATE_REJ] = "rej",
[LLC_CONN_STATE_AWAIT] = "await",
[LLC_CONN_STATE_AWAIT_BUSY] = "await_busy",
[LLC_CONN_STATE_AWAIT_REJ] = "await_rej",
[LLC_CONN_STATE_D_CONN] = "d_conn",
[LLC_CONN_STATE_RESET] = "reset",
[LLC_CONN_STATE_ERROR] = "error",
[LLC_CONN_STATE_TEMP] = "temp",
};
static int llc_seq_core_show(struct seq_file *seq, void *v)
{
struct sock* sk;
struct llc_sock *llc;
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "Connection list:\n"
"dsap state retr txw rxw pf ff sf df rs cs "
"tack tpfc trs tbs blog busr\n");
goto out;
}
sk = v;
llc = llc_sk(sk);
seq_printf(seq, " %02X %-10s %3d %3d %3d %2d %2d %2d %2d %2d %2d "
"%4d %4d %3d %3d %4d %4d\n",
llc->daddr.lsap, llc_conn_state_names[llc->state],
llc->retry_count, llc->k, llc->rw, llc->p_flag, llc->f_flag,
llc->s_flag, llc->data_flag, llc->remote_busy_flag,
llc->cause_flag, timer_pending(&llc->ack_timer.timer),
timer_pending(&llc->pf_cycle_timer.timer),
timer_pending(&llc->rej_sent_timer.timer),
timer_pending(&llc->busy_state_timer.timer),
!!sk->sk_backlog.tail, sock_owned_by_user_nocheck(sk));
out:
return 0;
}
static const struct seq_operations llc_seq_socket_ops = {
.start = llc_seq_start,
.next = llc_seq_next,
.stop = llc_seq_stop,
.show = llc_seq_socket_show,
};
static const struct seq_operations llc_seq_core_ops = {
.start = llc_seq_start,
.next = llc_seq_next,
.stop = llc_seq_stop,
.show = llc_seq_core_show,
};
static struct proc_dir_entry *llc_proc_dir;
int __init llc_proc_init(void)
{
int rc = -ENOMEM;
struct proc_dir_entry *p;
llc_proc_dir = proc_mkdir("llc", init_net.proc_net);
if (!llc_proc_dir)
goto out;
p = proc_create_seq("socket", 0444, llc_proc_dir, &llc_seq_socket_ops);
if (!p)
goto out_socket;
p = proc_create_seq("core", 0444, llc_proc_dir, &llc_seq_core_ops);
if (!p)
goto out_core;
rc = 0;
out:
return rc;
out_core:
remove_proc_entry("socket", llc_proc_dir);
out_socket:
remove_proc_entry("llc", init_net.proc_net);
goto out;
}
void llc_proc_exit(void)
{
remove_proc_entry("socket", llc_proc_dir);
remove_proc_entry("core", llc_proc_dir);
remove_proc_entry("llc", init_net.proc_net);
}

View File

@ -1,220 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* llc_s_ac.c - actions performed during sap state transition.
*
* Description :
* Functions in this module are implementation of sap component actions.
* Details of actions can be found in IEEE-802.2 standard document.
* All functions have one sap and one event as input argument. All of
* them return 0 On success and 1 otherwise.
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/netdevice.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
#include <net/llc_s_ac.h>
#include <net/llc_s_ev.h>
#include <net/llc_sap.h>
#include <net/sock.h>
/**
* llc_sap_action_unitdata_ind - forward UI PDU to network layer
* @sap: SAP
* @skb: the event to forward
*
* Received a UI PDU from MAC layer; forward to network layer as a
* UNITDATA INDICATION; verify our event is the kind we expect
*/
int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb)
{
llc_sap_rtn_pdu(sap, skb);
return 0;
}
static int llc_prepare_and_xmit(struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct sk_buff *nskb;
int rc;
rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
if (rc)
return rc;
nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb)
return -ENOMEM;
if (skb->sk)
skb_set_owner_w(nskb, skb->sk);
return dev_queue_xmit(nskb);
}
/**
* llc_sap_action_send_ui - sends UI PDU resp to UNITDATA REQ to MAC layer
* @sap: SAP
* @skb: the event to send
*
* Sends a UI PDU to the MAC layer in response to a UNITDATA REQUEST
* primitive from the network layer. Verifies event is a primitive type of
* event. Verify the primitive is a UNITDATA REQUEST.
*/
int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb);
return llc_prepare_and_xmit(skb);
}
/**
* llc_sap_action_send_xid_c - send XID PDU as response to XID REQ
* @sap: SAP
* @skb: the event to send
*
* Send a XID command PDU to MAC layer in response to a XID REQUEST
* primitive from the network layer. Verify event is a primitive type
* event. Verify the primitive is a XID REQUEST.
*/
int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
llc_pdu_header_init(skb, LLC_PDU_TYPE_U_XID, ev->saddr.lsap,
ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
return llc_prepare_and_xmit(skb);
}
/**
* llc_sap_action_send_xid_r - send XID PDU resp to MAC for received XID
* @sap: SAP
* @skb: the event to send
*
* Send XID response PDU to MAC in response to an earlier received XID
* command PDU. Verify event is a PDU type event
*/
int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
{
u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
int rc = 1;
struct sk_buff *nskb;
llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_da(skb, mac_sa);
llc_pdu_decode_ssap(skb, &dsap);
nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U,
sizeof(struct llc_xid_info));
if (!nskb)
goto out;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
if (likely(!rc))
rc = dev_queue_xmit(nskb);
else
kfree_skb(nskb);
out:
return rc;
}
/**
* llc_sap_action_send_test_c - send TEST PDU to MAC in resp to TEST REQ
* @sap: SAP
* @skb: the event to send
*
* Send a TEST command PDU to the MAC layer in response to a TEST REQUEST
* primitive from the network layer. Verify event is a primitive type
* event; verify the primitive is a TEST REQUEST.
*/
int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
ev->daddr.lsap, LLC_PDU_CMD);
llc_pdu_init_as_test_cmd(skb);
return llc_prepare_and_xmit(skb);
}
int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
{
u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
struct sk_buff *nskb;
int rc = 1;
u32 data_size;
if (skb->mac_len < ETH_HLEN)
return 1;
llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_da(skb, mac_sa);
llc_pdu_decode_ssap(skb, &dsap);
/* The test request command is type U (llc_len = 3) */
data_size = ntohs(eth_hdr(skb)->h_proto) - 3;
nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size);
if (!nskb)
goto out;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb);
rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
if (likely(!rc))
rc = dev_queue_xmit(nskb);
else
kfree_skb(nskb);
out:
return rc;
}
/**
* llc_sap_action_report_status - report data link status to layer mgmt
* @sap: SAP
* @skb: the event to send
*
* Report data link status to layer management. Verify our event is the
* kind we expect.
*/
int llc_sap_action_report_status(struct llc_sap *sap, struct sk_buff *skb)
{
return 0;
}
/**
* llc_sap_action_xid_ind - send XID PDU resp to net layer via XID IND
* @sap: SAP
* @skb: the event to send
*
* Send a XID response PDU to the network layer via a XID INDICATION
* primitive.
*/
int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb)
{
llc_sap_rtn_pdu(sap, skb);
return 0;
}
/**
* llc_sap_action_test_ind - send TEST PDU to net layer via TEST IND
* @sap: SAP
* @skb: the event to send
*
* Send a TEST response PDU to the network layer via a TEST INDICATION
* primitive. Verify our event is a PDU type event.
*/
int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb)
{
llc_sap_rtn_pdu(sap, skb);
return 0;
}

View File

@ -1,109 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* llc_s_ev.c - Defines SAP component events
*
* The followed event functions are SAP component events which are described
* in 802.2 LLC protocol standard document.
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/socket.h>
#include <net/sock.h>
#include <net/llc_if.h>
#include <net/llc_s_ev.h>
#include <net/llc_pdu.h>
int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
ev->prim_type == LLC_SAP_EV_ACTIVATION_REQ ? 0 : 1;
}
int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && LLC_PDU_IS_CMD(pdu) &&
LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_UI ? 0 : 1;
}
int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->prim == LLC_DATAUNIT_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
}
int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->prim == LLC_XID_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
}
int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && LLC_PDU_IS_CMD(pdu) &&
LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1;
}
int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && LLC_PDU_IS_RSP(pdu) &&
LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1;
}
int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->prim == LLC_TEST_PRIM &&
ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
}
int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && LLC_PDU_IS_CMD(pdu) &&
LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1;
}
int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && LLC_PDU_IS_RSP(pdu) &&
LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1;
}
int llc_sap_ev_deactivation_req(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
ev->prim_type == LLC_SAP_EV_DEACTIVATION_REQ ? 0 : 1;
}

View File

@ -1,177 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* llc_s_st.c - Defines SAP component state machine transitions.
*
* The followed transitions are SAP component state machine transitions
* which are described in 802.2 LLC protocol standard document.
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/types.h>
#include <net/llc_if.h>
#include <net/llc_s_ev.h>
#include <net/llc_s_ac.h>
#include <net/llc_s_st.h>
/* dummy last-transition indicator; common to all state transition groups
* last entry for this state
* all members are zeros, .bss zeroes it
*/
static const struct llc_sap_state_trans llc_sap_state_trans_end;
/* state LLC_SAP_STATE_INACTIVE transition for
* LLC_SAP_EV_ACTIVATION_REQ event
*/
static const llc_sap_action_t llc_sap_inactive_state_actions_1[] = {
[0] = llc_sap_action_report_status,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_inactive_state_trans_1 = {
.ev = llc_sap_ev_activation_req,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_inactive_state_actions_1,
};
/* array of pointers; one to each transition */
static const struct llc_sap_state_trans *llc_sap_inactive_state_transitions[] = {
[0] = &llc_sap_inactive_state_trans_1,
[1] = &llc_sap_state_trans_end,
};
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_UI event */
static const llc_sap_action_t llc_sap_active_state_actions_1[] = {
[0] = llc_sap_action_unitdata_ind,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_1 = {
.ev = llc_sap_ev_rx_ui,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_active_state_actions_1,
};
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_UNITDATA_REQ event */
static const llc_sap_action_t llc_sap_active_state_actions_2[] = {
[0] = llc_sap_action_send_ui,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_2 = {
.ev = llc_sap_ev_unitdata_req,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_active_state_actions_2,
};
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_XID_REQ event */
static const llc_sap_action_t llc_sap_active_state_actions_3[] = {
[0] = llc_sap_action_send_xid_c,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_3 = {
.ev = llc_sap_ev_xid_req,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_active_state_actions_3,
};
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_XID_C event */
static const llc_sap_action_t llc_sap_active_state_actions_4[] = {
[0] = llc_sap_action_send_xid_r,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_4 = {
.ev = llc_sap_ev_rx_xid_c,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_active_state_actions_4,
};
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_XID_R event */
static const llc_sap_action_t llc_sap_active_state_actions_5[] = {
[0] = llc_sap_action_xid_ind,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_5 = {
.ev = llc_sap_ev_rx_xid_r,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_active_state_actions_5,
};
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_TEST_REQ event */
static const llc_sap_action_t llc_sap_active_state_actions_6[] = {
[0] = llc_sap_action_send_test_c,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_6 = {
.ev = llc_sap_ev_test_req,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_active_state_actions_6,
};
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_TEST_C event */
static const llc_sap_action_t llc_sap_active_state_actions_7[] = {
[0] = llc_sap_action_send_test_r,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_7 = {
.ev = llc_sap_ev_rx_test_c,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_active_state_actions_7
};
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_TEST_R event */
static const llc_sap_action_t llc_sap_active_state_actions_8[] = {
[0] = llc_sap_action_test_ind,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_8 = {
.ev = llc_sap_ev_rx_test_r,
.next_state = LLC_SAP_STATE_ACTIVE,
.ev_actions = llc_sap_active_state_actions_8,
};
/* state LLC_SAP_STATE_ACTIVE transition for
* LLC_SAP_EV_DEACTIVATION_REQ event
*/
static const llc_sap_action_t llc_sap_active_state_actions_9[] = {
[0] = llc_sap_action_report_status,
[1] = NULL,
};
static const struct llc_sap_state_trans llc_sap_active_state_trans_9 = {
.ev = llc_sap_ev_deactivation_req,
.next_state = LLC_SAP_STATE_INACTIVE,
.ev_actions = llc_sap_active_state_actions_9
};
/* array of pointers; one to each transition */
static const struct llc_sap_state_trans *llc_sap_active_state_transitions[] = {
[0] = &llc_sap_active_state_trans_2,
[1] = &llc_sap_active_state_trans_1,
[2] = &llc_sap_active_state_trans_3,
[3] = &llc_sap_active_state_trans_4,
[4] = &llc_sap_active_state_trans_5,
[5] = &llc_sap_active_state_trans_6,
[6] = &llc_sap_active_state_trans_7,
[7] = &llc_sap_active_state_trans_8,
[8] = &llc_sap_active_state_trans_9,
[9] = &llc_sap_state_trans_end,
};
/* SAP state transition table */
struct llc_sap_state llc_sap_state_table[LLC_NR_SAP_STATES] = {
[LLC_SAP_STATE_INACTIVE - 1] = {
.curr_state = LLC_SAP_STATE_INACTIVE,
.transitions = llc_sap_inactive_state_transitions,
},
[LLC_SAP_STATE_ACTIVE - 1] = {
.curr_state = LLC_SAP_STATE_ACTIVE,
.transitions = llc_sap_active_state_transitions,
},
};

View File

@ -1,437 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* llc_sap.c - driver routines for SAP component.
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <net/llc.h>
#include <net/llc_if.h>
#include <net/llc_conn.h>
#include <net/llc_pdu.h>
#include <net/llc_sap.h>
#include <net/llc_s_ac.h>
#include <net/llc_s_ev.h>
#include <net/llc_s_st.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <linux/llc.h>
#include <linux/slab.h>
static int llc_mac_header_len(struct net_device *dev)
{
switch (dev->type) {
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK:
return LL_RESERVED_SPACE(dev);
}
return 0;
}
/**
* llc_alloc_frame - allocates sk_buff for frame
* @sk: socket to allocate frame to
* @dev: network device this skb will be sent over
* @type: pdu type to allocate
* @data_size: data size to allocate
*
* Allocates an sk_buff for frame and initializes sk_buff fields.
* Returns allocated skb or %NULL when out of memory.
*/
struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
u8 type, u32 data_size)
{
int hlen = type == LLC_PDU_TYPE_U ? 3 : 4;
struct sk_buff *skb;
hlen += llc_mac_header_len(dev);
skb = alloc_skb(hlen + data_size, GFP_ATOMIC);
if (skb) {
skb_reset_mac_header(skb);
skb_reserve(skb, hlen);
skb_reset_network_header(skb);
skb_reset_transport_header(skb);
skb->protocol = htons(ETH_P_802_2);
skb->dev = dev;
if (sk != NULL)
skb_set_owner_w(skb, sk);
}
return skb;
}
void llc_save_primitive(struct sock *sk, struct sk_buff *skb, u8 prim)
{
struct sockaddr_llc *addr;
/* save primitive for use by the user. */
addr = llc_ui_skb_cb(skb);
memset(addr, 0, sizeof(*addr));
addr->sllc_family = sk->sk_family;
addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = prim == LLC_TEST_PRIM;
addr->sllc_xid = prim == LLC_XID_PRIM;
addr->sllc_ua = prim == LLC_DATAUNIT_PRIM;
llc_pdu_decode_sa(skb, addr->sllc_mac);
llc_pdu_decode_ssap(skb, &addr->sllc_sap);
}
/**
* llc_sap_rtn_pdu - Informs upper layer on rx of an UI, XID or TEST pdu.
* @sap: pointer to SAP
* @skb: received pdu
*/
void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
switch (LLC_U_PDU_RSP(pdu)) {
case LLC_1_PDU_CMD_TEST:
ev->prim = LLC_TEST_PRIM; break;
case LLC_1_PDU_CMD_XID:
ev->prim = LLC_XID_PRIM; break;
case LLC_1_PDU_CMD_UI:
ev->prim = LLC_DATAUNIT_PRIM; break;
}
ev->ind_cfm_flag = LLC_IND;
}
/**
* llc_find_sap_trans - finds transition for event
* @sap: pointer to SAP
* @skb: happened event
*
* This function finds transition that matches with happened event.
* Returns the pointer to found transition on success or %NULL for
* failure.
*/
static const struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
struct sk_buff *skb)
{
int i = 0;
const struct llc_sap_state_trans *rc = NULL;
const struct llc_sap_state_trans **next_trans;
struct llc_sap_state *curr_state = &llc_sap_state_table[sap->state - 1];
/*
* Search thru events for this state until list exhausted or until
* its obvious the event is not valid for the current state
*/
for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
if (!next_trans[i]->ev(sap, skb)) {
rc = next_trans[i]; /* got event match; return it */
break;
}
return rc;
}
/**
* llc_exec_sap_trans_actions - execute actions related to event
* @sap: pointer to SAP
* @trans: pointer to transition that it's actions must be performed
* @skb: happened event.
*
* This function executes actions that is related to happened event.
* Returns 0 for success and 1 for failure of at least one action.
*/
static int llc_exec_sap_trans_actions(struct llc_sap *sap,
const struct llc_sap_state_trans *trans,
struct sk_buff *skb)
{
int rc = 0;
const llc_sap_action_t *next_action = trans->ev_actions;
for (; next_action && *next_action; next_action++)
if ((*next_action)(sap, skb))
rc = 1;
return rc;
}
/**
* llc_sap_next_state - finds transition, execs actions & change SAP state
* @sap: pointer to SAP
* @skb: happened event
*
* This function finds transition that matches with happened event, then
* executes related actions and finally changes state of SAP. It returns
* 0 on success and 1 for failure.
*/
static int llc_sap_next_state(struct llc_sap *sap, struct sk_buff *skb)
{
const struct llc_sap_state_trans *trans;
int rc = 1;
if (sap->state > LLC_NR_SAP_STATES)
goto out;
trans = llc_find_sap_trans(sap, skb);
if (!trans)
goto out;
/*
* Got the state to which we next transition; perform the actions
* associated with this transition before actually transitioning to the
* next state
*/
rc = llc_exec_sap_trans_actions(sap, trans, skb);
if (rc)
goto out;
/*
* Transition SAP to next state if all actions execute successfully
*/
sap->state = trans->next_state;
out:
return rc;
}
/**
* llc_sap_state_process - sends event to SAP state machine
* @sap: sap to use
* @skb: pointer to occurred event
*
* After executing actions of the event, upper layer will be indicated
* if needed(on receiving an UI frame). sk can be null for the
* datalink_proto case.
*
* This function always consumes a reference to the skb.
*/
static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->ind_cfm_flag = 0;
llc_sap_next_state(sap, skb);
if (ev->ind_cfm_flag == LLC_IND && skb->sk->sk_state != TCP_LISTEN) {
llc_save_primitive(skb->sk, skb, ev->prim);
/* queue skb to the user. */
if (sock_queue_rcv_skb(skb->sk, skb) == 0)
return;
}
kfree_skb(skb);
}
/**
* llc_build_and_send_test_pkt - TEST interface for upper layers.
* @sap: sap to use
* @skb: packet to send
* @dmac: destination mac address
* @dsap: destination sap
*
* This function is called when upper layer wants to send a TEST pdu.
* Returns 0 for success, 1 otherwise.
*/
void llc_build_and_send_test_pkt(struct llc_sap *sap,
struct sk_buff *skb, u8 *dmac, u8 dsap)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->saddr.lsap = sap->laddr.lsap;
ev->daddr.lsap = dsap;
memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->prim = LLC_TEST_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ;
llc_sap_state_process(sap, skb);
}
/**
* llc_build_and_send_xid_pkt - XID interface for upper layers
* @sap: sap to use
* @skb: packet to send
* @dmac: destination mac address
* @dsap: destination sap
*
* This function is called when upper layer wants to send a XID pdu.
* Returns 0 for success, 1 otherwise.
*/
void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->saddr.lsap = sap->laddr.lsap;
ev->daddr.lsap = dsap;
memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->prim = LLC_XID_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ;
llc_sap_state_process(sap, skb);
}
/**
* llc_sap_rcv - sends received pdus to the sap state machine
* @sap: current sap component structure.
* @skb: received frame.
* @sk: socket to associate to frame
*
* Sends received pdus to the sap state machine.
*/
static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb,
struct sock *sk)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->type = LLC_SAP_EV_TYPE_PDU;
ev->reason = 0;
skb_orphan(skb);
sock_hold(sk);
skb->sk = sk;
skb->destructor = sock_efree;
llc_sap_state_process(sap, skb);
}
static inline bool llc_dgram_match(const struct llc_sap *sap,
const struct llc_addr *laddr,
const struct sock *sk,
const struct net *net)
{
struct llc_sock *llc = llc_sk(sk);
return sk->sk_type == SOCK_DGRAM &&
net_eq(sock_net(sk), net) &&
llc->laddr.lsap == laddr->lsap &&
ether_addr_equal(llc->laddr.mac, laddr->mac);
}
/**
* llc_lookup_dgram - Finds dgram socket for the local sap/mac
* @sap: SAP
* @laddr: address of local LLC (MAC + SAP)
* @net: netns to look up a socket in
*
* Search socket list of the SAP and finds connection using the local
* mac, and local sap. Returns pointer for socket found, %NULL otherwise.
*/
static struct sock *llc_lookup_dgram(struct llc_sap *sap,
const struct llc_addr *laddr,
const struct net *net)
{
struct sock *rc;
struct hlist_nulls_node *node;
int slot = llc_sk_laddr_hashfn(sap, laddr);
struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot];
rcu_read_lock_bh();
again:
sk_nulls_for_each_rcu(rc, node, laddr_hb) {
if (llc_dgram_match(sap, laddr, rc, net)) {
/* Extra checks required by SLAB_TYPESAFE_BY_RCU */
if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
goto again;
if (unlikely(llc_sk(rc)->sap != sap ||
!llc_dgram_match(sap, laddr, rc, net))) {
sock_put(rc);
continue;
}
goto found;
}
}
rc = NULL;
/*
* if the nulls value we got at the end of this lookup is
* not the expected one, we must restart lookup.
* We probably met an item that was moved to another chain.
*/
if (unlikely(get_nulls_value(node) != slot))
goto again;
found:
rcu_read_unlock_bh();
return rc;
}
static inline bool llc_mcast_match(const struct llc_sap *sap,
const struct llc_addr *laddr,
const struct sk_buff *skb,
const struct sock *sk)
{
struct llc_sock *llc = llc_sk(sk);
return sk->sk_type == SOCK_DGRAM &&
llc->laddr.lsap == laddr->lsap &&
llc->dev == skb->dev;
}
static void llc_do_mcast(struct llc_sap *sap, struct sk_buff *skb,
struct sock **stack, int count)
{
struct sk_buff *skb1;
int i;
for (i = 0; i < count; i++) {
skb1 = skb_clone(skb, GFP_ATOMIC);
if (!skb1) {
sock_put(stack[i]);
continue;
}
llc_sap_rcv(sap, skb1, stack[i]);
sock_put(stack[i]);
}
}
/**
* llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets.
* @sap: SAP
* @laddr: address of local LLC (MAC + SAP)
* @skb: PDU to deliver
*
* Search socket list of the SAP and finds connections with same sap.
* Deliver clone to each.
*/
static void llc_sap_mcast(struct llc_sap *sap,
const struct llc_addr *laddr,
struct sk_buff *skb)
{
int i = 0;
struct sock *sk;
struct sock *stack[256 / sizeof(struct sock *)];
struct llc_sock *llc;
struct hlist_head *dev_hb = llc_sk_dev_hash(sap, skb->dev->ifindex);
spin_lock_bh(&sap->sk_lock);
hlist_for_each_entry(llc, dev_hb, dev_hash_node) {
sk = &llc->sk;
if (!llc_mcast_match(sap, laddr, skb, sk))
continue;
sock_hold(sk);
if (i < ARRAY_SIZE(stack))
stack[i++] = sk;
else {
llc_do_mcast(sap, skb, stack, i);
i = 0;
}
}
spin_unlock_bh(&sap->sk_lock);
llc_do_mcast(sap, skb, stack, i);
}
void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_addr laddr;
llc_pdu_decode_da(skb, laddr.mac);
llc_pdu_decode_dsap(skb, &laddr.lsap);
if (is_multicast_ether_addr(laddr.mac)) {
llc_sap_mcast(sap, &laddr, skb);
kfree_skb(skb);
} else {
struct sock *sk = llc_lookup_dgram(sap, &laddr, dev_net(skb->dev));
if (sk) {
llc_sap_rcv(sap, skb, sk);
sock_put(sk);
} else
kfree_skb(skb);
}
}

View File

@ -1,120 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* llc_station.c - station component of LLC
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <net/llc.h>
#include <net/llc_sap.h>
#include <net/llc_conn.h>
#include <net/llc_c_ac.h>
#include <net/llc_s_ac.h>
#include <net/llc_c_ev.h>
#include <net/llc_c_st.h>
#include <net/llc_s_ev.h>
#include <net/llc_s_st.h>
#include <net/llc_pdu.h>
static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb)
{
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && /* command PDU */
LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID &&
!pdu->dsap; /* NULL DSAP value */
}
static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb)
{
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return LLC_PDU_IS_CMD(pdu) && /* command PDU */
LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST &&
!pdu->dsap; /* NULL DSAP */
}
static int llc_station_ac_send_xid_r(struct sk_buff *skb)
{
u8 mac_da[ETH_ALEN], dsap;
int rc = 1;
struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U,
sizeof(struct llc_xid_info));
if (!nskb)
goto out;
llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da);
if (unlikely(rc))
goto free;
dev_queue_xmit(nskb);
out:
return rc;
free:
kfree_skb(nskb);
goto out;
}
static int llc_station_ac_send_test_r(struct sk_buff *skb)
{
u8 mac_da[ETH_ALEN], dsap;
int rc = 1;
u32 data_size;
struct sk_buff *nskb;
if (skb->mac_len < ETH_HLEN)
goto out;
/* The test request command is type U (llc_len = 3) */
data_size = ntohs(eth_hdr(skb)->h_proto) - 3;
nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size);
if (!nskb)
goto out;
llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb);
rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da);
if (unlikely(rc))
goto free;
dev_queue_xmit(nskb);
out:
return rc;
free:
kfree_skb(nskb);
goto out;
}
/**
* llc_station_rcv - send received pdu to the station state machine
* @skb: received frame.
*
* Sends data unit to station state machine.
*/
static void llc_station_rcv(struct sk_buff *skb)
{
if (llc_stat_ev_rx_null_dsap_xid_c(skb))
llc_station_ac_send_xid_r(skb);
else if (llc_stat_ev_rx_null_dsap_test_c(skb))
llc_station_ac_send_test_r(skb);
kfree_skb(skb);
}
void __init llc_station_init(void)
{
llc_set_station_handler(llc_station_rcv);
}
void llc_station_exit(void)
{
llc_set_station_handler(NULL);
}

View File

@ -1,71 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* sysctl_net_llc.c: sysctl interface to LLC net subsystem.
*
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/sysctl.h>
#include <net/net_namespace.h>
#include <net/llc.h>
static struct ctl_table llc2_timeout_table[] = {
{
.procname = "ack",
.data = &sysctl_llc2_ack_timeout,
.maxlen = sizeof(sysctl_llc2_ack_timeout),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "busy",
.data = &sysctl_llc2_busy_timeout,
.maxlen = sizeof(sysctl_llc2_busy_timeout),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "p",
.data = &sysctl_llc2_p_timeout,
.maxlen = sizeof(sysctl_llc2_p_timeout),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "rej",
.data = &sysctl_llc2_rej_timeout,
.maxlen = sizeof(sysctl_llc2_rej_timeout),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
};
static struct ctl_table_header *llc2_timeout_header;
static struct ctl_table_header *llc_station_header;
int __init llc_sysctl_init(void)
{
static struct ctl_table empty[1] = {};
llc2_timeout_header = register_net_sysctl(&init_net, "net/llc/llc2/timeout", llc2_timeout_table);
llc_station_header = register_net_sysctl_sz(&init_net, "net/llc/station", empty, 0);
if (!llc2_timeout_header || !llc_station_header) {
llc_sysctl_exit();
return -ENOMEM;
}
return 0;
}
void llc_sysctl_exit(void)
{
if (llc2_timeout_header) {
unregister_net_sysctl_table(llc2_timeout_header);
llc2_timeout_header = NULL;
}
if (llc_station_header) {
unregister_net_sysctl_table(llc_station_header);
llc_station_header = NULL;
}
}