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