xref: /linux/drivers/net/wan/lapbether.c (revision 662fa3d6099374c4615bf64d06895e3573b935b2)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *	"LAPB via ethernet" driver release 001
4  *
5  *	This code REQUIRES 2.1.15 or higher/ NET3.038
6  *
7  *	This is a "pseudo" network driver to allow LAPB over Ethernet.
8  *
9  *	This driver can use any ethernet destination address, and can be
10  *	limited to accept frames from one dedicated ethernet card only.
11  *
12  *	History
13  *	LAPBETH 001	Jonathan Naylor		Cloned from bpqether.c
14  *	2000-10-29	Henner Eisen	lapb_data_indication() return status.
15  *	2000-11-14	Henner Eisen	dev_hold/put, NETDEV_GOING_DOWN support
16  */
17 
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 
20 #include <linux/errno.h>
21 #include <linux/types.h>
22 #include <linux/socket.h>
23 #include <linux/in.h>
24 #include <linux/slab.h>
25 #include <linux/kernel.h>
26 #include <linux/string.h>
27 #include <linux/net.h>
28 #include <linux/inet.h>
29 #include <linux/netdevice.h>
30 #include <linux/if_arp.h>
31 #include <linux/skbuff.h>
32 #include <net/sock.h>
33 #include <linux/uaccess.h>
34 #include <linux/mm.h>
35 #include <linux/interrupt.h>
36 #include <linux/notifier.h>
37 #include <linux/stat.h>
38 #include <linux/module.h>
39 #include <linux/lapb.h>
40 #include <linux/init.h>
41 
42 #include <net/x25device.h>
43 
44 static const u8 bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
45 
46 /* If this number is made larger, check that the temporary string buffer
47  * in lapbeth_new_device is large enough to store the probe device name.
48  */
49 #define MAXLAPBDEV 100
50 
51 struct lapbethdev {
52 	struct list_head	node;
53 	struct net_device	*ethdev;	/* link to ethernet device */
54 	struct net_device	*axdev;		/* lapbeth device (lapb#) */
55 	bool			up;
56 	spinlock_t		up_lock;	/* Protects "up" */
57 	struct sk_buff_head	rx_queue;
58 	struct napi_struct	napi;
59 };
60 
61 static LIST_HEAD(lapbeth_devices);
62 
63 static void lapbeth_connected(struct net_device *dev, int reason);
64 static void lapbeth_disconnected(struct net_device *dev, int reason);
65 
66 /* ------------------------------------------------------------------------ */
67 
68 /*	Get the LAPB device for the ethernet device
69  */
70 static struct lapbethdev *lapbeth_get_x25_dev(struct net_device *dev)
71 {
72 	struct lapbethdev *lapbeth;
73 
74 	list_for_each_entry_rcu(lapbeth, &lapbeth_devices, node, lockdep_rtnl_is_held()) {
75 		if (lapbeth->ethdev == dev)
76 			return lapbeth;
77 	}
78 	return NULL;
79 }
80 
81 static __inline__ int dev_is_ethdev(struct net_device *dev)
82 {
83 	return dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5);
84 }
85 
86 /* ------------------------------------------------------------------------ */
87 
88 static int lapbeth_napi_poll(struct napi_struct *napi, int budget)
89 {
90 	struct lapbethdev *lapbeth = container_of(napi, struct lapbethdev,
91 						  napi);
92 	struct sk_buff *skb;
93 	int processed = 0;
94 
95 	for (; processed < budget; ++processed) {
96 		skb = skb_dequeue(&lapbeth->rx_queue);
97 		if (!skb)
98 			break;
99 		netif_receive_skb_core(skb);
100 	}
101 
102 	if (processed < budget)
103 		napi_complete(napi);
104 
105 	return processed;
106 }
107 
108 /*	Receive a LAPB frame via an ethernet interface.
109  */
110 static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev,
111 		       struct packet_type *ptype, struct net_device *orig_dev)
112 {
113 	int len, err;
114 	struct lapbethdev *lapbeth;
115 
116 	if (dev_net(dev) != &init_net)
117 		goto drop;
118 
119 	skb = skb_share_check(skb, GFP_ATOMIC);
120 	if (!skb)
121 		return NET_RX_DROP;
122 
123 	if (!pskb_may_pull(skb, 2))
124 		goto drop;
125 
126 	rcu_read_lock();
127 	lapbeth = lapbeth_get_x25_dev(dev);
128 	if (!lapbeth)
129 		goto drop_unlock_rcu;
130 	spin_lock_bh(&lapbeth->up_lock);
131 	if (!lapbeth->up)
132 		goto drop_unlock;
133 
134 	len = skb->data[0] + skb->data[1] * 256;
135 	dev->stats.rx_packets++;
136 	dev->stats.rx_bytes += len;
137 
138 	skb_pull(skb, 2);	/* Remove the length bytes */
139 	skb_trim(skb, len);	/* Set the length of the data */
140 
141 	err = lapb_data_received(lapbeth->axdev, skb);
142 	if (err != LAPB_OK) {
143 		printk(KERN_DEBUG "lapbether: lapb_data_received err - %d\n", err);
144 		goto drop_unlock;
145 	}
146 out:
147 	spin_unlock_bh(&lapbeth->up_lock);
148 	rcu_read_unlock();
149 	return 0;
150 drop_unlock:
151 	kfree_skb(skb);
152 	goto out;
153 drop_unlock_rcu:
154 	rcu_read_unlock();
155 drop:
156 	kfree_skb(skb);
157 	return 0;
158 }
159 
160 static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb)
161 {
162 	struct lapbethdev *lapbeth = netdev_priv(dev);
163 	unsigned char *ptr;
164 
165 	if (skb_cow(skb, 1)) {
166 		kfree_skb(skb);
167 		return NET_RX_DROP;
168 	}
169 
170 	skb_push(skb, 1);
171 
172 	ptr  = skb->data;
173 	*ptr = X25_IFACE_DATA;
174 
175 	skb->protocol = x25_type_trans(skb, dev);
176 
177 	skb_queue_tail(&lapbeth->rx_queue, skb);
178 	napi_schedule(&lapbeth->napi);
179 	return NET_RX_SUCCESS;
180 }
181 
182 /*	Send a LAPB frame via an ethernet interface
183  */
184 static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
185 				struct net_device *dev)
186 {
187 	struct lapbethdev *lapbeth = netdev_priv(dev);
188 	int err;
189 
190 	spin_lock_bh(&lapbeth->up_lock);
191 	if (!lapbeth->up)
192 		goto drop;
193 
194 	/* There should be a pseudo header of 1 byte added by upper layers.
195 	 * Check to make sure it is there before reading it.
196 	 */
197 	if (skb->len < 1)
198 		goto drop;
199 
200 	switch (skb->data[0]) {
201 	case X25_IFACE_DATA:
202 		break;
203 	case X25_IFACE_CONNECT:
204 		err = lapb_connect_request(dev);
205 		if (err == LAPB_CONNECTED)
206 			lapbeth_connected(dev, LAPB_OK);
207 		else if (err != LAPB_OK)
208 			pr_err("lapb_connect_request error: %d\n", err);
209 		goto drop;
210 	case X25_IFACE_DISCONNECT:
211 		err = lapb_disconnect_request(dev);
212 		if (err == LAPB_NOTCONNECTED)
213 			lapbeth_disconnected(dev, LAPB_OK);
214 		else if (err != LAPB_OK)
215 			pr_err("lapb_disconnect_request err: %d\n", err);
216 		fallthrough;
217 	default:
218 		goto drop;
219 	}
220 
221 	skb_pull(skb, 1);
222 
223 	err = lapb_data_request(dev, skb);
224 	if (err != LAPB_OK) {
225 		pr_err("lapb_data_request error - %d\n", err);
226 		goto drop;
227 	}
228 out:
229 	spin_unlock_bh(&lapbeth->up_lock);
230 	return NETDEV_TX_OK;
231 drop:
232 	kfree_skb(skb);
233 	goto out;
234 }
235 
236 static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb)
237 {
238 	struct lapbethdev *lapbeth = netdev_priv(ndev);
239 	unsigned char *ptr;
240 	struct net_device *dev;
241 	int size = skb->len;
242 
243 	ptr = skb_push(skb, 2);
244 
245 	*ptr++ = size % 256;
246 	*ptr++ = size / 256;
247 
248 	ndev->stats.tx_packets++;
249 	ndev->stats.tx_bytes += size;
250 
251 	skb->dev = dev = lapbeth->ethdev;
252 
253 	skb->protocol = htons(ETH_P_DEC);
254 
255 	skb_reset_network_header(skb);
256 
257 	dev_hard_header(skb, dev, ETH_P_DEC, bcast_addr, NULL, 0);
258 
259 	dev_queue_xmit(skb);
260 }
261 
262 static void lapbeth_connected(struct net_device *dev, int reason)
263 {
264 	struct lapbethdev *lapbeth = netdev_priv(dev);
265 	unsigned char *ptr;
266 	struct sk_buff *skb = __dev_alloc_skb(1, GFP_ATOMIC | __GFP_NOMEMALLOC);
267 
268 	if (!skb)
269 		return;
270 
271 	ptr  = skb_put(skb, 1);
272 	*ptr = X25_IFACE_CONNECT;
273 
274 	skb->protocol = x25_type_trans(skb, dev);
275 
276 	skb_queue_tail(&lapbeth->rx_queue, skb);
277 	napi_schedule(&lapbeth->napi);
278 }
279 
280 static void lapbeth_disconnected(struct net_device *dev, int reason)
281 {
282 	struct lapbethdev *lapbeth = netdev_priv(dev);
283 	unsigned char *ptr;
284 	struct sk_buff *skb = __dev_alloc_skb(1, GFP_ATOMIC | __GFP_NOMEMALLOC);
285 
286 	if (!skb)
287 		return;
288 
289 	ptr  = skb_put(skb, 1);
290 	*ptr = X25_IFACE_DISCONNECT;
291 
292 	skb->protocol = x25_type_trans(skb, dev);
293 
294 	skb_queue_tail(&lapbeth->rx_queue, skb);
295 	napi_schedule(&lapbeth->napi);
296 }
297 
298 /*	Set AX.25 callsign
299  */
300 static int lapbeth_set_mac_address(struct net_device *dev, void *addr)
301 {
302 	struct sockaddr *sa = addr;
303 
304 	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
305 	return 0;
306 }
307 
308 static const struct lapb_register_struct lapbeth_callbacks = {
309 	.connect_confirmation    = lapbeth_connected,
310 	.connect_indication      = lapbeth_connected,
311 	.disconnect_confirmation = lapbeth_disconnected,
312 	.disconnect_indication   = lapbeth_disconnected,
313 	.data_indication         = lapbeth_data_indication,
314 	.data_transmit           = lapbeth_data_transmit,
315 };
316 
317 /* open/close a device
318  */
319 static int lapbeth_open(struct net_device *dev)
320 {
321 	struct lapbethdev *lapbeth = netdev_priv(dev);
322 	int err;
323 
324 	napi_enable(&lapbeth->napi);
325 
326 	err = lapb_register(dev, &lapbeth_callbacks);
327 	if (err != LAPB_OK) {
328 		pr_err("lapb_register error: %d\n", err);
329 		return -ENODEV;
330 	}
331 
332 	spin_lock_bh(&lapbeth->up_lock);
333 	lapbeth->up = true;
334 	spin_unlock_bh(&lapbeth->up_lock);
335 
336 	return 0;
337 }
338 
339 static int lapbeth_close(struct net_device *dev)
340 {
341 	struct lapbethdev *lapbeth = netdev_priv(dev);
342 	int err;
343 
344 	spin_lock_bh(&lapbeth->up_lock);
345 	lapbeth->up = false;
346 	spin_unlock_bh(&lapbeth->up_lock);
347 
348 	err = lapb_unregister(dev);
349 	if (err != LAPB_OK)
350 		pr_err("lapb_unregister error: %d\n", err);
351 
352 	napi_disable(&lapbeth->napi);
353 
354 	return 0;
355 }
356 
357 /* ------------------------------------------------------------------------ */
358 
359 static const struct net_device_ops lapbeth_netdev_ops = {
360 	.ndo_open	     = lapbeth_open,
361 	.ndo_stop	     = lapbeth_close,
362 	.ndo_start_xmit	     = lapbeth_xmit,
363 	.ndo_set_mac_address = lapbeth_set_mac_address,
364 };
365 
366 static void lapbeth_setup(struct net_device *dev)
367 {
368 	dev->netdev_ops	     = &lapbeth_netdev_ops;
369 	dev->needs_free_netdev = true;
370 	dev->type            = ARPHRD_X25;
371 	dev->hard_header_len = 0;
372 	dev->mtu             = 1000;
373 	dev->addr_len        = 0;
374 }
375 
376 /*	Setup a new device.
377  */
378 static int lapbeth_new_device(struct net_device *dev)
379 {
380 	struct net_device *ndev;
381 	struct lapbethdev *lapbeth;
382 	int rc = -ENOMEM;
383 
384 	ASSERT_RTNL();
385 
386 	ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", NET_NAME_UNKNOWN,
387 			    lapbeth_setup);
388 	if (!ndev)
389 		goto out;
390 
391 	/* When transmitting data:
392 	 * first this driver removes a pseudo header of 1 byte,
393 	 * then the lapb module prepends an LAPB header of at most 3 bytes,
394 	 * then this driver prepends a length field of 2 bytes,
395 	 * then the underlying Ethernet device prepends its own header.
396 	 */
397 	ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len
398 					   + dev->needed_headroom;
399 	ndev->needed_tailroom = dev->needed_tailroom;
400 
401 	lapbeth = netdev_priv(ndev);
402 	lapbeth->axdev = ndev;
403 
404 	dev_hold(dev);
405 	lapbeth->ethdev = dev;
406 
407 	lapbeth->up = false;
408 	spin_lock_init(&lapbeth->up_lock);
409 
410 	skb_queue_head_init(&lapbeth->rx_queue);
411 	netif_napi_add(ndev, &lapbeth->napi, lapbeth_napi_poll, 16);
412 
413 	rc = -EIO;
414 	if (register_netdevice(ndev))
415 		goto fail;
416 
417 	list_add_rcu(&lapbeth->node, &lapbeth_devices);
418 	rc = 0;
419 out:
420 	return rc;
421 fail:
422 	dev_put(dev);
423 	free_netdev(ndev);
424 	goto out;
425 }
426 
427 /*	Free a lapb network device.
428  */
429 static void lapbeth_free_device(struct lapbethdev *lapbeth)
430 {
431 	dev_put(lapbeth->ethdev);
432 	list_del_rcu(&lapbeth->node);
433 	unregister_netdevice(lapbeth->axdev);
434 }
435 
436 /*	Handle device status changes.
437  *
438  * Called from notifier with RTNL held.
439  */
440 static int lapbeth_device_event(struct notifier_block *this,
441 				unsigned long event, void *ptr)
442 {
443 	struct lapbethdev *lapbeth;
444 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
445 
446 	if (dev_net(dev) != &init_net)
447 		return NOTIFY_DONE;
448 
449 	if (!dev_is_ethdev(dev))
450 		return NOTIFY_DONE;
451 
452 	switch (event) {
453 	case NETDEV_UP:
454 		/* New ethernet device -> new LAPB interface	 */
455 		if (!lapbeth_get_x25_dev(dev))
456 			lapbeth_new_device(dev);
457 		break;
458 	case NETDEV_GOING_DOWN:
459 		/* ethernet device closes -> close LAPB interface */
460 		lapbeth = lapbeth_get_x25_dev(dev);
461 		if (lapbeth)
462 			dev_close(lapbeth->axdev);
463 		break;
464 	case NETDEV_UNREGISTER:
465 		/* ethernet device disappears -> remove LAPB interface */
466 		lapbeth = lapbeth_get_x25_dev(dev);
467 		if (lapbeth)
468 			lapbeth_free_device(lapbeth);
469 		break;
470 	}
471 
472 	return NOTIFY_DONE;
473 }
474 
475 /* ------------------------------------------------------------------------ */
476 
477 static struct packet_type lapbeth_packet_type __read_mostly = {
478 	.type = cpu_to_be16(ETH_P_DEC),
479 	.func = lapbeth_rcv,
480 };
481 
482 static struct notifier_block lapbeth_dev_notifier = {
483 	.notifier_call = lapbeth_device_event,
484 };
485 
486 static const char banner[] __initconst =
487 	KERN_INFO "LAPB Ethernet driver version 0.02\n";
488 
489 static int __init lapbeth_init_driver(void)
490 {
491 	dev_add_pack(&lapbeth_packet_type);
492 
493 	register_netdevice_notifier(&lapbeth_dev_notifier);
494 
495 	printk(banner);
496 
497 	return 0;
498 }
499 module_init(lapbeth_init_driver);
500 
501 static void __exit lapbeth_cleanup_driver(void)
502 {
503 	struct lapbethdev *lapbeth;
504 	struct list_head *entry, *tmp;
505 
506 	dev_remove_pack(&lapbeth_packet_type);
507 	unregister_netdevice_notifier(&lapbeth_dev_notifier);
508 
509 	rtnl_lock();
510 	list_for_each_safe(entry, tmp, &lapbeth_devices) {
511 		lapbeth = list_entry(entry, struct lapbethdev, node);
512 
513 		dev_put(lapbeth->ethdev);
514 		unregister_netdevice(lapbeth->axdev);
515 	}
516 	rtnl_unlock();
517 }
518 module_exit(lapbeth_cleanup_driver);
519 
520 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
521 MODULE_DESCRIPTION("The unofficial LAPB over Ethernet driver");
522 MODULE_LICENSE("GPL");
523