2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
9 #include <linux/errno.h>
10 #include <linux/types.h>
11 #include <linux/socket.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>
19 #include <linux/inet.h>
20 #include <linux/netdevice.h>
21 #include <linux/skbuff.h>
23 #include <net/tcp_states.h>
24 #include <asm/uaccess.h>
25 #include <asm/system.h>
26 #include <linux/fcntl.h>
28 #include <linux/interrupt.h>
29 #include <net/netrom.h>
32 * This routine purges all of the queues of frames.
34 void nr_clear_queues(struct sock
*sk
)
36 struct nr_sock
*nr
= nr_sk(sk
);
38 skb_queue_purge(&sk
->sk_write_queue
);
39 skb_queue_purge(&nr
->ack_queue
);
40 skb_queue_purge(&nr
->reseq_queue
);
41 skb_queue_purge(&nr
->frag_queue
);
45 * This routine purges the input queue of those frames that have been
46 * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
49 void nr_frames_acked(struct sock
*sk
, unsigned short nr
)
51 struct nr_sock
*nrom
= nr_sk(sk
);
55 * Remove all the ack-ed frames from the ack queue.
58 while (skb_peek(&nrom
->ack_queue
) != NULL
&& nrom
->va
!= nr
) {
59 skb
= skb_dequeue(&nrom
->ack_queue
);
61 nrom
->va
= (nrom
->va
+ 1) % NR_MODULUS
;
67 * Requeue all the un-ack-ed frames on the output queue to be picked
68 * up by nr_kick called from the timer. This arrangement handles the
69 * possibility of an empty output queue.
71 void nr_requeue_frames(struct sock
*sk
)
73 struct sk_buff
*skb
, *skb_prev
= NULL
;
75 while ((skb
= skb_dequeue(&nr_sk(sk
)->ack_queue
)) != NULL
) {
77 skb_queue_head(&sk
->sk_write_queue
, skb
);
79 skb_append(skb_prev
, skb
, &sk
->sk_write_queue
);
85 * Validate that the value of nr is between va and vs. Return true or
88 int nr_validate_nr(struct sock
*sk
, unsigned short nr
)
90 struct nr_sock
*nrom
= nr_sk(sk
);
91 unsigned short vc
= nrom
->va
;
93 while (vc
!= nrom
->vs
) {
94 if (nr
== vc
) return 1;
95 vc
= (vc
+ 1) % NR_MODULUS
;
98 return nr
== nrom
->vs
;
102 * Check that ns is within the receive window.
104 int nr_in_rx_window(struct sock
*sk
, unsigned short ns
)
106 struct nr_sock
*nr
= nr_sk(sk
);
107 unsigned short vc
= nr
->vr
;
108 unsigned short vt
= (nr
->vl
+ nr
->window
) % NR_MODULUS
;
111 if (ns
== vc
) return 1;
112 vc
= (vc
+ 1) % NR_MODULUS
;
119 * This routine is called when the HDLC layer internally generates a
122 void nr_write_internal(struct sock
*sk
, int frametype
)
124 struct nr_sock
*nr
= nr_sk(sk
);
129 len
= NR_NETWORK_LEN
+ NR_TRANSPORT_LEN
;
131 switch (frametype
& 0x0F) {
136 len
+= (nr
->bpqext
) ? 2 : 1;
143 printk(KERN_ERR
"NET/ROM: nr_write_internal - invalid frame type %d\n", frametype
);
147 if ((skb
= alloc_skb(len
, GFP_ATOMIC
)) == NULL
)
151 * Space for AX.25 and NET/ROM network header
153 skb_reserve(skb
, NR_NETWORK_LEN
);
155 dptr
= skb_put(skb
, skb_tailroom(skb
));
157 switch (frametype
& 0x0F) {
159 timeout
= nr
->t1
/ HZ
;
160 *dptr
++ = nr
->my_index
;
165 *dptr
++ = nr
->window
;
166 memcpy(dptr
, &nr
->user_addr
, AX25_ADDR_LEN
);
167 dptr
[6] &= ~AX25_CBIT
;
168 dptr
[6] &= ~AX25_EBIT
;
169 dptr
[6] |= AX25_SSSID_SPARE
;
170 dptr
+= AX25_ADDR_LEN
;
171 memcpy(dptr
, &nr
->source_addr
, AX25_ADDR_LEN
);
172 dptr
[6] &= ~AX25_CBIT
;
173 dptr
[6] &= ~AX25_EBIT
;
174 dptr
[6] |= AX25_SSSID_SPARE
;
175 dptr
+= AX25_ADDR_LEN
;
176 *dptr
++ = timeout
% 256;
177 *dptr
++ = timeout
/ 256;
181 *dptr
++ = nr
->your_index
;
182 *dptr
++ = nr
->your_id
;
183 *dptr
++ = nr
->my_index
;
186 *dptr
++ = nr
->window
;
187 if (nr
->bpqext
) *dptr
++ = sysctl_netrom_network_ttl_initialiser
;
192 *dptr
++ = nr
->your_index
;
193 *dptr
++ = nr
->your_id
;
200 *dptr
++ = nr
->your_index
;
201 *dptr
++ = nr
->your_id
;
208 nr_transmit_buffer(sk
, skb
);
212 * This routine is called to send an error reply.
214 void __nr_transmit_reply(struct sk_buff
*skb
, int mine
, unsigned char cmdflags
)
216 struct sk_buff
*skbn
;
220 len
= NR_NETWORK_LEN
+ NR_TRANSPORT_LEN
+ 1;
222 if ((skbn
= alloc_skb(len
, GFP_ATOMIC
)) == NULL
)
225 skb_reserve(skbn
, 0);
227 dptr
= skb_put(skbn
, NR_NETWORK_LEN
+ NR_TRANSPORT_LEN
);
229 skb_copy_from_linear_data_offset(skb
, 7, dptr
, AX25_ADDR_LEN
);
230 dptr
[6] &= ~AX25_CBIT
;
231 dptr
[6] &= ~AX25_EBIT
;
232 dptr
[6] |= AX25_SSSID_SPARE
;
233 dptr
+= AX25_ADDR_LEN
;
235 skb_copy_from_linear_data(skb
, dptr
, AX25_ADDR_LEN
);
236 dptr
[6] &= ~AX25_CBIT
;
237 dptr
[6] |= AX25_EBIT
;
238 dptr
[6] |= AX25_SSSID_SPARE
;
239 dptr
+= AX25_ADDR_LEN
;
241 *dptr
++ = sysctl_netrom_network_ttl_initialiser
;
246 *dptr
++ = skb
->data
[15];
247 *dptr
++ = skb
->data
[16];
249 *dptr
++ = skb
->data
[15];
250 *dptr
++ = skb
->data
[16];
258 if (!nr_route_frame(skbn
, NULL
))
262 void nr_disconnect(struct sock
*sk
, int reason
)
267 nr_stop_idletimer(sk
);
271 nr_sk(sk
)->state
= NR_STATE_0
;
273 sk
->sk_state
= TCP_CLOSE
;
275 sk
->sk_shutdown
|= SEND_SHUTDOWN
;
277 if (!sock_flag(sk
, SOCK_DEAD
)) {
278 sk
->sk_state_change(sk
);
279 sock_set_flag(sk
, SOCK_DEAD
);