• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/net/x25/
1/*
2 *	X.25 Packet Layer release 002
3 *
4 *	This is ALPHA test software. This code may break your machine,
5 *	randomly fail to work with new releases, misbehave and/or generally
6 *	screw up. It might even work.
7 *
8 *	This code REQUIRES 2.1.15 or higher
9 *
10 *	This module:
11 *		This module is free software; you can redistribute it and/or
12 *		modify it under the terms of the GNU General Public License
13 *		as published by the Free Software Foundation; either version
14 *		2 of the License, or (at your option) any later version.
15 *
16 *	History
17 *	X.25 001	Jonathan Naylor	  Started coding.
18 *	X.25 002	Jonathan Naylor	  Centralised disconnection code.
19 *					  New timer architecture.
20 *	2000-03-20	Daniela Squassoni Disabling/enabling of facilities
21 *					  negotiation.
22 *	2000-11-10	Henner Eisen	  Check and reset for out-of-sequence
23 *					  i-frames.
24 */
25
26#include <linux/slab.h>
27#include <linux/errno.h>
28#include <linux/kernel.h>
29#include <linux/string.h>
30#include <linux/skbuff.h>
31#include <net/sock.h>
32#include <net/tcp_states.h>
33#include <net/x25.h>
34
35static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
36{
37	struct sk_buff *skbo, *skbn = skb;
38	struct x25_sock *x25 = x25_sk(sk);
39
40	if (more) {
41		x25->fraglen += skb->len;
42		skb_queue_tail(&x25->fragment_queue, skb);
43		skb_set_owner_r(skb, sk);
44		return 0;
45	}
46
47	if (!more && x25->fraglen > 0) {	/* End of fragment */
48		int len = x25->fraglen + skb->len;
49
50		if ((skbn = alloc_skb(len, GFP_ATOMIC)) == NULL){
51			kfree_skb(skb);
52			return 1;
53		}
54
55		skb_queue_tail(&x25->fragment_queue, skb);
56
57		skb_reset_transport_header(skbn);
58
59		skbo = skb_dequeue(&x25->fragment_queue);
60		skb_copy_from_linear_data(skbo, skb_put(skbn, skbo->len),
61					  skbo->len);
62		kfree_skb(skbo);
63
64		while ((skbo =
65			skb_dequeue(&x25->fragment_queue)) != NULL) {
66			skb_pull(skbo, (x25->neighbour->extended) ?
67					X25_EXT_MIN_LEN : X25_STD_MIN_LEN);
68			skb_copy_from_linear_data(skbo,
69						  skb_put(skbn, skbo->len),
70						  skbo->len);
71			kfree_skb(skbo);
72		}
73
74		x25->fraglen = 0;
75	}
76
77	skb_set_owner_r(skbn, sk);
78	skb_queue_tail(&sk->sk_receive_queue, skbn);
79	if (!sock_flag(sk, SOCK_DEAD))
80		sk->sk_data_ready(sk, skbn->len);
81
82	return 0;
83}
84
85/*
86 * State machine for state 1, Awaiting Call Accepted State.
87 * The handling of the timer(s) is in file x25_timer.c.
88 * Handling of state 0 and connection release is in af_x25.c.
89 */
90static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
91{
92	struct x25_address source_addr, dest_addr;
93	int len;
94
95	switch (frametype) {
96		case X25_CALL_ACCEPTED: {
97			struct x25_sock *x25 = x25_sk(sk);
98
99			x25_stop_timer(sk);
100			x25->condition = 0x00;
101			x25->vs        = 0;
102			x25->va        = 0;
103			x25->vr        = 0;
104			x25->vl        = 0;
105			x25->state     = X25_STATE_3;
106			sk->sk_state   = TCP_ESTABLISHED;
107			/*
108			 *	Parse the data in the frame.
109			 */
110			skb_pull(skb, X25_STD_MIN_LEN);
111
112			len = x25_parse_address_block(skb, &source_addr,
113						&dest_addr);
114			if (len > 0)
115				skb_pull(skb, len);
116
117			len = x25_parse_facilities(skb, &x25->facilities,
118						&x25->dte_facilities,
119						&x25->vc_facil_mask);
120			if (len > 0)
121				skb_pull(skb, len);
122			else
123				return -1;
124			/*
125			 *	Copy any Call User Data.
126			 */
127			if (skb->len > 0) {
128				skb_copy_from_linear_data(skb,
129					      x25->calluserdata.cuddata,
130					      skb->len);
131				x25->calluserdata.cudlength = skb->len;
132			}
133			if (!sock_flag(sk, SOCK_DEAD))
134				sk->sk_state_change(sk);
135			break;
136		}
137		case X25_CLEAR_REQUEST:
138			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
139			x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
140			break;
141
142		default:
143			break;
144	}
145
146	return 0;
147}
148
149/*
150 * State machine for state 2, Awaiting Clear Confirmation State.
151 * The handling of the timer(s) is in file x25_timer.c
152 * Handling of state 0 and connection release is in af_x25.c.
153 */
154static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)
155{
156	switch (frametype) {
157
158		case X25_CLEAR_REQUEST:
159			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
160			x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
161			break;
162
163		case X25_CLEAR_CONFIRMATION:
164			x25_disconnect(sk, 0, 0, 0);
165			break;
166
167		default:
168			break;
169	}
170
171	return 0;
172}
173
174/*
175 * State machine for state 3, Connected State.
176 * The handling of the timer(s) is in file x25_timer.c
177 * Handling of state 0 and connection release is in af_x25.c.
178 */
179static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m)
180{
181	int queued = 0;
182	int modulus;
183	struct x25_sock *x25 = x25_sk(sk);
184
185	modulus = (x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
186
187	switch (frametype) {
188
189		case X25_RESET_REQUEST:
190			x25_write_internal(sk, X25_RESET_CONFIRMATION);
191			x25_stop_timer(sk);
192			x25->condition = 0x00;
193			x25->vs        = 0;
194			x25->vr        = 0;
195			x25->va        = 0;
196			x25->vl        = 0;
197			x25_requeue_frames(sk);
198			break;
199
200		case X25_CLEAR_REQUEST:
201			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
202			x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
203			break;
204
205		case X25_RR:
206		case X25_RNR:
207			if (!x25_validate_nr(sk, nr)) {
208				x25_clear_queues(sk);
209				x25_write_internal(sk, X25_RESET_REQUEST);
210				x25_start_t22timer(sk);
211				x25->condition = 0x00;
212				x25->vs        = 0;
213				x25->vr        = 0;
214				x25->va        = 0;
215				x25->vl        = 0;
216				x25->state     = X25_STATE_4;
217			} else {
218				x25_frames_acked(sk, nr);
219				if (frametype == X25_RNR) {
220					x25->condition |= X25_COND_PEER_RX_BUSY;
221				} else {
222					x25->condition &= ~X25_COND_PEER_RX_BUSY;
223				}
224			}
225			break;
226
227		case X25_DATA:
228			x25->condition &= ~X25_COND_PEER_RX_BUSY;
229			if ((ns != x25->vr) || !x25_validate_nr(sk, nr)) {
230				x25_clear_queues(sk);
231				x25_write_internal(sk, X25_RESET_REQUEST);
232				x25_start_t22timer(sk);
233				x25->condition = 0x00;
234				x25->vs        = 0;
235				x25->vr        = 0;
236				x25->va        = 0;
237				x25->vl        = 0;
238				x25->state     = X25_STATE_4;
239				break;
240			}
241			x25_frames_acked(sk, nr);
242			if (ns == x25->vr) {
243				if (x25_queue_rx_frame(sk, skb, m) == 0) {
244					x25->vr = (x25->vr + 1) % modulus;
245					queued = 1;
246				} else {
247					/* Should never happen */
248					x25_clear_queues(sk);
249					x25_write_internal(sk, X25_RESET_REQUEST);
250					x25_start_t22timer(sk);
251					x25->condition = 0x00;
252					x25->vs        = 0;
253					x25->vr        = 0;
254					x25->va        = 0;
255					x25->vl        = 0;
256					x25->state     = X25_STATE_4;
257					break;
258				}
259				if (atomic_read(&sk->sk_rmem_alloc) >
260				    (sk->sk_rcvbuf >> 1))
261					x25->condition |= X25_COND_OWN_RX_BUSY;
262			}
263			/*
264			 *	If the window is full Ack it immediately, else
265			 *	start the holdback timer.
266			 */
267			if (((x25->vl + x25->facilities.winsize_in) % modulus) == x25->vr) {
268				x25->condition &= ~X25_COND_ACK_PENDING;
269				x25_stop_timer(sk);
270				x25_enquiry_response(sk);
271			} else {
272				x25->condition |= X25_COND_ACK_PENDING;
273				x25_start_t2timer(sk);
274			}
275			break;
276
277		case X25_INTERRUPT_CONFIRMATION:
278			clear_bit(X25_INTERRUPT_FLAG, &x25->flags);
279			break;
280
281		case X25_INTERRUPT:
282			if (sock_flag(sk, SOCK_URGINLINE))
283				queued = !sock_queue_rcv_skb(sk, skb);
284			else {
285				skb_set_owner_r(skb, sk);
286				skb_queue_tail(&x25->interrupt_in_queue, skb);
287				queued = 1;
288			}
289			sk_send_sigurg(sk);
290			x25_write_internal(sk, X25_INTERRUPT_CONFIRMATION);
291			break;
292
293		default:
294			printk(KERN_WARNING "x25: unknown %02X in state 3\n", frametype);
295			break;
296	}
297
298	return queued;
299}
300
301/*
302 * State machine for state 4, Awaiting Reset Confirmation State.
303 * The handling of the timer(s) is in file x25_timer.c
304 * Handling of state 0 and connection release is in af_x25.c.
305 */
306static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype)
307{
308	switch (frametype) {
309
310		case X25_RESET_REQUEST:
311			x25_write_internal(sk, X25_RESET_CONFIRMATION);
312		case X25_RESET_CONFIRMATION: {
313			struct x25_sock *x25 = x25_sk(sk);
314
315			x25_stop_timer(sk);
316			x25->condition = 0x00;
317			x25->va        = 0;
318			x25->vr        = 0;
319			x25->vs        = 0;
320			x25->vl        = 0;
321			x25->state     = X25_STATE_3;
322			x25_requeue_frames(sk);
323			break;
324		}
325		case X25_CLEAR_REQUEST:
326			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
327			x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
328			break;
329
330		default:
331			break;
332	}
333
334	return 0;
335}
336
337/* Higher level upcall for a LAPB frame */
338int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
339{
340	struct x25_sock *x25 = x25_sk(sk);
341	int queued = 0, frametype, ns, nr, q, d, m;
342
343	if (x25->state == X25_STATE_0)
344		return 0;
345
346	frametype = x25_decode(sk, skb, &ns, &nr, &q, &d, &m);
347
348	switch (x25->state) {
349		case X25_STATE_1:
350			queued = x25_state1_machine(sk, skb, frametype);
351			break;
352		case X25_STATE_2:
353			queued = x25_state2_machine(sk, skb, frametype);
354			break;
355		case X25_STATE_3:
356			queued = x25_state3_machine(sk, skb, frametype, ns, nr, q, d, m);
357			break;
358		case X25_STATE_4:
359			queued = x25_state4_machine(sk, skb, frametype);
360			break;
361	}
362
363	x25_kick(sk);
364
365	return queued;
366}
367
368int x25_backlog_rcv(struct sock *sk, struct sk_buff *skb)
369{
370	int queued = x25_process_rx_frame(sk, skb);
371
372	if (!queued)
373		kfree_skb(skb);
374
375	return 0;
376}
377