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