~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/lapb/lapb_iface.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *      LAPB release 002
  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  *      LAPB 001        Jonathan Naylor Started Coding
 14  *      LAPB 002        Jonathan Naylor New timer architecture.
 15  *      2000-10-29      Henner Eisen    lapb_data_indication() return status.
 16  */
 17  
 18 #include <linux/config.h>
 19 #if defined(CONFIG_LAPB) || defined(CONFIG_LAPB_MODULE)
 20 #include <linux/module.h>
 21 #include <linux/errno.h>
 22 #include <linux/types.h>
 23 #include <linux/socket.h>
 24 #include <linux/in.h>
 25 #include <linux/kernel.h>
 26 #include <linux/sched.h>
 27 #include <linux/timer.h>
 28 #include <linux/string.h>
 29 #include <linux/sockios.h>
 30 #include <linux/net.h>
 31 #include <linux/inet.h>
 32 #include <linux/if_arp.h>
 33 #include <linux/skbuff.h>
 34 #include <net/sock.h>
 35 #include <asm/uaccess.h>
 36 #include <asm/system.h>
 37 #include <linux/fcntl.h>
 38 #include <linux/mm.h>
 39 #include <linux/interrupt.h>
 40 #include <linux/stat.h>
 41 #include <linux/init.h>
 42 #include <net/lapb.h>
 43 
 44 static lapb_cb *volatile lapb_list = NULL;
 45 
 46 /*
 47  *      Free an allocated lapb control block. This is done to centralise
 48  *      the MOD count code.
 49  */
 50 static void lapb_free_cb(lapb_cb *lapb)
 51 {
 52         kfree(lapb);
 53 
 54         MOD_DEC_USE_COUNT;
 55 }
 56 
 57 /*
 58  *      Socket removal during an interrupt is now safe.
 59  */
 60 static void lapb_remove_cb(lapb_cb *lapb)
 61 {
 62         lapb_cb *s;
 63         unsigned long flags;
 64 
 65         save_flags(flags); cli();
 66 
 67         if ((s = lapb_list) == lapb) {
 68                 lapb_list = s->next;
 69                 restore_flags(flags);
 70                 return;
 71         }
 72 
 73         while (s != NULL && s->next != NULL) {
 74                 if (s->next == lapb) {
 75                         s->next = lapb->next;
 76                         restore_flags(flags);
 77                         return;
 78                 }
 79 
 80                 s = s->next;
 81         }
 82 
 83         restore_flags(flags);
 84 }
 85 
 86 /*
 87  *      Add a socket to the bound sockets list.
 88  */
 89 static void lapb_insert_cb(lapb_cb *lapb)
 90 {
 91         unsigned long flags;
 92 
 93         save_flags(flags); cli();
 94 
 95         lapb->next = lapb_list;
 96         lapb_list  = lapb;
 97 
 98         restore_flags(flags);
 99 }
100 
101 /*
102  *      Convert the integer token used by the device driver into a pointer
103  *      to a LAPB control structure.
104  */
105 static lapb_cb *lapb_tokentostruct(void *token)
106 {
107         lapb_cb *lapb;
108 
109         for (lapb = lapb_list; lapb != NULL; lapb = lapb->next)
110                 if (lapb->token == token)
111                         return lapb;
112 
113         return NULL;
114 }
115 
116 /*
117  *      Create an empty LAPB control block.
118  */
119 static lapb_cb *lapb_create_cb(void)
120 {
121         lapb_cb *lapb;
122 
123         if ((lapb = kmalloc(sizeof(*lapb), GFP_ATOMIC)) == NULL)
124                 return NULL;
125 
126         MOD_INC_USE_COUNT;
127 
128         memset(lapb, 0x00, sizeof(*lapb));
129 
130         skb_queue_head_init(&lapb->write_queue);
131         skb_queue_head_init(&lapb->ack_queue);
132 
133         init_timer(&lapb->t1timer);
134         init_timer(&lapb->t2timer);
135 
136         lapb->t1      = LAPB_DEFAULT_T1;
137         lapb->t2      = LAPB_DEFAULT_T2;
138         lapb->n2      = LAPB_DEFAULT_N2;
139         lapb->mode    = LAPB_DEFAULT_MODE;
140         lapb->window  = LAPB_DEFAULT_WINDOW;
141         lapb->state   = LAPB_STATE_0;
142 
143         return lapb;
144 }
145 
146 int lapb_register(void *token, struct lapb_register_struct *callbacks)
147 {
148         lapb_cb *lapb;
149 
150         if (lapb_tokentostruct(token) != NULL)
151                 return LAPB_BADTOKEN;
152 
153         if ((lapb = lapb_create_cb()) == NULL)
154                 return LAPB_NOMEM;
155 
156         lapb->token     = token;
157         lapb->callbacks = *callbacks;
158 
159         lapb_insert_cb(lapb);
160 
161         lapb_start_t1timer(lapb);
162 
163         return LAPB_OK;
164 }
165 
166 int lapb_unregister(void *token)
167 {
168         lapb_cb *lapb;
169 
170         if ((lapb = lapb_tokentostruct(token)) == NULL)
171                 return LAPB_BADTOKEN;
172 
173         lapb_stop_t1timer(lapb);
174         lapb_stop_t2timer(lapb);
175 
176         lapb_clear_queues(lapb);
177 
178         lapb_remove_cb(lapb);
179 
180         lapb_free_cb(lapb);
181 
182         return LAPB_OK;
183 }
184 
185 int lapb_getparms(void *token, struct lapb_parms_struct *parms)
186 {
187         lapb_cb *lapb;
188 
189         if ((lapb = lapb_tokentostruct(token)) == NULL)
190                 return LAPB_BADTOKEN;
191 
192         parms->t1      = lapb->t1 / HZ;
193         parms->t2      = lapb->t2 / HZ;
194         parms->n2      = lapb->n2;
195         parms->n2count = lapb->n2count;
196         parms->state   = lapb->state;
197         parms->window  = lapb->window;
198         parms->mode    = lapb->mode;
199 
200         if (!timer_pending(&lapb->t1timer))
201                 parms->t1timer = 0;
202         else
203                 parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
204 
205         if (!timer_pending(&lapb->t2timer))
206                 parms->t2timer = 0;
207         else
208                 parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
209 
210         return LAPB_OK;
211 }
212 
213 int lapb_setparms(void *token, struct lapb_parms_struct *parms)
214 {
215         lapb_cb *lapb;
216 
217         if ((lapb = lapb_tokentostruct(token)) == NULL)
218                 return LAPB_BADTOKEN;
219 
220         if (parms->t1 < 1)
221                 return LAPB_INVALUE;
222 
223         if (parms->t2 < 1)
224                 return LAPB_INVALUE;
225 
226         if (parms->n2 < 1)
227                 return LAPB_INVALUE;
228 
229         if (lapb->state == LAPB_STATE_0) {
230                 if (parms->mode & LAPB_EXTENDED) {
231                         if (parms->window < 1 || parms->window > 127)
232                                 return LAPB_INVALUE;
233                 } else {
234                         if (parms->window < 1 || parms->window > 7)
235                                 return LAPB_INVALUE;
236                 }
237 
238                 lapb->mode    = parms->mode;
239                 lapb->window  = parms->window;
240         }
241 
242         lapb->t1    = parms->t1 * HZ;
243         lapb->t2    = parms->t2 * HZ;
244         lapb->n2    = parms->n2;
245 
246         return LAPB_OK;
247 }
248 
249 int lapb_connect_request(void *token)
250 {
251         lapb_cb *lapb;
252 
253         if ((lapb = lapb_tokentostruct(token)) == NULL)
254                 return LAPB_BADTOKEN;
255 
256         switch (lapb->state) {
257                 case LAPB_STATE_1:
258                         return LAPB_OK;
259                 case LAPB_STATE_3:
260                 case LAPB_STATE_4:
261                         return LAPB_CONNECTED;
262         }
263 
264         lapb_establish_data_link(lapb);
265 
266 #if LAPB_DEBUG > 0
267         printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->token);
268 #endif
269 
270         lapb->state = LAPB_STATE_1;
271 
272         return LAPB_OK;
273 }
274         
275 int lapb_disconnect_request(void *token)
276 {
277         lapb_cb *lapb;
278 
279         if ((lapb = lapb_tokentostruct(token)) == NULL)
280                 return LAPB_BADTOKEN;
281 
282         switch (lapb->state) {
283                 case LAPB_STATE_0:
284                         return LAPB_NOTCONNECTED;
285 
286                 case LAPB_STATE_1:
287 #if LAPB_DEBUG > 1
288                         printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->token);
289 #endif
290 #if LAPB_DEBUG > 0
291                         printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
292 #endif
293                         lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
294                         lapb->state = LAPB_STATE_0;
295                         lapb_start_t1timer(lapb);
296                         return LAPB_NOTCONNECTED;
297 
298                 case LAPB_STATE_2:
299                         return LAPB_OK;
300         }
301 
302         lapb_clear_queues(lapb);
303         lapb->n2count = 0;
304         lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
305         lapb_start_t1timer(lapb);
306         lapb_stop_t2timer(lapb);
307         lapb->state = LAPB_STATE_2;
308 
309 #if LAPB_DEBUG > 1
310         printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->token);
311 #endif
312 #if LAPB_DEBUG > 0
313         printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->token);
314 #endif
315 
316         return LAPB_OK;
317 }
318 
319 int lapb_data_request(void *token, struct sk_buff *skb)
320 {
321         lapb_cb *lapb;
322 
323         if ((lapb = lapb_tokentostruct(token)) == NULL)
324                 return LAPB_BADTOKEN;
325 
326         if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4)
327                 return LAPB_NOTCONNECTED;
328 
329         skb_queue_tail(&lapb->write_queue, skb);
330 
331         lapb_kick(lapb);
332 
333         return LAPB_OK;
334 }
335 
336 int lapb_data_received(void *token, struct sk_buff *skb)
337 {
338         lapb_cb *lapb;
339 
340         if ((lapb = lapb_tokentostruct(token)) == NULL)
341                 return LAPB_BADTOKEN;
342 
343         lapb_data_input(lapb, skb);
344 
345         return LAPB_OK;
346 }
347 
348 void lapb_connect_confirmation(lapb_cb *lapb, int reason)
349 {
350         if (lapb->callbacks.connect_confirmation != NULL)
351                 (lapb->callbacks.connect_confirmation)(lapb->token, reason);
352 }
353 
354 void lapb_connect_indication(lapb_cb *lapb, int reason)
355 {
356         if (lapb->callbacks.connect_indication != NULL)
357                 (lapb->callbacks.connect_indication)(lapb->token, reason);
358 }
359 
360 void lapb_disconnect_confirmation(lapb_cb *lapb, int reason)
361 {
362         if (lapb->callbacks.disconnect_confirmation != NULL)
363                 (lapb->callbacks.disconnect_confirmation)(lapb->token, reason);
364 }
365 
366 void lapb_disconnect_indication(lapb_cb *lapb, int reason)
367 {
368         if (lapb->callbacks.disconnect_indication != NULL)
369                 (lapb->callbacks.disconnect_indication)(lapb->token, reason);
370 }
371 
372 int lapb_data_indication(lapb_cb *lapb, struct sk_buff *skb)
373 {
374         if (lapb->callbacks.data_indication != NULL) {
375                 return (lapb->callbacks.data_indication)(lapb->token, skb);
376         }
377         kfree_skb(skb);
378         return NET_RX_CN_HIGH; /* For now; must be != NET_RX_DROP */ 
379 }
380 
381 int lapb_data_transmit(lapb_cb *lapb, struct sk_buff *skb)
382 {
383         int used = 0;
384 
385         if (lapb->callbacks.data_transmit != NULL) {
386                 (lapb->callbacks.data_transmit)(lapb->token, skb);
387                 used = 1;
388         }
389 
390         return used;
391 }
392 
393 EXPORT_SYMBOL(lapb_register);
394 EXPORT_SYMBOL(lapb_unregister);
395 EXPORT_SYMBOL(lapb_getparms);
396 EXPORT_SYMBOL(lapb_setparms);
397 EXPORT_SYMBOL(lapb_connect_request);
398 EXPORT_SYMBOL(lapb_disconnect_request);
399 EXPORT_SYMBOL(lapb_data_request);
400 EXPORT_SYMBOL(lapb_data_received);
401 
402 static int __init lapb_init(void)
403 {
404         printk(KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n");
405         return 0;
406 }
407 
408 #ifdef MODULE
409 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
410 MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
411 #endif
412 
413 
414 module_init(lapb_init);
415 
416 #endif
417 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.