xref: /OK3568_Linux_fs/kernel/net/rose/rose_subr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun #include <linux/errno.h>
7*4882a593Smuzhiyun #include <linux/types.h>
8*4882a593Smuzhiyun #include <linux/socket.h>
9*4882a593Smuzhiyun #include <linux/in.h>
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/timer.h>
12*4882a593Smuzhiyun #include <linux/string.h>
13*4882a593Smuzhiyun #include <linux/sockios.h>
14*4882a593Smuzhiyun #include <linux/net.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <net/ax25.h>
17*4882a593Smuzhiyun #include <linux/inet.h>
18*4882a593Smuzhiyun #include <linux/netdevice.h>
19*4882a593Smuzhiyun #include <linux/skbuff.h>
20*4882a593Smuzhiyun #include <net/sock.h>
21*4882a593Smuzhiyun #include <net/tcp_states.h>
22*4882a593Smuzhiyun #include <linux/fcntl.h>
23*4882a593Smuzhiyun #include <linux/mm.h>
24*4882a593Smuzhiyun #include <linux/interrupt.h>
25*4882a593Smuzhiyun #include <net/rose.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose);
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun  *	This routine purges all of the queues of frames.
31*4882a593Smuzhiyun  */
rose_clear_queues(struct sock * sk)32*4882a593Smuzhiyun void rose_clear_queues(struct sock *sk)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	skb_queue_purge(&sk->sk_write_queue);
35*4882a593Smuzhiyun 	skb_queue_purge(&rose_sk(sk)->ack_queue);
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /*
39*4882a593Smuzhiyun  * This routine purges the input queue of those frames that have been
40*4882a593Smuzhiyun  * acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
41*4882a593Smuzhiyun  * SDL diagram.
42*4882a593Smuzhiyun  */
rose_frames_acked(struct sock * sk,unsigned short nr)43*4882a593Smuzhiyun void rose_frames_acked(struct sock *sk, unsigned short nr)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	struct sk_buff *skb;
46*4882a593Smuzhiyun 	struct rose_sock *rose = rose_sk(sk);
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	/*
49*4882a593Smuzhiyun 	 * Remove all the ack-ed frames from the ack queue.
50*4882a593Smuzhiyun 	 */
51*4882a593Smuzhiyun 	if (rose->va != nr) {
52*4882a593Smuzhiyun 		while (skb_peek(&rose->ack_queue) != NULL && rose->va != nr) {
53*4882a593Smuzhiyun 			skb = skb_dequeue(&rose->ack_queue);
54*4882a593Smuzhiyun 			kfree_skb(skb);
55*4882a593Smuzhiyun 			rose->va = (rose->va + 1) % ROSE_MODULUS;
56*4882a593Smuzhiyun 		}
57*4882a593Smuzhiyun 	}
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
rose_requeue_frames(struct sock * sk)60*4882a593Smuzhiyun void rose_requeue_frames(struct sock *sk)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	struct sk_buff *skb, *skb_prev = NULL;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	/*
65*4882a593Smuzhiyun 	 * Requeue all the un-ack-ed frames on the output queue to be picked
66*4882a593Smuzhiyun 	 * up by rose_kick. This arrangement handles the possibility of an
67*4882a593Smuzhiyun 	 * empty output queue.
68*4882a593Smuzhiyun 	 */
69*4882a593Smuzhiyun 	while ((skb = skb_dequeue(&rose_sk(sk)->ack_queue)) != NULL) {
70*4882a593Smuzhiyun 		if (skb_prev == NULL)
71*4882a593Smuzhiyun 			skb_queue_head(&sk->sk_write_queue, skb);
72*4882a593Smuzhiyun 		else
73*4882a593Smuzhiyun 			skb_append(skb_prev, skb, &sk->sk_write_queue);
74*4882a593Smuzhiyun 		skb_prev = skb;
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun  *	Validate that the value of nr is between va and vs. Return true or
80*4882a593Smuzhiyun  *	false for testing.
81*4882a593Smuzhiyun  */
rose_validate_nr(struct sock * sk,unsigned short nr)82*4882a593Smuzhiyun int rose_validate_nr(struct sock *sk, unsigned short nr)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	struct rose_sock *rose = rose_sk(sk);
85*4882a593Smuzhiyun 	unsigned short vc = rose->va;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	while (vc != rose->vs) {
88*4882a593Smuzhiyun 		if (nr == vc) return 1;
89*4882a593Smuzhiyun 		vc = (vc + 1) % ROSE_MODULUS;
90*4882a593Smuzhiyun 	}
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	return nr == rose->vs;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun /*
96*4882a593Smuzhiyun  *  This routine is called when the packet layer internally generates a
97*4882a593Smuzhiyun  *  control frame.
98*4882a593Smuzhiyun  */
rose_write_internal(struct sock * sk,int frametype)99*4882a593Smuzhiyun void rose_write_internal(struct sock *sk, int frametype)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	struct rose_sock *rose = rose_sk(sk);
102*4882a593Smuzhiyun 	struct sk_buff *skb;
103*4882a593Smuzhiyun 	unsigned char  *dptr;
104*4882a593Smuzhiyun 	unsigned char  lci1, lci2;
105*4882a593Smuzhiyun 	int maxfaclen = 0;
106*4882a593Smuzhiyun 	int len, faclen;
107*4882a593Smuzhiyun 	int reserve;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	reserve = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 1;
110*4882a593Smuzhiyun 	len = ROSE_MIN_LEN;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	switch (frametype) {
113*4882a593Smuzhiyun 	case ROSE_CALL_REQUEST:
114*4882a593Smuzhiyun 		len   += 1 + ROSE_ADDR_LEN + ROSE_ADDR_LEN;
115*4882a593Smuzhiyun 		maxfaclen = 256;
116*4882a593Smuzhiyun 		break;
117*4882a593Smuzhiyun 	case ROSE_CALL_ACCEPTED:
118*4882a593Smuzhiyun 	case ROSE_CLEAR_REQUEST:
119*4882a593Smuzhiyun 	case ROSE_RESET_REQUEST:
120*4882a593Smuzhiyun 		len   += 2;
121*4882a593Smuzhiyun 		break;
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	skb = alloc_skb(reserve + len + maxfaclen, GFP_ATOMIC);
125*4882a593Smuzhiyun 	if (!skb)
126*4882a593Smuzhiyun 		return;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	/*
129*4882a593Smuzhiyun 	 *	Space for AX.25 header and PID.
130*4882a593Smuzhiyun 	 */
131*4882a593Smuzhiyun 	skb_reserve(skb, reserve);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	dptr = skb_put(skb, len);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	lci1 = (rose->lci >> 8) & 0x0F;
136*4882a593Smuzhiyun 	lci2 = (rose->lci >> 0) & 0xFF;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	switch (frametype) {
139*4882a593Smuzhiyun 	case ROSE_CALL_REQUEST:
140*4882a593Smuzhiyun 		*dptr++ = ROSE_GFI | lci1;
141*4882a593Smuzhiyun 		*dptr++ = lci2;
142*4882a593Smuzhiyun 		*dptr++ = frametype;
143*4882a593Smuzhiyun 		*dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL;
144*4882a593Smuzhiyun 		memcpy(dptr, &rose->dest_addr,  ROSE_ADDR_LEN);
145*4882a593Smuzhiyun 		dptr   += ROSE_ADDR_LEN;
146*4882a593Smuzhiyun 		memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN);
147*4882a593Smuzhiyun 		dptr   += ROSE_ADDR_LEN;
148*4882a593Smuzhiyun 		faclen = rose_create_facilities(dptr, rose);
149*4882a593Smuzhiyun 		skb_put(skb, faclen);
150*4882a593Smuzhiyun 		dptr   += faclen;
151*4882a593Smuzhiyun 		break;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	case ROSE_CALL_ACCEPTED:
154*4882a593Smuzhiyun 		*dptr++ = ROSE_GFI | lci1;
155*4882a593Smuzhiyun 		*dptr++ = lci2;
156*4882a593Smuzhiyun 		*dptr++ = frametype;
157*4882a593Smuzhiyun 		*dptr++ = 0x00;		/* Address length */
158*4882a593Smuzhiyun 		*dptr++ = 0;		/* Facilities length */
159*4882a593Smuzhiyun 		break;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	case ROSE_CLEAR_REQUEST:
162*4882a593Smuzhiyun 		*dptr++ = ROSE_GFI | lci1;
163*4882a593Smuzhiyun 		*dptr++ = lci2;
164*4882a593Smuzhiyun 		*dptr++ = frametype;
165*4882a593Smuzhiyun 		*dptr++ = rose->cause;
166*4882a593Smuzhiyun 		*dptr++ = rose->diagnostic;
167*4882a593Smuzhiyun 		break;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	case ROSE_RESET_REQUEST:
170*4882a593Smuzhiyun 		*dptr++ = ROSE_GFI | lci1;
171*4882a593Smuzhiyun 		*dptr++ = lci2;
172*4882a593Smuzhiyun 		*dptr++ = frametype;
173*4882a593Smuzhiyun 		*dptr++ = ROSE_DTE_ORIGINATED;
174*4882a593Smuzhiyun 		*dptr++ = 0;
175*4882a593Smuzhiyun 		break;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	case ROSE_RR:
178*4882a593Smuzhiyun 	case ROSE_RNR:
179*4882a593Smuzhiyun 		*dptr++ = ROSE_GFI | lci1;
180*4882a593Smuzhiyun 		*dptr++ = lci2;
181*4882a593Smuzhiyun 		*dptr   = frametype;
182*4882a593Smuzhiyun 		*dptr++ |= (rose->vr << 5) & 0xE0;
183*4882a593Smuzhiyun 		break;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	case ROSE_CLEAR_CONFIRMATION:
186*4882a593Smuzhiyun 	case ROSE_RESET_CONFIRMATION:
187*4882a593Smuzhiyun 		*dptr++ = ROSE_GFI | lci1;
188*4882a593Smuzhiyun 		*dptr++ = lci2;
189*4882a593Smuzhiyun 		*dptr++  = frametype;
190*4882a593Smuzhiyun 		break;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	default:
193*4882a593Smuzhiyun 		printk(KERN_ERR "ROSE: rose_write_internal - invalid frametype %02X\n", frametype);
194*4882a593Smuzhiyun 		kfree_skb(skb);
195*4882a593Smuzhiyun 		return;
196*4882a593Smuzhiyun 	}
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	rose_transmit_link(skb, rose->neighbour);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
rose_decode(struct sk_buff * skb,int * ns,int * nr,int * q,int * d,int * m)201*4882a593Smuzhiyun int rose_decode(struct sk_buff *skb, int *ns, int *nr, int *q, int *d, int *m)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun 	unsigned char *frame;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	frame = skb->data;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	*ns = *nr = *q = *d = *m = 0;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	switch (frame[2]) {
210*4882a593Smuzhiyun 	case ROSE_CALL_REQUEST:
211*4882a593Smuzhiyun 	case ROSE_CALL_ACCEPTED:
212*4882a593Smuzhiyun 	case ROSE_CLEAR_REQUEST:
213*4882a593Smuzhiyun 	case ROSE_CLEAR_CONFIRMATION:
214*4882a593Smuzhiyun 	case ROSE_RESET_REQUEST:
215*4882a593Smuzhiyun 	case ROSE_RESET_CONFIRMATION:
216*4882a593Smuzhiyun 		return frame[2];
217*4882a593Smuzhiyun 	default:
218*4882a593Smuzhiyun 		break;
219*4882a593Smuzhiyun 	}
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	if ((frame[2] & 0x1F) == ROSE_RR  ||
222*4882a593Smuzhiyun 	    (frame[2] & 0x1F) == ROSE_RNR) {
223*4882a593Smuzhiyun 		*nr = (frame[2] >> 5) & 0x07;
224*4882a593Smuzhiyun 		return frame[2] & 0x1F;
225*4882a593Smuzhiyun 	}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	if ((frame[2] & 0x01) == ROSE_DATA) {
228*4882a593Smuzhiyun 		*q  = (frame[0] & ROSE_Q_BIT) == ROSE_Q_BIT;
229*4882a593Smuzhiyun 		*d  = (frame[0] & ROSE_D_BIT) == ROSE_D_BIT;
230*4882a593Smuzhiyun 		*m  = (frame[2] & ROSE_M_BIT) == ROSE_M_BIT;
231*4882a593Smuzhiyun 		*nr = (frame[2] >> 5) & 0x07;
232*4882a593Smuzhiyun 		*ns = (frame[2] >> 1) & 0x07;
233*4882a593Smuzhiyun 		return ROSE_DATA;
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	return ROSE_ILLEGAL;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
rose_parse_national(unsigned char * p,struct rose_facilities_struct * facilities,int len)239*4882a593Smuzhiyun static int rose_parse_national(unsigned char *p, struct rose_facilities_struct *facilities, int len)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	unsigned char *pt;
242*4882a593Smuzhiyun 	unsigned char l, lg, n = 0;
243*4882a593Smuzhiyun 	int fac_national_digis_received = 0;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	do {
246*4882a593Smuzhiyun 		switch (*p & 0xC0) {
247*4882a593Smuzhiyun 		case 0x00:
248*4882a593Smuzhiyun 			if (len < 2)
249*4882a593Smuzhiyun 				return -1;
250*4882a593Smuzhiyun 			p   += 2;
251*4882a593Smuzhiyun 			n   += 2;
252*4882a593Smuzhiyun 			len -= 2;
253*4882a593Smuzhiyun 			break;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 		case 0x40:
256*4882a593Smuzhiyun 			if (len < 3)
257*4882a593Smuzhiyun 				return -1;
258*4882a593Smuzhiyun 			if (*p == FAC_NATIONAL_RAND)
259*4882a593Smuzhiyun 				facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF);
260*4882a593Smuzhiyun 			p   += 3;
261*4882a593Smuzhiyun 			n   += 3;
262*4882a593Smuzhiyun 			len -= 3;
263*4882a593Smuzhiyun 			break;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 		case 0x80:
266*4882a593Smuzhiyun 			if (len < 4)
267*4882a593Smuzhiyun 				return -1;
268*4882a593Smuzhiyun 			p   += 4;
269*4882a593Smuzhiyun 			n   += 4;
270*4882a593Smuzhiyun 			len -= 4;
271*4882a593Smuzhiyun 			break;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 		case 0xC0:
274*4882a593Smuzhiyun 			if (len < 2)
275*4882a593Smuzhiyun 				return -1;
276*4882a593Smuzhiyun 			l = p[1];
277*4882a593Smuzhiyun 			if (len < 2 + l)
278*4882a593Smuzhiyun 				return -1;
279*4882a593Smuzhiyun 			if (*p == FAC_NATIONAL_DEST_DIGI) {
280*4882a593Smuzhiyun 				if (!fac_national_digis_received) {
281*4882a593Smuzhiyun 					if (l < AX25_ADDR_LEN)
282*4882a593Smuzhiyun 						return -1;
283*4882a593Smuzhiyun 					memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN);
284*4882a593Smuzhiyun 					facilities->source_ndigis = 1;
285*4882a593Smuzhiyun 				}
286*4882a593Smuzhiyun 			}
287*4882a593Smuzhiyun 			else if (*p == FAC_NATIONAL_SRC_DIGI) {
288*4882a593Smuzhiyun 				if (!fac_national_digis_received) {
289*4882a593Smuzhiyun 					if (l < AX25_ADDR_LEN)
290*4882a593Smuzhiyun 						return -1;
291*4882a593Smuzhiyun 					memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN);
292*4882a593Smuzhiyun 					facilities->dest_ndigis = 1;
293*4882a593Smuzhiyun 				}
294*4882a593Smuzhiyun 			}
295*4882a593Smuzhiyun 			else if (*p == FAC_NATIONAL_FAIL_CALL) {
296*4882a593Smuzhiyun 				if (l < AX25_ADDR_LEN)
297*4882a593Smuzhiyun 					return -1;
298*4882a593Smuzhiyun 				memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN);
299*4882a593Smuzhiyun 			}
300*4882a593Smuzhiyun 			else if (*p == FAC_NATIONAL_FAIL_ADD) {
301*4882a593Smuzhiyun 				if (l < 1 + ROSE_ADDR_LEN)
302*4882a593Smuzhiyun 					return -1;
303*4882a593Smuzhiyun 				memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN);
304*4882a593Smuzhiyun 			}
305*4882a593Smuzhiyun 			else if (*p == FAC_NATIONAL_DIGIS) {
306*4882a593Smuzhiyun 				if (l % AX25_ADDR_LEN)
307*4882a593Smuzhiyun 					return -1;
308*4882a593Smuzhiyun 				fac_national_digis_received = 1;
309*4882a593Smuzhiyun 				facilities->source_ndigis = 0;
310*4882a593Smuzhiyun 				facilities->dest_ndigis   = 0;
311*4882a593Smuzhiyun 				for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) {
312*4882a593Smuzhiyun 					if (pt[6] & AX25_HBIT) {
313*4882a593Smuzhiyun 						if (facilities->dest_ndigis >= ROSE_MAX_DIGIS)
314*4882a593Smuzhiyun 							return -1;
315*4882a593Smuzhiyun 						memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN);
316*4882a593Smuzhiyun 					} else {
317*4882a593Smuzhiyun 						if (facilities->source_ndigis >= ROSE_MAX_DIGIS)
318*4882a593Smuzhiyun 							return -1;
319*4882a593Smuzhiyun 						memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN);
320*4882a593Smuzhiyun 					}
321*4882a593Smuzhiyun 				}
322*4882a593Smuzhiyun 			}
323*4882a593Smuzhiyun 			p   += l + 2;
324*4882a593Smuzhiyun 			n   += l + 2;
325*4882a593Smuzhiyun 			len -= l + 2;
326*4882a593Smuzhiyun 			break;
327*4882a593Smuzhiyun 		}
328*4882a593Smuzhiyun 	} while (*p != 0x00 && len > 0);
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	return n;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun 
rose_parse_ccitt(unsigned char * p,struct rose_facilities_struct * facilities,int len)333*4882a593Smuzhiyun static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *facilities, int len)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun 	unsigned char l, n = 0;
336*4882a593Smuzhiyun 	char callsign[11];
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	do {
339*4882a593Smuzhiyun 		switch (*p & 0xC0) {
340*4882a593Smuzhiyun 		case 0x00:
341*4882a593Smuzhiyun 			if (len < 2)
342*4882a593Smuzhiyun 				return -1;
343*4882a593Smuzhiyun 			p   += 2;
344*4882a593Smuzhiyun 			n   += 2;
345*4882a593Smuzhiyun 			len -= 2;
346*4882a593Smuzhiyun 			break;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 		case 0x40:
349*4882a593Smuzhiyun 			if (len < 3)
350*4882a593Smuzhiyun 				return -1;
351*4882a593Smuzhiyun 			p   += 3;
352*4882a593Smuzhiyun 			n   += 3;
353*4882a593Smuzhiyun 			len -= 3;
354*4882a593Smuzhiyun 			break;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 		case 0x80:
357*4882a593Smuzhiyun 			if (len < 4)
358*4882a593Smuzhiyun 				return -1;
359*4882a593Smuzhiyun 			p   += 4;
360*4882a593Smuzhiyun 			n   += 4;
361*4882a593Smuzhiyun 			len -= 4;
362*4882a593Smuzhiyun 			break;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 		case 0xC0:
365*4882a593Smuzhiyun 			if (len < 2)
366*4882a593Smuzhiyun 				return -1;
367*4882a593Smuzhiyun 			l = p[1];
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 			/* Prevent overflows*/
370*4882a593Smuzhiyun 			if (l < 10 || l > 20)
371*4882a593Smuzhiyun 				return -1;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 			if (*p == FAC_CCITT_DEST_NSAP) {
374*4882a593Smuzhiyun 				memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
375*4882a593Smuzhiyun 				memcpy(callsign, p + 12,   l - 10);
376*4882a593Smuzhiyun 				callsign[l - 10] = '\0';
377*4882a593Smuzhiyun 				asc2ax(&facilities->source_call, callsign);
378*4882a593Smuzhiyun 			}
379*4882a593Smuzhiyun 			if (*p == FAC_CCITT_SRC_NSAP) {
380*4882a593Smuzhiyun 				memcpy(&facilities->dest_addr, p + 7, ROSE_ADDR_LEN);
381*4882a593Smuzhiyun 				memcpy(callsign, p + 12, l - 10);
382*4882a593Smuzhiyun 				callsign[l - 10] = '\0';
383*4882a593Smuzhiyun 				asc2ax(&facilities->dest_call, callsign);
384*4882a593Smuzhiyun 			}
385*4882a593Smuzhiyun 			p   += l + 2;
386*4882a593Smuzhiyun 			n   += l + 2;
387*4882a593Smuzhiyun 			len -= l + 2;
388*4882a593Smuzhiyun 			break;
389*4882a593Smuzhiyun 		}
390*4882a593Smuzhiyun 	} while (*p != 0x00 && len > 0);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	return n;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
rose_parse_facilities(unsigned char * p,unsigned packet_len,struct rose_facilities_struct * facilities)395*4882a593Smuzhiyun int rose_parse_facilities(unsigned char *p, unsigned packet_len,
396*4882a593Smuzhiyun 	struct rose_facilities_struct *facilities)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun 	int facilities_len, len;
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	facilities_len = *p++;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	if (facilities_len == 0 || (unsigned int)facilities_len > packet_len)
403*4882a593Smuzhiyun 		return 0;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	while (facilities_len >= 3 && *p == 0x00) {
406*4882a593Smuzhiyun 		facilities_len--;
407*4882a593Smuzhiyun 		p++;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 		switch (*p) {
410*4882a593Smuzhiyun 		case FAC_NATIONAL:		/* National */
411*4882a593Smuzhiyun 			len = rose_parse_national(p + 1, facilities, facilities_len - 1);
412*4882a593Smuzhiyun 			break;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 		case FAC_CCITT:		/* CCITT */
415*4882a593Smuzhiyun 			len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
416*4882a593Smuzhiyun 			break;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 		default:
419*4882a593Smuzhiyun 			printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p);
420*4882a593Smuzhiyun 			len = 1;
421*4882a593Smuzhiyun 			break;
422*4882a593Smuzhiyun 		}
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 		if (len < 0)
425*4882a593Smuzhiyun 			return 0;
426*4882a593Smuzhiyun 		if (WARN_ON(len >= facilities_len))
427*4882a593Smuzhiyun 			return 0;
428*4882a593Smuzhiyun 		facilities_len -= len + 1;
429*4882a593Smuzhiyun 		p += len + 1;
430*4882a593Smuzhiyun 	}
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	return facilities_len == 0;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
rose_create_facilities(unsigned char * buffer,struct rose_sock * rose)435*4882a593Smuzhiyun static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun 	unsigned char *p = buffer + 1;
438*4882a593Smuzhiyun 	char *callsign;
439*4882a593Smuzhiyun 	char buf[11];
440*4882a593Smuzhiyun 	int len, nb;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	/* National Facilities */
443*4882a593Smuzhiyun 	if (rose->rand != 0 || rose->source_ndigis == 1 || rose->dest_ndigis == 1) {
444*4882a593Smuzhiyun 		*p++ = 0x00;
445*4882a593Smuzhiyun 		*p++ = FAC_NATIONAL;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 		if (rose->rand != 0) {
448*4882a593Smuzhiyun 			*p++ = FAC_NATIONAL_RAND;
449*4882a593Smuzhiyun 			*p++ = (rose->rand >> 8) & 0xFF;
450*4882a593Smuzhiyun 			*p++ = (rose->rand >> 0) & 0xFF;
451*4882a593Smuzhiyun 		}
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 		/* Sent before older facilities */
454*4882a593Smuzhiyun 		if ((rose->source_ndigis > 0) || (rose->dest_ndigis > 0)) {
455*4882a593Smuzhiyun 			int maxdigi = 0;
456*4882a593Smuzhiyun 			*p++ = FAC_NATIONAL_DIGIS;
457*4882a593Smuzhiyun 			*p++ = AX25_ADDR_LEN * (rose->source_ndigis + rose->dest_ndigis);
458*4882a593Smuzhiyun 			for (nb = 0 ; nb < rose->source_ndigis ; nb++) {
459*4882a593Smuzhiyun 				if (++maxdigi >= ROSE_MAX_DIGIS)
460*4882a593Smuzhiyun 					break;
461*4882a593Smuzhiyun 				memcpy(p, &rose->source_digis[nb], AX25_ADDR_LEN);
462*4882a593Smuzhiyun 				p[6] |= AX25_HBIT;
463*4882a593Smuzhiyun 				p += AX25_ADDR_LEN;
464*4882a593Smuzhiyun 			}
465*4882a593Smuzhiyun 			for (nb = 0 ; nb < rose->dest_ndigis ; nb++) {
466*4882a593Smuzhiyun 				if (++maxdigi >= ROSE_MAX_DIGIS)
467*4882a593Smuzhiyun 					break;
468*4882a593Smuzhiyun 				memcpy(p, &rose->dest_digis[nb], AX25_ADDR_LEN);
469*4882a593Smuzhiyun 				p[6] &= ~AX25_HBIT;
470*4882a593Smuzhiyun 				p += AX25_ADDR_LEN;
471*4882a593Smuzhiyun 			}
472*4882a593Smuzhiyun 		}
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 		/* For compatibility */
475*4882a593Smuzhiyun 		if (rose->source_ndigis > 0) {
476*4882a593Smuzhiyun 			*p++ = FAC_NATIONAL_SRC_DIGI;
477*4882a593Smuzhiyun 			*p++ = AX25_ADDR_LEN;
478*4882a593Smuzhiyun 			memcpy(p, &rose->source_digis[0], AX25_ADDR_LEN);
479*4882a593Smuzhiyun 			p   += AX25_ADDR_LEN;
480*4882a593Smuzhiyun 		}
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 		/* For compatibility */
483*4882a593Smuzhiyun 		if (rose->dest_ndigis > 0) {
484*4882a593Smuzhiyun 			*p++ = FAC_NATIONAL_DEST_DIGI;
485*4882a593Smuzhiyun 			*p++ = AX25_ADDR_LEN;
486*4882a593Smuzhiyun 			memcpy(p, &rose->dest_digis[0], AX25_ADDR_LEN);
487*4882a593Smuzhiyun 			p   += AX25_ADDR_LEN;
488*4882a593Smuzhiyun 		}
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	*p++ = 0x00;
492*4882a593Smuzhiyun 	*p++ = FAC_CCITT;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	*p++ = FAC_CCITT_DEST_NSAP;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	callsign = ax2asc(buf, &rose->dest_call);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	*p++ = strlen(callsign) + 10;
499*4882a593Smuzhiyun 	*p++ = (strlen(callsign) + 9) * 2;		/* ??? */
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	*p++ = 0x47; *p++ = 0x00; *p++ = 0x11;
502*4882a593Smuzhiyun 	*p++ = ROSE_ADDR_LEN * 2;
503*4882a593Smuzhiyun 	memcpy(p, &rose->dest_addr, ROSE_ADDR_LEN);
504*4882a593Smuzhiyun 	p   += ROSE_ADDR_LEN;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	memcpy(p, callsign, strlen(callsign));
507*4882a593Smuzhiyun 	p   += strlen(callsign);
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	*p++ = FAC_CCITT_SRC_NSAP;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	callsign = ax2asc(buf, &rose->source_call);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	*p++ = strlen(callsign) + 10;
514*4882a593Smuzhiyun 	*p++ = (strlen(callsign) + 9) * 2;		/* ??? */
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	*p++ = 0x47; *p++ = 0x00; *p++ = 0x11;
517*4882a593Smuzhiyun 	*p++ = ROSE_ADDR_LEN * 2;
518*4882a593Smuzhiyun 	memcpy(p, &rose->source_addr, ROSE_ADDR_LEN);
519*4882a593Smuzhiyun 	p   += ROSE_ADDR_LEN;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	memcpy(p, callsign, strlen(callsign));
522*4882a593Smuzhiyun 	p   += strlen(callsign);
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	len       = p - buffer;
525*4882a593Smuzhiyun 	buffer[0] = len - 1;
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	return len;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun 
rose_disconnect(struct sock * sk,int reason,int cause,int diagnostic)530*4882a593Smuzhiyun void rose_disconnect(struct sock *sk, int reason, int cause, int diagnostic)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun 	struct rose_sock *rose = rose_sk(sk);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	rose_stop_timer(sk);
535*4882a593Smuzhiyun 	rose_stop_idletimer(sk);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	rose_clear_queues(sk);
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	rose->lci   = 0;
540*4882a593Smuzhiyun 	rose->state = ROSE_STATE_0;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	if (cause != -1)
543*4882a593Smuzhiyun 		rose->cause = cause;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	if (diagnostic != -1)
546*4882a593Smuzhiyun 		rose->diagnostic = diagnostic;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	sk->sk_state     = TCP_CLOSE;
549*4882a593Smuzhiyun 	sk->sk_err       = reason;
550*4882a593Smuzhiyun 	sk->sk_shutdown |= SEND_SHUTDOWN;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	if (!sock_flag(sk, SOCK_DEAD)) {
553*4882a593Smuzhiyun 		sk->sk_state_change(sk);
554*4882a593Smuzhiyun 		sock_set_flag(sk, SOCK_DEAD);
555*4882a593Smuzhiyun 	}
556*4882a593Smuzhiyun }
557