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