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