Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/ax25/ax25_subr.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
*
4
* Copyright (C) Alan Cox GW4PTS ([email protected])
5
* Copyright (C) Jonathan Naylor G4KLX ([email protected])
6
* Copyright (C) Joerg Reuter DL1BKE ([email protected])
7
* Copyright (C) Frederic Rible F1OAT ([email protected])
8
*/
9
#include <linux/errno.h>
10
#include <linux/types.h>
11
#include <linux/socket.h>
12
#include <linux/in.h>
13
#include <linux/kernel.h>
14
#include <linux/timer.h>
15
#include <linux/string.h>
16
#include <linux/sockios.h>
17
#include <linux/net.h>
18
#include <linux/slab.h>
19
#include <net/ax25.h>
20
#include <linux/inet.h>
21
#include <linux/netdevice.h>
22
#include <linux/skbuff.h>
23
#include <net/sock.h>
24
#include <net/tcp_states.h>
25
#include <linux/uaccess.h>
26
#include <linux/fcntl.h>
27
#include <linux/mm.h>
28
#include <linux/interrupt.h>
29
30
/*
31
* This routine purges all the queues of frames.
32
*/
33
void ax25_clear_queues(ax25_cb *ax25)
34
{
35
skb_queue_purge(&ax25->write_queue);
36
skb_queue_purge(&ax25->ack_queue);
37
skb_queue_purge(&ax25->reseq_queue);
38
skb_queue_purge(&ax25->frag_queue);
39
}
40
41
/*
42
* This routine purges the input queue of those frames that have been
43
* acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
44
* SDL diagram.
45
*/
46
void ax25_frames_acked(ax25_cb *ax25, unsigned short nr)
47
{
48
struct sk_buff *skb;
49
50
/*
51
* Remove all the ack-ed frames from the ack queue.
52
*/
53
if (ax25->va != nr) {
54
while (skb_peek(&ax25->ack_queue) != NULL && ax25->va != nr) {
55
skb = skb_dequeue(&ax25->ack_queue);
56
kfree_skb(skb);
57
ax25->va = (ax25->va + 1) % ax25->modulus;
58
}
59
}
60
}
61
62
void ax25_requeue_frames(ax25_cb *ax25)
63
{
64
struct sk_buff *skb;
65
66
/*
67
* Requeue all the un-ack-ed frames on the output queue to be picked
68
* up by ax25_kick called from the timer. This arrangement handles the
69
* possibility of an empty output queue.
70
*/
71
while ((skb = skb_dequeue_tail(&ax25->ack_queue)) != NULL)
72
skb_queue_head(&ax25->write_queue, skb);
73
}
74
75
/*
76
* Validate that the value of nr is between va and vs. Return true or
77
* false for testing.
78
*/
79
int ax25_validate_nr(ax25_cb *ax25, unsigned short nr)
80
{
81
unsigned short vc = ax25->va;
82
83
while (vc != ax25->vs) {
84
if (nr == vc) return 1;
85
vc = (vc + 1) % ax25->modulus;
86
}
87
88
if (nr == ax25->vs) return 1;
89
90
return 0;
91
}
92
93
/*
94
* This routine is the centralised routine for parsing the control
95
* information for the different frame formats.
96
*/
97
int ax25_decode(ax25_cb *ax25, struct sk_buff *skb, int *ns, int *nr, int *pf)
98
{
99
unsigned char *frame;
100
int frametype = AX25_ILLEGAL;
101
102
frame = skb->data;
103
*ns = *nr = *pf = 0;
104
105
if (ax25->modulus == AX25_MODULUS) {
106
if ((frame[0] & AX25_S) == 0) {
107
frametype = AX25_I; /* I frame - carries NR/NS/PF */
108
*ns = (frame[0] >> 1) & 0x07;
109
*nr = (frame[0] >> 5) & 0x07;
110
*pf = frame[0] & AX25_PF;
111
} else if ((frame[0] & AX25_U) == 1) { /* S frame - take out PF/NR */
112
frametype = frame[0] & 0x0F;
113
*nr = (frame[0] >> 5) & 0x07;
114
*pf = frame[0] & AX25_PF;
115
} else if ((frame[0] & AX25_U) == 3) { /* U frame - take out PF */
116
frametype = frame[0] & ~AX25_PF;
117
*pf = frame[0] & AX25_PF;
118
}
119
skb_pull(skb, 1);
120
} else {
121
if ((frame[0] & AX25_S) == 0) {
122
frametype = AX25_I; /* I frame - carries NR/NS/PF */
123
*ns = (frame[0] >> 1) & 0x7F;
124
*nr = (frame[1] >> 1) & 0x7F;
125
*pf = frame[1] & AX25_EPF;
126
skb_pull(skb, 2);
127
} else if ((frame[0] & AX25_U) == 1) { /* S frame - take out PF/NR */
128
frametype = frame[0] & 0x0F;
129
*nr = (frame[1] >> 1) & 0x7F;
130
*pf = frame[1] & AX25_EPF;
131
skb_pull(skb, 2);
132
} else if ((frame[0] & AX25_U) == 3) { /* U frame - take out PF */
133
frametype = frame[0] & ~AX25_PF;
134
*pf = frame[0] & AX25_PF;
135
skb_pull(skb, 1);
136
}
137
}
138
139
return frametype;
140
}
141
142
/*
143
* This routine is called when the HDLC layer internally generates a
144
* command or response for the remote machine ( eg. RR, UA etc. ).
145
* Only supervisory or unnumbered frames are processed.
146
*/
147
void ax25_send_control(ax25_cb *ax25, int frametype, int poll_bit, int type)
148
{
149
struct sk_buff *skb;
150
unsigned char *dptr;
151
152
if ((skb = alloc_skb(ax25->ax25_dev->dev->hard_header_len + 2, GFP_ATOMIC)) == NULL)
153
return;
154
155
skb_reserve(skb, ax25->ax25_dev->dev->hard_header_len);
156
157
skb_reset_network_header(skb);
158
159
/* Assume a response - address structure for DTE */
160
if (ax25->modulus == AX25_MODULUS) {
161
dptr = skb_put(skb, 1);
162
*dptr = frametype;
163
*dptr |= (poll_bit) ? AX25_PF : 0;
164
if ((frametype & AX25_U) == AX25_S) /* S frames carry NR */
165
*dptr |= (ax25->vr << 5);
166
} else {
167
if ((frametype & AX25_U) == AX25_U) {
168
dptr = skb_put(skb, 1);
169
*dptr = frametype;
170
*dptr |= (poll_bit) ? AX25_PF : 0;
171
} else {
172
dptr = skb_put(skb, 2);
173
dptr[0] = frametype;
174
dptr[1] = (ax25->vr << 1);
175
dptr[1] |= (poll_bit) ? AX25_EPF : 0;
176
}
177
}
178
179
ax25_transmit_buffer(ax25, skb, type);
180
}
181
182
/*
183
* Send a 'DM' to an unknown connection attempt, or an invalid caller.
184
*
185
* Note: src here is the sender, thus it's the target of the DM
186
*/
187
void ax25_return_dm(struct net_device *dev, ax25_address *src, ax25_address *dest, ax25_digi *digi)
188
{
189
struct sk_buff *skb;
190
char *dptr;
191
ax25_digi retdigi;
192
193
if (dev == NULL)
194
return;
195
196
if ((skb = alloc_skb(dev->hard_header_len + 1, GFP_ATOMIC)) == NULL)
197
return; /* Next SABM will get DM'd */
198
199
skb_reserve(skb, dev->hard_header_len);
200
skb_reset_network_header(skb);
201
202
ax25_digi_invert(digi, &retdigi);
203
204
dptr = skb_put(skb, 1);
205
206
*dptr = AX25_DM | AX25_PF;
207
208
/*
209
* Do the address ourselves
210
*/
211
dptr = skb_push(skb, ax25_addr_size(digi));
212
dptr += ax25_addr_build(dptr, dest, src, &retdigi, AX25_RESPONSE, AX25_MODULUS);
213
214
ax25_queue_xmit(skb, dev);
215
}
216
217
/*
218
* Exponential backoff for AX.25
219
*/
220
void ax25_calculate_t1(ax25_cb *ax25)
221
{
222
int n, t = 2;
223
224
switch (ax25->backoff) {
225
case 0:
226
break;
227
228
case 1:
229
t += 2 * ax25->n2count;
230
break;
231
232
case 2:
233
for (n = 0; n < ax25->n2count; n++)
234
t *= 2;
235
if (t > 8) t = 8;
236
break;
237
}
238
239
ax25->t1 = t * ax25->rtt;
240
}
241
242
/*
243
* Calculate the Round Trip Time
244
*/
245
void ax25_calculate_rtt(ax25_cb *ax25)
246
{
247
if (ax25->backoff == 0)
248
return;
249
250
if (ax25_t1timer_running(ax25) && ax25->n2count == 0)
251
ax25->rtt = (9 * ax25->rtt + ax25->t1 - ax25_display_timer(&ax25->t1timer)) / 10;
252
253
if (ax25->rtt < AX25_T1CLAMPLO)
254
ax25->rtt = AX25_T1CLAMPLO;
255
256
if (ax25->rtt > AX25_T1CLAMPHI)
257
ax25->rtt = AX25_T1CLAMPHI;
258
}
259
260
void ax25_disconnect(ax25_cb *ax25, int reason)
261
{
262
ax25_clear_queues(ax25);
263
264
if (reason == ENETUNREACH) {
265
timer_delete_sync(&ax25->timer);
266
timer_delete_sync(&ax25->t1timer);
267
timer_delete_sync(&ax25->t2timer);
268
timer_delete_sync(&ax25->t3timer);
269
timer_delete_sync(&ax25->idletimer);
270
} else {
271
if (ax25->sk && !sock_flag(ax25->sk, SOCK_DESTROY))
272
ax25_stop_heartbeat(ax25);
273
ax25_stop_t1timer(ax25);
274
ax25_stop_t2timer(ax25);
275
ax25_stop_t3timer(ax25);
276
ax25_stop_idletimer(ax25);
277
}
278
279
ax25->state = AX25_STATE_0;
280
281
ax25_link_failed(ax25, reason);
282
283
if (ax25->sk != NULL) {
284
local_bh_disable();
285
bh_lock_sock(ax25->sk);
286
ax25->sk->sk_state = TCP_CLOSE;
287
ax25->sk->sk_err = reason;
288
ax25->sk->sk_shutdown |= SEND_SHUTDOWN;
289
if (!sock_flag(ax25->sk, SOCK_DEAD)) {
290
ax25->sk->sk_state_change(ax25->sk);
291
sock_set_flag(ax25->sk, SOCK_DEAD);
292
}
293
bh_unlock_sock(ax25->sk);
294
local_bh_enable();
295
}
296
}
297
298