Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/lapb/lapb_iface.c
26146 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* LAPB release 002
4
*
5
* This code REQUIRES 2.1.15 or higher/ NET3.038
6
*
7
* History
8
* LAPB 001 Jonathan Naylor Started Coding
9
* LAPB 002 Jonathan Naylor New timer architecture.
10
* 2000-10-29 Henner Eisen lapb_data_indication() return status.
11
*/
12
13
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
15
#include <linux/module.h>
16
#include <linux/errno.h>
17
#include <linux/types.h>
18
#include <linux/socket.h>
19
#include <linux/in.h>
20
#include <linux/kernel.h>
21
#include <linux/jiffies.h>
22
#include <linux/timer.h>
23
#include <linux/string.h>
24
#include <linux/sockios.h>
25
#include <linux/net.h>
26
#include <linux/inet.h>
27
#include <linux/if_arp.h>
28
#include <linux/skbuff.h>
29
#include <linux/slab.h>
30
#include <net/sock.h>
31
#include <linux/uaccess.h>
32
#include <linux/fcntl.h>
33
#include <linux/mm.h>
34
#include <linux/interrupt.h>
35
#include <linux/stat.h>
36
#include <linux/init.h>
37
#include <net/lapb.h>
38
39
static LIST_HEAD(lapb_list);
40
static DEFINE_RWLOCK(lapb_list_lock);
41
42
/*
43
* Free an allocated lapb control block.
44
*/
45
static void lapb_free_cb(struct lapb_cb *lapb)
46
{
47
kfree(lapb);
48
}
49
50
static __inline__ void lapb_hold(struct lapb_cb *lapb)
51
{
52
refcount_inc(&lapb->refcnt);
53
}
54
55
static __inline__ void lapb_put(struct lapb_cb *lapb)
56
{
57
if (refcount_dec_and_test(&lapb->refcnt))
58
lapb_free_cb(lapb);
59
}
60
61
/*
62
* Socket removal during an interrupt is now safe.
63
*/
64
static void __lapb_remove_cb(struct lapb_cb *lapb)
65
{
66
if (lapb->node.next) {
67
list_del(&lapb->node);
68
lapb_put(lapb);
69
}
70
}
71
72
/*
73
* Add a socket to the bound sockets list.
74
*/
75
static void __lapb_insert_cb(struct lapb_cb *lapb)
76
{
77
list_add(&lapb->node, &lapb_list);
78
lapb_hold(lapb);
79
}
80
81
static struct lapb_cb *__lapb_devtostruct(struct net_device *dev)
82
{
83
struct lapb_cb *lapb, *use = NULL;
84
85
list_for_each_entry(lapb, &lapb_list, node) {
86
if (lapb->dev == dev) {
87
use = lapb;
88
break;
89
}
90
}
91
92
if (use)
93
lapb_hold(use);
94
95
return use;
96
}
97
98
static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
99
{
100
struct lapb_cb *rc;
101
102
read_lock_bh(&lapb_list_lock);
103
rc = __lapb_devtostruct(dev);
104
read_unlock_bh(&lapb_list_lock);
105
106
return rc;
107
}
108
/*
109
* Create an empty LAPB control block.
110
*/
111
static struct lapb_cb *lapb_create_cb(void)
112
{
113
struct lapb_cb *lapb = kzalloc(sizeof(*lapb), GFP_ATOMIC);
114
115
if (!lapb)
116
goto out;
117
118
skb_queue_head_init(&lapb->write_queue);
119
skb_queue_head_init(&lapb->ack_queue);
120
121
timer_setup(&lapb->t1timer, NULL, 0);
122
timer_setup(&lapb->t2timer, NULL, 0);
123
lapb->t1timer_running = false;
124
lapb->t2timer_running = false;
125
126
lapb->t1 = LAPB_DEFAULT_T1;
127
lapb->t2 = LAPB_DEFAULT_T2;
128
lapb->n2 = LAPB_DEFAULT_N2;
129
lapb->mode = LAPB_DEFAULT_MODE;
130
lapb->window = LAPB_DEFAULT_WINDOW;
131
lapb->state = LAPB_STATE_0;
132
133
spin_lock_init(&lapb->lock);
134
refcount_set(&lapb->refcnt, 1);
135
out:
136
return lapb;
137
}
138
139
int lapb_register(struct net_device *dev,
140
const struct lapb_register_struct *callbacks)
141
{
142
struct lapb_cb *lapb;
143
int rc = LAPB_BADTOKEN;
144
145
write_lock_bh(&lapb_list_lock);
146
147
lapb = __lapb_devtostruct(dev);
148
if (lapb) {
149
lapb_put(lapb);
150
goto out;
151
}
152
153
lapb = lapb_create_cb();
154
rc = LAPB_NOMEM;
155
if (!lapb)
156
goto out;
157
158
lapb->dev = dev;
159
lapb->callbacks = callbacks;
160
161
__lapb_insert_cb(lapb);
162
163
lapb_start_t1timer(lapb);
164
165
rc = LAPB_OK;
166
out:
167
write_unlock_bh(&lapb_list_lock);
168
return rc;
169
}
170
EXPORT_SYMBOL(lapb_register);
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
lapb_put(lapb);
182
183
/* Wait for other refs to "lapb" to drop */
184
while (refcount_read(&lapb->refcnt) > 2)
185
usleep_range(1, 10);
186
187
spin_lock_bh(&lapb->lock);
188
189
lapb_stop_t1timer(lapb);
190
lapb_stop_t2timer(lapb);
191
192
lapb_clear_queues(lapb);
193
194
spin_unlock_bh(&lapb->lock);
195
196
/* Wait for running timers to stop */
197
timer_delete_sync(&lapb->t1timer);
198
timer_delete_sync(&lapb->t2timer);
199
200
__lapb_remove_cb(lapb);
201
202
lapb_put(lapb);
203
rc = LAPB_OK;
204
out:
205
write_unlock_bh(&lapb_list_lock);
206
return rc;
207
}
208
EXPORT_SYMBOL(lapb_unregister);
209
210
int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms)
211
{
212
int rc = LAPB_BADTOKEN;
213
struct lapb_cb *lapb = lapb_devtostruct(dev);
214
215
if (!lapb)
216
goto out;
217
218
spin_lock_bh(&lapb->lock);
219
220
parms->t1 = lapb->t1 / HZ;
221
parms->t2 = lapb->t2 / HZ;
222
parms->n2 = lapb->n2;
223
parms->n2count = lapb->n2count;
224
parms->state = lapb->state;
225
parms->window = lapb->window;
226
parms->mode = lapb->mode;
227
228
if (!timer_pending(&lapb->t1timer))
229
parms->t1timer = 0;
230
else
231
parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
232
233
if (!timer_pending(&lapb->t2timer))
234
parms->t2timer = 0;
235
else
236
parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
237
238
spin_unlock_bh(&lapb->lock);
239
lapb_put(lapb);
240
rc = LAPB_OK;
241
out:
242
return rc;
243
}
244
EXPORT_SYMBOL(lapb_getparms);
245
246
int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms)
247
{
248
int rc = LAPB_BADTOKEN;
249
struct lapb_cb *lapb = lapb_devtostruct(dev);
250
251
if (!lapb)
252
goto out;
253
254
spin_lock_bh(&lapb->lock);
255
256
rc = LAPB_INVALUE;
257
if (parms->t1 < 1 || parms->t2 < 1 || parms->n2 < 1)
258
goto out_put;
259
260
if (lapb->state == LAPB_STATE_0) {
261
if (parms->mode & LAPB_EXTENDED) {
262
if (parms->window < 1 || parms->window > 127)
263
goto out_put;
264
} else {
265
if (parms->window < 1 || parms->window > 7)
266
goto out_put;
267
}
268
lapb->mode = parms->mode;
269
lapb->window = parms->window;
270
}
271
272
lapb->t1 = parms->t1 * HZ;
273
lapb->t2 = parms->t2 * HZ;
274
lapb->n2 = parms->n2;
275
276
rc = LAPB_OK;
277
out_put:
278
spin_unlock_bh(&lapb->lock);
279
lapb_put(lapb);
280
out:
281
return rc;
282
}
283
EXPORT_SYMBOL(lapb_setparms);
284
285
int lapb_connect_request(struct net_device *dev)
286
{
287
struct lapb_cb *lapb = lapb_devtostruct(dev);
288
int rc = LAPB_BADTOKEN;
289
290
if (!lapb)
291
goto out;
292
293
spin_lock_bh(&lapb->lock);
294
295
rc = LAPB_OK;
296
if (lapb->state == LAPB_STATE_1)
297
goto out_put;
298
299
rc = LAPB_CONNECTED;
300
if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4)
301
goto out_put;
302
303
lapb_establish_data_link(lapb);
304
305
lapb_dbg(0, "(%p) S0 -> S1\n", lapb->dev);
306
lapb->state = LAPB_STATE_1;
307
308
rc = LAPB_OK;
309
out_put:
310
spin_unlock_bh(&lapb->lock);
311
lapb_put(lapb);
312
out:
313
return rc;
314
}
315
EXPORT_SYMBOL(lapb_connect_request);
316
317
static int __lapb_disconnect_request(struct lapb_cb *lapb)
318
{
319
switch (lapb->state) {
320
case LAPB_STATE_0:
321
return LAPB_NOTCONNECTED;
322
323
case LAPB_STATE_1:
324
lapb_dbg(1, "(%p) S1 TX DISC(1)\n", lapb->dev);
325
lapb_dbg(0, "(%p) S1 -> S0\n", lapb->dev);
326
lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
327
lapb->state = LAPB_STATE_0;
328
lapb_start_t1timer(lapb);
329
return LAPB_NOTCONNECTED;
330
331
case LAPB_STATE_2:
332
return LAPB_OK;
333
}
334
335
lapb_clear_queues(lapb);
336
lapb->n2count = 0;
337
lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
338
lapb_start_t1timer(lapb);
339
lapb_stop_t2timer(lapb);
340
lapb->state = LAPB_STATE_2;
341
342
lapb_dbg(1, "(%p) S3 DISC(1)\n", lapb->dev);
343
lapb_dbg(0, "(%p) S3 -> S2\n", lapb->dev);
344
345
return LAPB_OK;
346
}
347
348
int lapb_disconnect_request(struct net_device *dev)
349
{
350
struct lapb_cb *lapb = lapb_devtostruct(dev);
351
int rc = LAPB_BADTOKEN;
352
353
if (!lapb)
354
goto out;
355
356
spin_lock_bh(&lapb->lock);
357
358
rc = __lapb_disconnect_request(lapb);
359
360
spin_unlock_bh(&lapb->lock);
361
lapb_put(lapb);
362
out:
363
return rc;
364
}
365
EXPORT_SYMBOL(lapb_disconnect_request);
366
367
int lapb_data_request(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
goto out;
374
375
spin_lock_bh(&lapb->lock);
376
377
rc = LAPB_NOTCONNECTED;
378
if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4)
379
goto out_put;
380
381
skb_queue_tail(&lapb->write_queue, skb);
382
lapb_kick(lapb);
383
rc = LAPB_OK;
384
out_put:
385
spin_unlock_bh(&lapb->lock);
386
lapb_put(lapb);
387
out:
388
return rc;
389
}
390
EXPORT_SYMBOL(lapb_data_request);
391
392
int lapb_data_received(struct net_device *dev, struct sk_buff *skb)
393
{
394
struct lapb_cb *lapb = lapb_devtostruct(dev);
395
int rc = LAPB_BADTOKEN;
396
397
if (lapb) {
398
spin_lock_bh(&lapb->lock);
399
lapb_data_input(lapb, skb);
400
spin_unlock_bh(&lapb->lock);
401
lapb_put(lapb);
402
rc = LAPB_OK;
403
}
404
405
return rc;
406
}
407
EXPORT_SYMBOL(lapb_data_received);
408
409
void lapb_connect_confirmation(struct lapb_cb *lapb, int reason)
410
{
411
if (lapb->callbacks->connect_confirmation)
412
lapb->callbacks->connect_confirmation(lapb->dev, reason);
413
}
414
415
void lapb_connect_indication(struct lapb_cb *lapb, int reason)
416
{
417
if (lapb->callbacks->connect_indication)
418
lapb->callbacks->connect_indication(lapb->dev, reason);
419
}
420
421
void lapb_disconnect_confirmation(struct lapb_cb *lapb, int reason)
422
{
423
if (lapb->callbacks->disconnect_confirmation)
424
lapb->callbacks->disconnect_confirmation(lapb->dev, reason);
425
}
426
427
void lapb_disconnect_indication(struct lapb_cb *lapb, int reason)
428
{
429
if (lapb->callbacks->disconnect_indication)
430
lapb->callbacks->disconnect_indication(lapb->dev, reason);
431
}
432
433
int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb)
434
{
435
if (lapb->callbacks->data_indication)
436
return lapb->callbacks->data_indication(lapb->dev, skb);
437
438
kfree_skb(skb);
439
return NET_RX_SUCCESS; /* For now; must be != NET_RX_DROP */
440
}
441
442
int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
443
{
444
int used = 0;
445
446
if (lapb->callbacks->data_transmit) {
447
lapb->callbacks->data_transmit(lapb->dev, skb);
448
used = 1;
449
}
450
451
return used;
452
}
453
454
/* Handle device status changes. */
455
static int lapb_device_event(struct notifier_block *this, unsigned long event,
456
void *ptr)
457
{
458
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
459
struct lapb_cb *lapb;
460
461
if (!net_eq(dev_net(dev), &init_net))
462
return NOTIFY_DONE;
463
464
if (dev->type != ARPHRD_X25)
465
return NOTIFY_DONE;
466
467
lapb = lapb_devtostruct(dev);
468
if (!lapb)
469
return NOTIFY_DONE;
470
471
spin_lock_bh(&lapb->lock);
472
473
switch (event) {
474
case NETDEV_UP:
475
lapb_dbg(0, "(%p) Interface up: %s\n", dev, dev->name);
476
477
if (netif_carrier_ok(dev)) {
478
lapb_dbg(0, "(%p): Carrier is already up: %s\n", dev,
479
dev->name);
480
if (lapb->mode & LAPB_DCE) {
481
lapb_start_t1timer(lapb);
482
} else {
483
if (lapb->state == LAPB_STATE_0) {
484
lapb->state = LAPB_STATE_1;
485
lapb_establish_data_link(lapb);
486
}
487
}
488
}
489
break;
490
case NETDEV_GOING_DOWN:
491
if (netif_carrier_ok(dev))
492
__lapb_disconnect_request(lapb);
493
break;
494
case NETDEV_DOWN:
495
lapb_dbg(0, "(%p) Interface down: %s\n", dev, dev->name);
496
lapb_dbg(0, "(%p) S%d -> S0\n", dev, lapb->state);
497
lapb_clear_queues(lapb);
498
lapb->state = LAPB_STATE_0;
499
lapb->n2count = 0;
500
lapb_stop_t1timer(lapb);
501
lapb_stop_t2timer(lapb);
502
break;
503
case NETDEV_CHANGE:
504
if (netif_carrier_ok(dev)) {
505
lapb_dbg(0, "(%p): Carrier detected: %s\n", dev,
506
dev->name);
507
if (lapb->mode & LAPB_DCE) {
508
lapb_start_t1timer(lapb);
509
} else {
510
if (lapb->state == LAPB_STATE_0) {
511
lapb->state = LAPB_STATE_1;
512
lapb_establish_data_link(lapb);
513
}
514
}
515
} else {
516
lapb_dbg(0, "(%p) Carrier lost: %s\n", dev, dev->name);
517
lapb_dbg(0, "(%p) S%d -> S0\n", dev, lapb->state);
518
lapb_clear_queues(lapb);
519
lapb->state = LAPB_STATE_0;
520
lapb->n2count = 0;
521
lapb_stop_t1timer(lapb);
522
lapb_stop_t2timer(lapb);
523
}
524
break;
525
}
526
527
spin_unlock_bh(&lapb->lock);
528
lapb_put(lapb);
529
return NOTIFY_DONE;
530
}
531
532
static struct notifier_block lapb_dev_notifier = {
533
.notifier_call = lapb_device_event,
534
};
535
536
static int __init lapb_init(void)
537
{
538
return register_netdevice_notifier(&lapb_dev_notifier);
539
}
540
541
static void __exit lapb_exit(void)
542
{
543
WARN_ON(!list_empty(&lapb_list));
544
545
unregister_netdevice_notifier(&lapb_dev_notifier);
546
}
547
548
MODULE_AUTHOR("Jonathan Naylor <[email protected]>");
549
MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
550
MODULE_LICENSE("GPL");
551
552
module_init(lapb_init);
553
module_exit(lapb_exit);
554
555