Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lapb_iface.c
Go to the documentation of this file.
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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 
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/jiffies.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 <linux/slab.h>
35 #include <net/sock.h>
36 #include <asm/uaccess.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 LIST_HEAD(lapb_list);
45 static DEFINE_RWLOCK(lapb_list_lock);
46 
47 /*
48  * Free an allocated lapb control block.
49  */
50 static void lapb_free_cb(struct lapb_cb *lapb)
51 {
52  kfree(lapb);
53 }
54 
55 static __inline__ void lapb_hold(struct lapb_cb *lapb)
56 {
57  atomic_inc(&lapb->refcnt);
58 }
59 
60 static __inline__ void lapb_put(struct lapb_cb *lapb)
61 {
62  if (atomic_dec_and_test(&lapb->refcnt))
63  lapb_free_cb(lapb);
64 }
65 
66 /*
67  * Socket removal during an interrupt is now safe.
68  */
69 static void __lapb_remove_cb(struct lapb_cb *lapb)
70 {
71  if (lapb->node.next) {
72  list_del(&lapb->node);
73  lapb_put(lapb);
74  }
75 }
76 
77 /*
78  * Add a socket to the bound sockets list.
79  */
80 static void __lapb_insert_cb(struct lapb_cb *lapb)
81 {
82  list_add(&lapb->node, &lapb_list);
83  lapb_hold(lapb);
84 }
85 
86 static struct lapb_cb *__lapb_devtostruct(struct net_device *dev)
87 {
88  struct list_head *entry;
89  struct lapb_cb *lapb, *use = NULL;
90 
91  list_for_each(entry, &lapb_list) {
92  lapb = list_entry(entry, struct lapb_cb, node);
93  if (lapb->dev == dev) {
94  use = lapb;
95  break;
96  }
97  }
98 
99  if (use)
100  lapb_hold(use);
101 
102  return use;
103 }
104 
105 static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
106 {
107  struct lapb_cb *rc;
108 
109  read_lock_bh(&lapb_list_lock);
110  rc = __lapb_devtostruct(dev);
111  read_unlock_bh(&lapb_list_lock);
112 
113  return rc;
114 }
115 /*
116  * Create an empty LAPB control block.
117  */
118 static struct lapb_cb *lapb_create_cb(void)
119 {
120  struct lapb_cb *lapb = kzalloc(sizeof(*lapb), GFP_ATOMIC);
121 
122 
123  if (!lapb)
124  goto out;
125 
126  skb_queue_head_init(&lapb->write_queue);
127  skb_queue_head_init(&lapb->ack_queue);
128 
129  init_timer(&lapb->t1timer);
130  init_timer(&lapb->t2timer);
131 
132  lapb->t1 = LAPB_DEFAULT_T1;
133  lapb->t2 = LAPB_DEFAULT_T2;
134  lapb->n2 = LAPB_DEFAULT_N2;
135  lapb->mode = LAPB_DEFAULT_MODE;
136  lapb->window = LAPB_DEFAULT_WINDOW;
137  lapb->state = LAPB_STATE_0;
138  atomic_set(&lapb->refcnt, 1);
139 out:
140  return lapb;
141 }
142 
143 int lapb_register(struct net_device *dev,
144  const struct lapb_register_struct *callbacks)
145 {
146  struct lapb_cb *lapb;
147  int rc = LAPB_BADTOKEN;
148 
149  write_lock_bh(&lapb_list_lock);
150 
151  lapb = __lapb_devtostruct(dev);
152  if (lapb) {
153  lapb_put(lapb);
154  goto out;
155  }
156 
157  lapb = lapb_create_cb();
158  rc = LAPB_NOMEM;
159  if (!lapb)
160  goto out;
161 
162  lapb->dev = dev;
163  lapb->callbacks = callbacks;
164 
165  __lapb_insert_cb(lapb);
166 
167  lapb_start_t1timer(lapb);
168 
169  rc = LAPB_OK;
170 out:
171  write_unlock_bh(&lapb_list_lock);
172  return rc;
173 }
174 
175 int lapb_unregister(struct net_device *dev)
176 {
177  struct lapb_cb *lapb;
178  int rc = LAPB_BADTOKEN;
179 
180  write_lock_bh(&lapb_list_lock);
181  lapb = __lapb_devtostruct(dev);
182  if (!lapb)
183  goto out;
184 
185  lapb_stop_t1timer(lapb);
186  lapb_stop_t2timer(lapb);
187 
188  lapb_clear_queues(lapb);
189 
190  __lapb_remove_cb(lapb);
191 
192  lapb_put(lapb);
193  rc = LAPB_OK;
194 out:
195  write_unlock_bh(&lapb_list_lock);
196  return rc;
197 }
198 
200 {
201  int rc = LAPB_BADTOKEN;
202  struct lapb_cb *lapb = lapb_devtostruct(dev);
203 
204  if (!lapb)
205  goto out;
206 
207  parms->t1 = lapb->t1 / HZ;
208  parms->t2 = lapb->t2 / HZ;
209  parms->n2 = lapb->n2;
210  parms->n2count = lapb->n2count;
211  parms->state = lapb->state;
212  parms->window = lapb->window;
213  parms->mode = lapb->mode;
214 
215  if (!timer_pending(&lapb->t1timer))
216  parms->t1timer = 0;
217  else
218  parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
219 
220  if (!timer_pending(&lapb->t2timer))
221  parms->t2timer = 0;
222  else
223  parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
224 
225  lapb_put(lapb);
226  rc = LAPB_OK;
227 out:
228  return rc;
229 }
230 
232 {
233  int rc = LAPB_BADTOKEN;
234  struct lapb_cb *lapb = lapb_devtostruct(dev);
235 
236  if (!lapb)
237  goto out;
238 
239  rc = LAPB_INVALUE;
240  if (parms->t1 < 1 || parms->t2 < 1 || parms->n2 < 1)
241  goto out_put;
242 
243  if (lapb->state == LAPB_STATE_0) {
244  if (parms->mode & LAPB_EXTENDED) {
245  if (parms->window < 1 || parms->window > 127)
246  goto out_put;
247  } else {
248  if (parms->window < 1 || parms->window > 7)
249  goto out_put;
250  }
251  lapb->mode = parms->mode;
252  lapb->window = parms->window;
253  }
254 
255  lapb->t1 = parms->t1 * HZ;
256  lapb->t2 = parms->t2 * HZ;
257  lapb->n2 = parms->n2;
258 
259  rc = LAPB_OK;
260 out_put:
261  lapb_put(lapb);
262 out:
263  return rc;
264 }
265 
267 {
268  struct lapb_cb *lapb = lapb_devtostruct(dev);
269  int rc = LAPB_BADTOKEN;
270 
271  if (!lapb)
272  goto out;
273 
274  rc = LAPB_OK;
275  if (lapb->state == LAPB_STATE_1)
276  goto out_put;
277 
278  rc = LAPB_CONNECTED;
279  if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4)
280  goto out_put;
281 
283 
284  lapb_dbg(0, "(%p) S0 -> S1\n", lapb->dev);
285  lapb->state = LAPB_STATE_1;
286 
287  rc = LAPB_OK;
288 out_put:
289  lapb_put(lapb);
290 out:
291  return rc;
292 }
293 
295 {
296  struct lapb_cb *lapb = lapb_devtostruct(dev);
297  int rc = LAPB_BADTOKEN;
298 
299  if (!lapb)
300  goto out;
301 
302  switch (lapb->state) {
303  case LAPB_STATE_0:
304  rc = LAPB_NOTCONNECTED;
305  goto out_put;
306 
307  case LAPB_STATE_1:
308  lapb_dbg(1, "(%p) S1 TX DISC(1)\n", lapb->dev);
309  lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev);
311  lapb->state = LAPB_STATE_0;
312  lapb_start_t1timer(lapb);
313  rc = LAPB_NOTCONNECTED;
314  goto out_put;
315 
316  case LAPB_STATE_2:
317  rc = LAPB_OK;
318  goto out_put;
319  }
320 
321  lapb_clear_queues(lapb);
322  lapb->n2count = 0;
324  lapb_start_t1timer(lapb);
325  lapb_stop_t2timer(lapb);
326  lapb->state = LAPB_STATE_2;
327 
328  lapb_dbg(1, "(%p) S3 DISC(1)\n", lapb->dev);
329  lapb_dbg(0, "(%p) S3 -> S2\n", lapb->dev);
330 
331  rc = LAPB_OK;
332 out_put:
333  lapb_put(lapb);
334 out:
335  return rc;
336 }
337 
338 int lapb_data_request(struct net_device *dev, struct sk_buff *skb)
339 {
340  struct lapb_cb *lapb = lapb_devtostruct(dev);
341  int rc = LAPB_BADTOKEN;
342 
343  if (!lapb)
344  goto out;
345 
346  rc = LAPB_NOTCONNECTED;
347  if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4)
348  goto out_put;
349 
350  skb_queue_tail(&lapb->write_queue, skb);
351  lapb_kick(lapb);
352  rc = LAPB_OK;
353 out_put:
354  lapb_put(lapb);
355 out:
356  return rc;
357 }
358 
359 int lapb_data_received(struct net_device *dev, struct sk_buff *skb)
360 {
361  struct lapb_cb *lapb = lapb_devtostruct(dev);
362  int rc = LAPB_BADTOKEN;
363 
364  if (lapb) {
365  lapb_data_input(lapb, skb);
366  lapb_put(lapb);
367  rc = LAPB_OK;
368  }
369 
370  return rc;
371 }
372 
373 void lapb_connect_confirmation(struct lapb_cb *lapb, int reason)
374 {
375  if (lapb->callbacks->connect_confirmation)
376  lapb->callbacks->connect_confirmation(lapb->dev, reason);
377 }
378 
379 void lapb_connect_indication(struct lapb_cb *lapb, int reason)
380 {
381  if (lapb->callbacks->connect_indication)
382  lapb->callbacks->connect_indication(lapb->dev, reason);
383 }
384 
386 {
387  if (lapb->callbacks->disconnect_confirmation)
388  lapb->callbacks->disconnect_confirmation(lapb->dev, reason);
389 }
390 
392 {
393  if (lapb->callbacks->disconnect_indication)
394  lapb->callbacks->disconnect_indication(lapb->dev, reason);
395 }
396 
397 int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb)
398 {
399  if (lapb->callbacks->data_indication)
400  return lapb->callbacks->data_indication(lapb->dev, skb);
401 
402  kfree_skb(skb);
403  return NET_RX_SUCCESS; /* For now; must be != NET_RX_DROP */
404 }
405 
406 int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
407 {
408  int used = 0;
409 
410  if (lapb->callbacks->data_transmit) {
411  lapb->callbacks->data_transmit(lapb->dev, skb);
412  used = 1;
413  }
414 
415  return used;
416 }
417 
426 
427 static int __init lapb_init(void)
428 {
429  return 0;
430 }
431 
432 static void __exit lapb_exit(void)
433 {
434  WARN_ON(!list_empty(&lapb_list));
435 }
436 
437 MODULE_AUTHOR("Jonathan Naylor <[email protected]>");
438 MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
439 MODULE_LICENSE("GPL");
440 
441 module_init(lapb_init);
442 module_exit(lapb_exit);