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