4 * This code REQUIRES 2.1.15 or higher/ NET3.038
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.
13 * ROSE 001 Jonathan(G4KLX) Cloned from nr_subr.c
16 #include <linux/config.h>
17 #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
18 #include <linux/errno.h>
19 #include <linux/types.h>
20 #include <linux/socket.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>
29 #include <linux/inet.h>
30 #include <linux/netdevice.h>
31 #include <linux/skbuff.h>
33 #include <asm/segment.h>
34 #include <asm/system.h>
35 #include <linux/fcntl.h>
37 #include <linux/interrupt.h>
41 * This routine purges all of the queues of frames.
43 void rose_clear_queues(struct sock
*sk
)
47 while ((skb
= skb_dequeue(&sk
->write_queue
)) != NULL
)
48 kfree_skb(skb
, FREE_WRITE
);
50 while ((skb
= skb_dequeue(&sk
->protinfo
.rose
->frag_queue
)) != NULL
)
51 kfree_skb(skb
, FREE_READ
);
55 * Validate that the value of nr is between va and vs. Return true or
58 int rose_validate_nr(struct sock
*sk
, unsigned short nr
)
60 unsigned short vc
= sk
->protinfo
.rose
->va
;
62 while (vc
!= sk
->protinfo
.rose
->vs
) {
63 if (nr
== vc
) return 1;
64 vc
= (vc
+ 1) % ROSE_MODULUS
;
67 if (nr
== sk
->protinfo
.rose
->vs
) return 1;
73 * This routine is called when the packet layer internally generates a
76 void rose_write_internal(struct sock
*sk
, int frametype
)
80 unsigned char lci1
, lci2
;
84 len
= AX25_BPQ_HEADER_LEN
+ AX25_MAX_HEADER_LEN
+ ROSE_MIN_LEN
+ 1;
87 case ROSE_CALL_REQUEST
:
88 len
+= 1 + ROSE_ADDR_LEN
+ ROSE_ADDR_LEN
;
89 faclen
= rose_create_facilities(buffer
, sk
->protinfo
.rose
);
92 case ROSE_CALL_ACCEPTED
:
93 case ROSE_CLEAR_REQUEST
:
94 case ROSE_RESET_REQUEST
:
103 if ((skb
= alloc_skb(len
, GFP_ATOMIC
)) == NULL
)
107 * Space for AX.25 header and PID.
109 skb_reserve(skb
, AX25_BPQ_HEADER_LEN
+ AX25_MAX_HEADER_LEN
+ 1);
111 dptr
= skb_put(skb
, skb_tailroom(skb
));
113 lci1
= (sk
->protinfo
.rose
->lci
>> 8) & 0x0F;
114 lci2
= (sk
->protinfo
.rose
->lci
>> 0) & 0xFF;
118 case ROSE_CALL_REQUEST
:
119 *dptr
++ = ROSE_GFI
| lci1
;
123 memcpy(dptr
, &sk
->protinfo
.rose
->dest_addr
, ROSE_ADDR_LEN
);
124 dptr
+= ROSE_ADDR_LEN
;
125 memcpy(dptr
, &sk
->protinfo
.rose
->source_addr
, ROSE_ADDR_LEN
);
126 dptr
+= ROSE_ADDR_LEN
;
127 memcpy(dptr
, buffer
, faclen
);
131 case ROSE_CALL_ACCEPTED
:
132 *dptr
++ = ROSE_GFI
| lci1
;
135 *dptr
++ = 0x00; /* Address length */
136 *dptr
++ = 0; /* Facilities length */
139 case ROSE_CLEAR_REQUEST
:
140 case ROSE_RESET_REQUEST
:
141 *dptr
++ = ROSE_GFI
| lci1
;
144 *dptr
++ = 0x00; /* XXX */
145 *dptr
++ = 0x00; /* XXX */
149 *dptr
++ = ROSE_GFI
| lci1
;
152 *dptr
++ = 0x00; /* XXX */
158 *dptr
++ = ROSE_GFI
| lci1
;
161 *dptr
++ |= (sk
->protinfo
.rose
->vr
<< 5) & 0xE0;
164 case ROSE_CLEAR_CONFIRMATION
:
165 case ROSE_INTERRUPT_CONFIRMATION
:
166 case ROSE_RESET_CONFIRMATION
:
167 *dptr
++ = ROSE_GFI
| lci1
;
173 printk(KERN_ERR
"ROSE: rose_write_internal - invalid frametype %02X\n", frametype
);
174 kfree_skb(skb
, FREE_WRITE
);
178 rose_transmit_link(skb
, sk
->protinfo
.rose
->neighbour
);
181 int rose_decode(struct sk_buff
*skb
, int *ns
, int *nr
, int *q
, int *d
, int *m
)
183 unsigned char *frame
;
187 *ns
= *nr
= *q
= *d
= *m
= 0;
190 case ROSE_CALL_REQUEST
:
191 case ROSE_CALL_ACCEPTED
:
192 case ROSE_CLEAR_REQUEST
:
193 case ROSE_CLEAR_CONFIRMATION
:
195 case ROSE_INTERRUPT_CONFIRMATION
:
196 case ROSE_RESET_REQUEST
:
197 case ROSE_RESET_CONFIRMATION
:
198 case ROSE_RESTART_REQUEST
:
199 case ROSE_RESTART_CONFIRMATION
:
200 case ROSE_REGISTRATION_REQUEST
:
201 case ROSE_REGISTRATION_CONFIRMATION
:
202 case ROSE_DIAGNOSTIC
:
208 if ((frame
[2] & 0x1F) == ROSE_RR
||
209 (frame
[2] & 0x1F) == ROSE_RNR
||
210 (frame
[2] & 0x1F) == ROSE_REJ
) {
211 *nr
= (frame
[2] >> 5) & 0x07;
212 return frame
[2] & 0x1F;
215 if ((frame
[2] & 0x01) == ROSE_DATA
) {
216 *q
= (frame
[0] & ROSE_Q_BIT
) == ROSE_Q_BIT
;
217 *d
= (frame
[0] & ROSE_D_BIT
) == ROSE_D_BIT
;
218 *m
= (frame
[2] & ROSE_M_BIT
) == ROSE_M_BIT
;
219 *nr
= (frame
[2] >> 5) & 0x07;
220 *ns
= (frame
[2] >> 1) & 0x07;
227 static int rose_parse_national(unsigned char *p
, struct rose_facilities
*facilities
, int len
)
229 unsigned char l
, n
= 0;
240 if (*p
== FAC_NATIONAL_RAND
)
241 facilities
->rand
= ((p
[1] << 8) & 0xFF00) + ((p
[2] << 0) & 0x00FF);
255 if (*p
== FAC_NATIONAL_DEST_DIGI
) {
256 memcpy(&facilities
->source_digi
, p
+ 2, AX25_ADDR_LEN
);
257 facilities
->source_ndigis
= 1;
259 if (*p
== FAC_NATIONAL_SRC_DIGI
) {
260 memcpy(&facilities
->dest_digi
, p
+ 2, AX25_ADDR_LEN
);
261 facilities
->dest_ndigis
= 1;
268 } while (*p
!= 0x00 && len
> 0);
273 static int rose_parse_ccitt(unsigned char *p
, struct rose_facilities
*facilities
, int len
)
275 unsigned char l
, n
= 0;
300 if (*p
== FAC_CCITT_DEST_NSAP
) {
301 memcpy(&facilities
->source_addr
, p
+ 7, ROSE_ADDR_LEN
);
302 memcpy(callsign
, p
+ 12, l
- 10);
303 callsign
[l
- 10] = '\0';
304 facilities
->source_call
= *asc2ax(callsign
);
306 if (*p
== FAC_CCITT_SRC_NSAP
) {
307 memcpy(&facilities
->dest_addr
, p
+ 7, ROSE_ADDR_LEN
);
308 memcpy(callsign
, p
+ 12, l
- 10);
309 callsign
[l
- 10] = '\0';
310 facilities
->dest_call
= *asc2ax(callsign
);
317 } while (*p
!= 0x00 && len
> 0);
322 int rose_parse_facilities(struct sk_buff
*skb
, struct rose_facilities
*facilities
)
324 int facilities_len
, len
;
327 memset(facilities
, 0x00, sizeof(struct rose_facilities
));
329 len
= (((skb
->data
[3] >> 4) & 0x0F) + 1) / 2;
330 len
+= (((skb
->data
[3] >> 0) & 0x0F) + 1) / 2;
332 p
= skb
->data
+ len
+ 4;
334 facilities_len
= *p
++;
336 if (facilities_len
== 0)
339 while (facilities_len
> 0) {
345 case FAC_NATIONAL
: /* National */
346 len
= rose_parse_national(p
+ 1, facilities
, facilities_len
- 1);
347 facilities_len
-= len
+ 1;
351 case FAC_CCITT
: /* CCITT */
352 len
= rose_parse_ccitt(p
+ 1, facilities
, facilities_len
- 1);
353 facilities_len
-= len
+ 1;
358 printk(KERN_DEBUG
"ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p
);
369 int rose_create_facilities(unsigned char *buffer
, rose_cb
*rose
)
371 unsigned char *p
= buffer
+ 1;
375 /* National Facilities */
376 if (rose
->rand
!= 0 || rose
->source_ndigis
== 1 || rose
->dest_ndigis
== 1) {
380 if (rose
->rand
!= 0) {
381 *p
++ = FAC_NATIONAL_RAND
;
382 *p
++ = (rose
->rand
>> 8) & 0xFF;
383 *p
++ = (rose
->rand
>> 0) & 0xFF;
386 if (rose
->source_ndigis
== 1) {
387 *p
++ = FAC_NATIONAL_SRC_DIGI
;
388 *p
++ = AX25_ADDR_LEN
;
389 memcpy(p
, &rose
->source_digi
, AX25_ADDR_LEN
);
393 if (rose
->dest_ndigis
== 1) {
394 *p
++ = FAC_NATIONAL_DEST_DIGI
;
395 *p
++ = AX25_ADDR_LEN
;
396 memcpy(p
, &rose
->dest_digi
, AX25_ADDR_LEN
);
404 *p
++ = FAC_CCITT_DEST_NSAP
;
406 callsign
= ax2asc(&rose
->dest_call
);
408 *p
++ = strlen(callsign
) + 10;
409 *p
++ = (strlen(callsign
) + 9) * 2; /* ??? */
411 *p
++ = 0x47; *p
++ = 0x00; *p
++ = 0x11;
412 *p
++ = ROSE_ADDR_LEN
* 2;
413 memcpy(p
, &rose
->dest_addr
, ROSE_ADDR_LEN
);
416 memcpy(p
, callsign
, strlen(callsign
));
417 p
+= strlen(callsign
);
419 *p
++ = FAC_CCITT_SRC_NSAP
;
421 callsign
= ax2asc(&rose
->source_call
);
423 *p
++ = strlen(callsign
) + 10;
424 *p
++ = (strlen(callsign
) + 9) * 2; /* ??? */
426 *p
++ = 0x47; *p
++ = 0x00; *p
++ = 0x11;
427 *p
++ = ROSE_ADDR_LEN
* 2;
428 memcpy(p
, &rose
->source_addr
, ROSE_ADDR_LEN
);
431 memcpy(p
, callsign
, strlen(callsign
));
432 p
+= strlen(callsign
);