Root/
1 | /* |
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. |
6 | * |
7 | * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) |
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 <asm/uaccess.h> |
26 | #include <asm/system.h> |
27 | #include <linux/fcntl.h> |
28 | #include <linux/mm.h> |
29 | #include <linux/interrupt.h> |
30 | #include <net/netrom.h> |
31 | |
32 | /* |
33 | * This routine purges all of the queues of frames. |
34 | */ |
35 | void nr_clear_queues(struct sock *sk) |
36 | { |
37 | struct nr_sock *nr = nr_sk(sk); |
38 | |
39 | skb_queue_purge(&sk->sk_write_queue); |
40 | skb_queue_purge(&nr->ack_queue); |
41 | skb_queue_purge(&nr->reseq_queue); |
42 | skb_queue_purge(&nr->frag_queue); |
43 | } |
44 | |
45 | /* |
46 | * This routine purges the input queue of those frames that have been |
47 | * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the |
48 | * SDL diagram. |
49 | */ |
50 | void nr_frames_acked(struct sock *sk, unsigned short nr) |
51 | { |
52 | struct nr_sock *nrom = nr_sk(sk); |
53 | struct sk_buff *skb; |
54 | |
55 | /* |
56 | * Remove all the ack-ed frames from the ack queue. |
57 | */ |
58 | if (nrom->va != nr) { |
59 | while (skb_peek(&nrom->ack_queue) != NULL && nrom->va != nr) { |
60 | skb = skb_dequeue(&nrom->ack_queue); |
61 | kfree_skb(skb); |
62 | nrom->va = (nrom->va + 1) % NR_MODULUS; |
63 | } |
64 | } |
65 | } |
66 | |
67 | /* |
68 | * Requeue all the un-ack-ed frames on the output queue to be picked |
69 | * up by nr_kick called from the timer. This arrangement handles the |
70 | * possibility of an empty output queue. |
71 | */ |
72 | void nr_requeue_frames(struct sock *sk) |
73 | { |
74 | struct sk_buff *skb, *skb_prev = NULL; |
75 | |
76 | while ((skb = skb_dequeue(&nr_sk(sk)->ack_queue)) != NULL) { |
77 | if (skb_prev == NULL) |
78 | skb_queue_head(&sk->sk_write_queue, skb); |
79 | else |
80 | skb_append(skb_prev, skb, &sk->sk_write_queue); |
81 | skb_prev = skb; |
82 | } |
83 | } |
84 | |
85 | /* |
86 | * Validate that the value of nr is between va and vs. Return true or |
87 | * false for testing. |
88 | */ |
89 | int nr_validate_nr(struct sock *sk, unsigned short nr) |
90 | { |
91 | struct nr_sock *nrom = nr_sk(sk); |
92 | unsigned short vc = nrom->va; |
93 | |
94 | while (vc != nrom->vs) { |
95 | if (nr == vc) return 1; |
96 | vc = (vc + 1) % NR_MODULUS; |
97 | } |
98 | |
99 | return nr == nrom->vs; |
100 | } |
101 | |
102 | /* |
103 | * Check that ns is within the receive window. |
104 | */ |
105 | int nr_in_rx_window(struct sock *sk, unsigned short ns) |
106 | { |
107 | struct nr_sock *nr = nr_sk(sk); |
108 | unsigned short vc = nr->vr; |
109 | unsigned short vt = (nr->vl + nr->window) % NR_MODULUS; |
110 | |
111 | while (vc != vt) { |
112 | if (ns == vc) return 1; |
113 | vc = (vc + 1) % NR_MODULUS; |
114 | } |
115 | |
116 | return 0; |
117 | } |
118 | |
119 | /* |
120 | * This routine is called when the HDLC layer internally generates a |
121 | * control frame. |
122 | */ |
123 | void nr_write_internal(struct sock *sk, int frametype) |
124 | { |
125 | struct nr_sock *nr = nr_sk(sk); |
126 | struct sk_buff *skb; |
127 | unsigned char *dptr; |
128 | int len, timeout; |
129 | |
130 | len = NR_NETWORK_LEN + NR_TRANSPORT_LEN; |
131 | |
132 | switch (frametype & 0x0F) { |
133 | case NR_CONNREQ: |
134 | len += 17; |
135 | break; |
136 | case NR_CONNACK: |
137 | len += (nr->bpqext) ? 2 : 1; |
138 | break; |
139 | case NR_DISCREQ: |
140 | case NR_DISCACK: |
141 | case NR_INFOACK: |
142 | break; |
143 | default: |
144 | printk(KERN_ERR "NET/ROM: nr_write_internal - invalid frame type %d\n", frametype); |
145 | return; |
146 | } |
147 | |
148 | if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL) |
149 | return; |
150 | |
151 | /* |
152 | * Space for AX.25 and NET/ROM network header |
153 | */ |
154 | skb_reserve(skb, NR_NETWORK_LEN); |
155 | |
156 | dptr = skb_put(skb, skb_tailroom(skb)); |
157 | |
158 | switch (frametype & 0x0F) { |
159 | case NR_CONNREQ: |
160 | timeout = nr->t1 / HZ; |
161 | *dptr++ = nr->my_index; |
162 | *dptr++ = nr->my_id; |
163 | *dptr++ = 0; |
164 | *dptr++ = 0; |
165 | *dptr++ = frametype; |
166 | *dptr++ = nr->window; |
167 | memcpy(dptr, &nr->user_addr, AX25_ADDR_LEN); |
168 | dptr[6] &= ~AX25_CBIT; |
169 | dptr[6] &= ~AX25_EBIT; |
170 | dptr[6] |= AX25_SSSID_SPARE; |
171 | dptr += AX25_ADDR_LEN; |
172 | memcpy(dptr, &nr->source_addr, AX25_ADDR_LEN); |
173 | dptr[6] &= ~AX25_CBIT; |
174 | dptr[6] &= ~AX25_EBIT; |
175 | dptr[6] |= AX25_SSSID_SPARE; |
176 | dptr += AX25_ADDR_LEN; |
177 | *dptr++ = timeout % 256; |
178 | *dptr++ = timeout / 256; |
179 | break; |
180 | |
181 | case NR_CONNACK: |
182 | *dptr++ = nr->your_index; |
183 | *dptr++ = nr->your_id; |
184 | *dptr++ = nr->my_index; |
185 | *dptr++ = nr->my_id; |
186 | *dptr++ = frametype; |
187 | *dptr++ = nr->window; |
188 | if (nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser; |
189 | break; |
190 | |
191 | case NR_DISCREQ: |
192 | case NR_DISCACK: |
193 | *dptr++ = nr->your_index; |
194 | *dptr++ = nr->your_id; |
195 | *dptr++ = 0; |
196 | *dptr++ = 0; |
197 | *dptr++ = frametype; |
198 | break; |
199 | |
200 | case NR_INFOACK: |
201 | *dptr++ = nr->your_index; |
202 | *dptr++ = nr->your_id; |
203 | *dptr++ = 0; |
204 | *dptr++ = nr->vr; |
205 | *dptr++ = frametype; |
206 | break; |
207 | } |
208 | |
209 | nr_transmit_buffer(sk, skb); |
210 | } |
211 | |
212 | /* |
213 | * This routine is called to send an error reply. |
214 | */ |
215 | void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags) |
216 | { |
217 | struct sk_buff *skbn; |
218 | unsigned char *dptr; |
219 | int len; |
220 | |
221 | len = NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1; |
222 | |
223 | if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL) |
224 | return; |
225 | |
226 | skb_reserve(skbn, 0); |
227 | |
228 | dptr = skb_put(skbn, NR_NETWORK_LEN + NR_TRANSPORT_LEN); |
229 | |
230 | skb_copy_from_linear_data_offset(skb, 7, dptr, AX25_ADDR_LEN); |
231 | dptr[6] &= ~AX25_CBIT; |
232 | dptr[6] &= ~AX25_EBIT; |
233 | dptr[6] |= AX25_SSSID_SPARE; |
234 | dptr += AX25_ADDR_LEN; |
235 | |
236 | skb_copy_from_linear_data(skb, dptr, AX25_ADDR_LEN); |
237 | dptr[6] &= ~AX25_CBIT; |
238 | dptr[6] |= AX25_EBIT; |
239 | dptr[6] |= AX25_SSSID_SPARE; |
240 | dptr += AX25_ADDR_LEN; |
241 | |
242 | *dptr++ = sysctl_netrom_network_ttl_initialiser; |
243 | |
244 | if (mine) { |
245 | *dptr++ = 0; |
246 | *dptr++ = 0; |
247 | *dptr++ = skb->data[15]; |
248 | *dptr++ = skb->data[16]; |
249 | } else { |
250 | *dptr++ = skb->data[15]; |
251 | *dptr++ = skb->data[16]; |
252 | *dptr++ = 0; |
253 | *dptr++ = 0; |
254 | } |
255 | |
256 | *dptr++ = cmdflags; |
257 | *dptr++ = 0; |
258 | |
259 | if (!nr_route_frame(skbn, NULL)) |
260 | kfree_skb(skbn); |
261 | } |
262 | |
263 | void nr_disconnect(struct sock *sk, int reason) |
264 | { |
265 | nr_stop_t1timer(sk); |
266 | nr_stop_t2timer(sk); |
267 | nr_stop_t4timer(sk); |
268 | nr_stop_idletimer(sk); |
269 | |
270 | nr_clear_queues(sk); |
271 | |
272 | nr_sk(sk)->state = NR_STATE_0; |
273 | |
274 | sk->sk_state = TCP_CLOSE; |
275 | sk->sk_err = reason; |
276 | sk->sk_shutdown |= SEND_SHUTDOWN; |
277 | |
278 | if (!sock_flag(sk, SOCK_DEAD)) { |
279 | sk->sk_state_change(sk); |
280 | sock_set_flag(sk, SOCK_DEAD); |
281 | } |
282 | } |
283 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9