Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/llc/llc_station.c
26278 views
1
/*
2
* llc_station.c - station component of LLC
3
*
4
* Copyright (c) 1997 by Procom Technology, Inc.
5
* 2001-2003 by Arnaldo Carvalho de Melo <[email protected]>
6
*
7
* This program can be redistributed or modified under the terms of the
8
* GNU General Public License as published by the Free Software Foundation.
9
* This program is distributed without any warranty or implied warranty
10
* of merchantability or fitness for a particular purpose.
11
*
12
* See the GNU General Public License for more details.
13
*/
14
#include <linux/init.h>
15
#include <linux/module.h>
16
#include <linux/slab.h>
17
#include <net/llc.h>
18
#include <net/llc_sap.h>
19
#include <net/llc_conn.h>
20
#include <net/llc_c_ac.h>
21
#include <net/llc_s_ac.h>
22
#include <net/llc_c_ev.h>
23
#include <net/llc_c_st.h>
24
#include <net/llc_s_ev.h>
25
#include <net/llc_s_st.h>
26
#include <net/llc_pdu.h>
27
28
static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb)
29
{
30
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
31
32
return LLC_PDU_IS_CMD(pdu) && /* command PDU */
33
LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
34
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID &&
35
!pdu->dsap; /* NULL DSAP value */
36
}
37
38
static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb)
39
{
40
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
41
42
return LLC_PDU_IS_CMD(pdu) && /* command PDU */
43
LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
44
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST &&
45
!pdu->dsap; /* NULL DSAP */
46
}
47
48
static int llc_station_ac_send_xid_r(struct sk_buff *skb)
49
{
50
u8 mac_da[ETH_ALEN], dsap;
51
int rc = 1;
52
struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U,
53
sizeof(struct llc_xid_info));
54
55
if (!nskb)
56
goto out;
57
llc_pdu_decode_sa(skb, mac_da);
58
llc_pdu_decode_ssap(skb, &dsap);
59
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
60
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
61
rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da);
62
if (unlikely(rc))
63
goto free;
64
dev_queue_xmit(nskb);
65
out:
66
return rc;
67
free:
68
kfree_skb(nskb);
69
goto out;
70
}
71
72
static int llc_station_ac_send_test_r(struct sk_buff *skb)
73
{
74
u8 mac_da[ETH_ALEN], dsap;
75
int rc = 1;
76
u32 data_size;
77
struct sk_buff *nskb;
78
79
if (skb->mac_len < ETH_HLEN)
80
goto out;
81
82
/* The test request command is type U (llc_len = 3) */
83
data_size = ntohs(eth_hdr(skb)->h_proto) - 3;
84
nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size);
85
86
if (!nskb)
87
goto out;
88
llc_pdu_decode_sa(skb, mac_da);
89
llc_pdu_decode_ssap(skb, &dsap);
90
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
91
llc_pdu_init_as_test_rsp(nskb, skb);
92
rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da);
93
if (unlikely(rc))
94
goto free;
95
dev_queue_xmit(nskb);
96
out:
97
return rc;
98
free:
99
kfree_skb(nskb);
100
goto out;
101
}
102
103
/**
104
* llc_station_rcv - send received pdu to the station state machine
105
* @skb: received frame.
106
*
107
* Sends data unit to station state machine.
108
*/
109
static void llc_station_rcv(struct sk_buff *skb)
110
{
111
if (llc_stat_ev_rx_null_dsap_xid_c(skb))
112
llc_station_ac_send_xid_r(skb);
113
else if (llc_stat_ev_rx_null_dsap_test_c(skb))
114
llc_station_ac_send_test_r(skb);
115
kfree_skb(skb);
116
}
117
118
void __init llc_station_init(void)
119
{
120
llc_set_station_handler(llc_station_rcv);
121
}
122
123
void llc_station_exit(void)
124
{
125
llc_set_station_handler(NULL);
126
}
127
128