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 * LAPB 001 Jonathan Naylor Started Coding
14 * LAPB 002 Jonathan Naylor New timer architecture.
17 #include <linux/config.h>
18 #if defined(CONFIG_LAPB) || defined(CONFIG_LAPB_MODULE)
19 #include <linux/module.h>
20 #include <linux/errno.h>
21 #include <linux/types.h>
22 #include <linux/socket.h>
24 #include <linux/kernel.h>
25 #include <linux/sched.h>
26 #include <linux/timer.h>
27 #include <linux/string.h>
28 #include <linux/sockios.h>
29 #include <linux/net.h>
30 #include <linux/inet.h>
31 #include <linux/if_arp.h>
32 #include <linux/skbuff.h>
34 #include <asm/uaccess.h>
35 #include <asm/system.h>
36 #include <linux/fcntl.h>
38 #include <linux/interrupt.h>
39 #include <linux/stat.h>
40 #include <linux/init.h>
43 static lapb_cb
*volatile lapb_list
= NULL
;
46 * Free an allocated lapb control block. This is done to centralise
49 static void lapb_free_cb(lapb_cb
*lapb
)
57 * Socket removal during an interrupt is now safe.
59 static void lapb_remove_cb(lapb_cb
*lapb
)
64 save_flags(flags
); cli();
66 if ((s
= lapb_list
) == lapb
) {
72 while (s
!= NULL
&& s
->next
!= NULL
) {
73 if (s
->next
== lapb
) {
86 * Add a socket to the bound sockets list.
88 static void lapb_insert_cb(lapb_cb
*lapb
)
92 save_flags(flags
); cli();
94 lapb
->next
= lapb_list
;
101 * Convert the integer token used by the device driver into a pointer
102 * to a LAPB control structure.
104 static lapb_cb
*lapb_tokentostruct(void *token
)
108 for (lapb
= lapb_list
; lapb
!= NULL
; lapb
= lapb
->next
)
109 if (lapb
->token
== token
)
116 * Create an empty LAPB control block.
118 static lapb_cb
*lapb_create_cb(void)
122 if ((lapb
= kmalloc(sizeof(*lapb
), GFP_ATOMIC
)) == NULL
)
127 memset(lapb
, 0x00, sizeof(*lapb
));
129 skb_queue_head_init(&lapb
->write_queue
);
130 skb_queue_head_init(&lapb
->ack_queue
);
132 init_timer(&lapb
->t1timer
);
133 init_timer(&lapb
->t2timer
);
135 lapb
->t1
= LAPB_DEFAULT_T1
;
136 lapb
->t2
= LAPB_DEFAULT_T2
;
137 lapb
->n2
= LAPB_DEFAULT_N2
;
138 lapb
->mode
= LAPB_DEFAULT_MODE
;
139 lapb
->window
= LAPB_DEFAULT_WINDOW
;
140 lapb
->state
= LAPB_STATE_0
;
145 int lapb_register(void *token
, struct lapb_register_struct
*callbacks
)
149 if (lapb_tokentostruct(token
) != NULL
)
150 return LAPB_BADTOKEN
;
152 if ((lapb
= lapb_create_cb()) == NULL
)
156 lapb
->callbacks
= *callbacks
;
158 lapb_insert_cb(lapb
);
160 lapb_start_t1timer(lapb
);
165 int lapb_unregister(void *token
)
169 if ((lapb
= lapb_tokentostruct(token
)) == NULL
)
170 return LAPB_BADTOKEN
;
172 lapb_stop_t1timer(lapb
);
173 lapb_stop_t2timer(lapb
);
175 lapb_clear_queues(lapb
);
177 lapb_remove_cb(lapb
);
184 int lapb_getparms(void *token
, struct lapb_parms_struct
*parms
)
188 if ((lapb
= lapb_tokentostruct(token
)) == NULL
)
189 return LAPB_BADTOKEN
;
191 parms
->t1
= lapb
->t1
/ HZ
;
192 parms
->t2
= lapb
->t2
/ HZ
;
193 parms
->n2
= lapb
->n2
;
194 parms
->n2count
= lapb
->n2count
;
195 parms
->state
= lapb
->state
;
196 parms
->window
= lapb
->window
;
197 parms
->mode
= lapb
->mode
;
199 if (lapb
->t1timer
.prev
== NULL
&& lapb
->t1timer
.next
== NULL
)
202 parms
->t1timer
= (lapb
->t1timer
.expires
- jiffies
) / HZ
;
204 if (lapb
->t2timer
.prev
== NULL
&& lapb
->t2timer
.next
== NULL
)
207 parms
->t2timer
= (lapb
->t2timer
.expires
- jiffies
) / HZ
;
212 int lapb_setparms(void *token
, struct lapb_parms_struct
*parms
)
216 if ((lapb
= lapb_tokentostruct(token
)) == NULL
)
217 return LAPB_BADTOKEN
;
228 if (lapb
->state
== LAPB_STATE_0
) {
229 if (parms
->mode
& LAPB_EXTENDED
) {
230 if (parms
->window
< 1 || parms
->window
> 127)
233 if (parms
->window
< 1 || parms
->window
> 7)
237 lapb
->mode
= parms
->mode
;
238 lapb
->window
= parms
->window
;
241 lapb
->t1
= parms
->t1
* HZ
;
242 lapb
->t2
= parms
->t2
* HZ
;
243 lapb
->n2
= parms
->n2
;
248 int lapb_connect_request(void *token
)
252 if ((lapb
= lapb_tokentostruct(token
)) == NULL
)
253 return LAPB_BADTOKEN
;
255 switch (lapb
->state
) {
260 return LAPB_CONNECTED
;
263 lapb_establish_data_link(lapb
);
266 printk(KERN_DEBUG
"lapb: (%p) S0 -> S1\n", lapb
->token
);
269 lapb
->state
= LAPB_STATE_1
;
274 int lapb_disconnect_request(void *token
)
278 if ((lapb
= lapb_tokentostruct(token
)) == NULL
)
279 return LAPB_BADTOKEN
;
281 switch (lapb
->state
) {
283 return LAPB_NOTCONNECTED
;
287 printk(KERN_DEBUG
"lapb: (%p) S1 TX DISC(1)\n", lapb
->token
);
290 printk(KERN_DEBUG
"lapb: (%p) S1 -> S0\n", lapb
->token
);
292 lapb_send_control(lapb
, LAPB_DISC
, LAPB_POLLON
, LAPB_COMMAND
);
293 lapb
->state
= LAPB_STATE_0
;
294 lapb_start_t1timer(lapb
);
295 return LAPB_NOTCONNECTED
;
301 lapb_clear_queues(lapb
);
303 lapb_send_control(lapb
, LAPB_DISC
, LAPB_POLLON
, LAPB_COMMAND
);
304 lapb_start_t1timer(lapb
);
305 lapb_stop_t2timer(lapb
);
306 lapb
->state
= LAPB_STATE_2
;
309 printk(KERN_DEBUG
"lapb: (%p) S3 DISC(1)\n", lapb
->token
);
312 printk(KERN_DEBUG
"lapb: (%p) S3 -> S2\n", lapb
->token
);
318 int lapb_data_request(void *token
, struct sk_buff
*skb
)
322 if ((lapb
= lapb_tokentostruct(token
)) == NULL
)
323 return LAPB_BADTOKEN
;
325 if (lapb
->state
!= LAPB_STATE_3
&& lapb
->state
!= LAPB_STATE_4
)
326 return LAPB_NOTCONNECTED
;
328 skb_queue_tail(&lapb
->write_queue
, skb
);
335 int lapb_data_received(void *token
, struct sk_buff
*skb
)
339 if ((lapb
= lapb_tokentostruct(token
)) == NULL
)
340 return LAPB_BADTOKEN
;
342 lapb_data_input(lapb
, skb
);
347 void lapb_connect_confirmation(lapb_cb
*lapb
, int reason
)
349 if (lapb
->callbacks
.connect_confirmation
!= NULL
)
350 (lapb
->callbacks
.connect_confirmation
)(lapb
->token
, reason
);
353 void lapb_connect_indication(lapb_cb
*lapb
, int reason
)
355 if (lapb
->callbacks
.connect_indication
!= NULL
)
356 (lapb
->callbacks
.connect_indication
)(lapb
->token
, reason
);
359 void lapb_disconnect_confirmation(lapb_cb
*lapb
, int reason
)
361 if (lapb
->callbacks
.disconnect_confirmation
!= NULL
)
362 (lapb
->callbacks
.disconnect_confirmation
)(lapb
->token
, reason
);
365 void lapb_disconnect_indication(lapb_cb
*lapb
, int reason
)
367 if (lapb
->callbacks
.disconnect_indication
!= NULL
)
368 (lapb
->callbacks
.disconnect_indication
)(lapb
->token
, reason
);
371 int lapb_data_indication(lapb_cb
*lapb
, struct sk_buff
*skb
)
375 if (lapb
->callbacks
.data_indication
!= NULL
) {
376 (lapb
->callbacks
.data_indication
)(lapb
->token
, skb
);
383 int lapb_data_transmit(lapb_cb
*lapb
, struct sk_buff
*skb
)
387 if (lapb
->callbacks
.data_transmit
!= NULL
) {
388 (lapb
->callbacks
.data_transmit
)(lapb
->token
, skb
);
395 EXPORT_SYMBOL(lapb_register
);
396 EXPORT_SYMBOL(lapb_unregister
);
397 EXPORT_SYMBOL(lapb_getparms
);
398 EXPORT_SYMBOL(lapb_setparms
);
399 EXPORT_SYMBOL(lapb_connect_request
);
400 EXPORT_SYMBOL(lapb_disconnect_request
);
401 EXPORT_SYMBOL(lapb_data_request
);
402 EXPORT_SYMBOL(lapb_data_received
);
404 __initfunc(void lapb_proto_init(struct net_proto
*pro
))
406 printk(KERN_INFO
"NET4: LAPB for Linux. Version 0.01 for NET4.0\n");
410 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
411 MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
413 int init_module(void)
415 lapb_proto_init(NULL
);
420 void cleanup_module(void)