1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
6 #include <linux/errno.h>
7 #include <linux/types.h>
8 #include <linux/socket.h>
10 #include <linux/kernel.h>
11 #include <linux/timer.h>
12 #include <linux/string.h>
13 #include <linux/sockios.h>
14 #include <linux/net.h>
15 #include <linux/slab.h>
17 #include <linux/inet.h>
18 #include <linux/netdevice.h>
19 #include <linux/skbuff.h>
21 #include <net/tcp_states.h>
22 #include <linux/uaccess.h>
23 #include <linux/fcntl.h>
25 #include <linux/interrupt.h>
26 #include <net/netrom.h>
29 * This routine purges all of the queues of frames.
31 void nr_clear_queues(struct sock
*sk
)
33 struct nr_sock
*nr
= nr_sk(sk
);
35 skb_queue_purge(&sk
->sk_write_queue
);
36 skb_queue_purge(&nr
->ack_queue
);
37 skb_queue_purge(&nr
->reseq_queue
);
38 skb_queue_purge(&nr
->frag_queue
);
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
46 void nr_frames_acked(struct sock
*sk
, unsigned short nr
)
48 struct nr_sock
*nrom
= nr_sk(sk
);
52 * Remove all the ack-ed frames from the ack queue.
55 while (skb_peek(&nrom
->ack_queue
) != NULL
&& nrom
->va
!= nr
) {
56 skb
= skb_dequeue(&nrom
->ack_queue
);
58 nrom
->va
= (nrom
->va
+ 1) % NR_MODULUS
;
64 * Requeue all the un-ack-ed frames on the output queue to be picked
65 * up by nr_kick called from the timer. This arrangement handles the
66 * possibility of an empty output queue.
68 void nr_requeue_frames(struct sock
*sk
)
70 struct sk_buff
*skb
, *skb_prev
= NULL
;
72 while ((skb
= skb_dequeue(&nr_sk(sk
)->ack_queue
)) != NULL
) {
74 skb_queue_head(&sk
->sk_write_queue
, skb
);
76 skb_append(skb_prev
, skb
, &sk
->sk_write_queue
);
82 * Validate that the value of nr is between va and vs. Return true or
85 int nr_validate_nr(struct sock
*sk
, unsigned short nr
)
87 struct nr_sock
*nrom
= nr_sk(sk
);
88 unsigned short vc
= nrom
->va
;
90 while (vc
!= nrom
->vs
) {
91 if (nr
== vc
) return 1;
92 vc
= (vc
+ 1) % NR_MODULUS
;
95 return nr
== nrom
->vs
;
99 * Check that ns is within the receive window.
101 int nr_in_rx_window(struct sock
*sk
, unsigned short ns
)
103 struct nr_sock
*nr
= nr_sk(sk
);
104 unsigned short vc
= nr
->vr
;
105 unsigned short vt
= (nr
->vl
+ nr
->window
) % NR_MODULUS
;
108 if (ns
== vc
) return 1;
109 vc
= (vc
+ 1) % NR_MODULUS
;
116 * This routine is called when the HDLC layer internally generates a
119 void nr_write_internal(struct sock
*sk
, int frametype
)
121 struct nr_sock
*nr
= nr_sk(sk
);
126 len
= NR_NETWORK_LEN
+ NR_TRANSPORT_LEN
;
128 switch (frametype
& 0x0F) {
133 len
+= (nr
->bpqext
) ? 2 : 1;
140 printk(KERN_ERR
"NET/ROM: nr_write_internal - invalid frame type %d\n", frametype
);
144 if ((skb
= alloc_skb(len
, GFP_ATOMIC
)) == NULL
)
148 * Space for AX.25 and NET/ROM network header
150 skb_reserve(skb
, NR_NETWORK_LEN
);
152 dptr
= skb_put(skb
, skb_tailroom(skb
));
154 switch (frametype
& 0x0F) {
156 timeout
= nr
->t1
/ HZ
;
157 *dptr
++ = nr
->my_index
;
162 *dptr
++ = nr
->window
;
163 memcpy(dptr
, &nr
->user_addr
, AX25_ADDR_LEN
);
164 dptr
[6] &= ~AX25_CBIT
;
165 dptr
[6] &= ~AX25_EBIT
;
166 dptr
[6] |= AX25_SSSID_SPARE
;
167 dptr
+= AX25_ADDR_LEN
;
168 memcpy(dptr
, &nr
->source_addr
, AX25_ADDR_LEN
);
169 dptr
[6] &= ~AX25_CBIT
;
170 dptr
[6] &= ~AX25_EBIT
;
171 dptr
[6] |= AX25_SSSID_SPARE
;
172 dptr
+= AX25_ADDR_LEN
;
173 *dptr
++ = timeout
% 256;
174 *dptr
++ = timeout
/ 256;
178 *dptr
++ = nr
->your_index
;
179 *dptr
++ = nr
->your_id
;
180 *dptr
++ = nr
->my_index
;
183 *dptr
++ = nr
->window
;
184 if (nr
->bpqext
) *dptr
++ = sysctl_netrom_network_ttl_initialiser
;
189 *dptr
++ = nr
->your_index
;
190 *dptr
++ = nr
->your_id
;
197 *dptr
++ = nr
->your_index
;
198 *dptr
++ = nr
->your_id
;
205 nr_transmit_buffer(sk
, skb
);
209 * This routine is called to send an error reply.
211 void __nr_transmit_reply(struct sk_buff
*skb
, int mine
, unsigned char cmdflags
)
213 struct sk_buff
*skbn
;
217 len
= NR_NETWORK_LEN
+ NR_TRANSPORT_LEN
+ 1;
219 if ((skbn
= alloc_skb(len
, GFP_ATOMIC
)) == NULL
)
222 skb_reserve(skbn
, 0);
224 dptr
= skb_put(skbn
, NR_NETWORK_LEN
+ NR_TRANSPORT_LEN
);
226 skb_copy_from_linear_data_offset(skb
, 7, dptr
, AX25_ADDR_LEN
);
227 dptr
[6] &= ~AX25_CBIT
;
228 dptr
[6] &= ~AX25_EBIT
;
229 dptr
[6] |= AX25_SSSID_SPARE
;
230 dptr
+= AX25_ADDR_LEN
;
232 skb_copy_from_linear_data(skb
, dptr
, AX25_ADDR_LEN
);
233 dptr
[6] &= ~AX25_CBIT
;
234 dptr
[6] |= AX25_EBIT
;
235 dptr
[6] |= AX25_SSSID_SPARE
;
236 dptr
+= AX25_ADDR_LEN
;
238 *dptr
++ = sysctl_netrom_network_ttl_initialiser
;
243 *dptr
++ = skb
->data
[15];
244 *dptr
++ = skb
->data
[16];
246 *dptr
++ = skb
->data
[15];
247 *dptr
++ = skb
->data
[16];
255 if (!nr_route_frame(skbn
, NULL
))
259 void nr_disconnect(struct sock
*sk
, int reason
)
264 nr_stop_idletimer(sk
);
268 nr_sk(sk
)->state
= NR_STATE_0
;
270 sk
->sk_state
= TCP_CLOSE
;
272 sk
->sk_shutdown
|= SEND_SHUTDOWN
;
274 if (!sock_flag(sk
, SOCK_DEAD
)) {
275 sk
->sk_state_change(sk
);
276 sock_set_flag(sk
, SOCK_DEAD
);