xref: /linux/drivers/net/wan/lapbether.c (revision 34dc1baba215b826e454b8d19e4f24adbeb7d00d)
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 	dev_addr_set(dev, sa->sa_data);
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 		napi_disable(&lapbeth->napi);
329 		pr_err("lapb_register error: %d\n", err);
330 		return -ENODEV;
331 	}
332 
333 	spin_lock_bh(&lapbeth->up_lock);
334 	lapbeth->up = true;
335 	spin_unlock_bh(&lapbeth->up_lock);
336 
337 	return 0;
338 }
339 
340 static int lapbeth_close(struct net_device *dev)
341 {
342 	struct lapbethdev *lapbeth = netdev_priv(dev);
343 	int err;
344 
345 	spin_lock_bh(&lapbeth->up_lock);
346 	lapbeth->up = false;
347 	spin_unlock_bh(&lapbeth->up_lock);
348 
349 	err = lapb_unregister(dev);
350 	if (err != LAPB_OK)
351 		pr_err("lapb_unregister error: %d\n", err);
352 
353 	napi_disable(&lapbeth->napi);
354 
355 	return 0;
356 }
357 
358 /* ------------------------------------------------------------------------ */
359 
360 static const struct net_device_ops lapbeth_netdev_ops = {
361 	.ndo_open	     = lapbeth_open,
362 	.ndo_stop	     = lapbeth_close,
363 	.ndo_start_xmit	     = lapbeth_xmit,
364 	.ndo_set_mac_address = lapbeth_set_mac_address,
365 };
366 
367 static void lapbeth_setup(struct net_device *dev)
368 {
369 	dev->netdev_ops	     = &lapbeth_netdev_ops;
370 	dev->needs_free_netdev = true;
371 	dev->type            = ARPHRD_X25;
372 	dev->hard_header_len = 0;
373 	dev->mtu             = 1000;
374 	dev->addr_len        = 0;
375 }
376 
377 /*	Setup a new device.
378  */
379 static int lapbeth_new_device(struct net_device *dev)
380 {
381 	struct net_device *ndev;
382 	struct lapbethdev *lapbeth;
383 	int rc = -ENOMEM;
384 
385 	ASSERT_RTNL();
386 
387 	if (dev->type != ARPHRD_ETHER)
388 		return -EINVAL;
389 
390 	ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", NET_NAME_UNKNOWN,
391 			    lapbeth_setup);
392 	if (!ndev)
393 		goto out;
394 
395 	/* When transmitting data:
396 	 * first this driver removes a pseudo header of 1 byte,
397 	 * then the lapb module prepends an LAPB header of at most 3 bytes,
398 	 * then this driver prepends a length field of 2 bytes,
399 	 * then the underlying Ethernet device prepends its own header.
400 	 */
401 	ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len
402 					   + dev->needed_headroom;
403 	ndev->needed_tailroom = dev->needed_tailroom;
404 
405 	lapbeth = netdev_priv(ndev);
406 	lapbeth->axdev = ndev;
407 
408 	dev_hold(dev);
409 	lapbeth->ethdev = dev;
410 
411 	lapbeth->up = false;
412 	spin_lock_init(&lapbeth->up_lock);
413 
414 	skb_queue_head_init(&lapbeth->rx_queue);
415 	netif_napi_add_weight(ndev, &lapbeth->napi, lapbeth_napi_poll, 16);
416 
417 	rc = -EIO;
418 	if (register_netdevice(ndev))
419 		goto fail;
420 
421 	list_add_rcu(&lapbeth->node, &lapbeth_devices);
422 	rc = 0;
423 out:
424 	return rc;
425 fail:
426 	dev_put(dev);
427 	free_netdev(ndev);
428 	goto out;
429 }
430 
431 /*	Free a lapb network device.
432  */
433 static void lapbeth_free_device(struct lapbethdev *lapbeth)
434 {
435 	dev_put(lapbeth->ethdev);
436 	list_del_rcu(&lapbeth->node);
437 	unregister_netdevice(lapbeth->axdev);
438 }
439 
440 /*	Handle device status changes.
441  *
442  * Called from notifier with RTNL held.
443  */
444 static int lapbeth_device_event(struct notifier_block *this,
445 				unsigned long event, void *ptr)
446 {
447 	struct lapbethdev *lapbeth;
448 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
449 
450 	if (dev_net(dev) != &init_net)
451 		return NOTIFY_DONE;
452 
453 	if (!dev_is_ethdev(dev) && !lapbeth_get_x25_dev(dev))
454 		return NOTIFY_DONE;
455 
456 	switch (event) {
457 	case NETDEV_UP:
458 		/* New ethernet device -> new LAPB interface	 */
459 		if (!lapbeth_get_x25_dev(dev))
460 			lapbeth_new_device(dev);
461 		break;
462 	case NETDEV_GOING_DOWN:
463 		/* ethernet device closes -> close LAPB interface */
464 		lapbeth = lapbeth_get_x25_dev(dev);
465 		if (lapbeth)
466 			dev_close(lapbeth->axdev);
467 		break;
468 	case NETDEV_UNREGISTER:
469 		/* ethernet device disappears -> remove LAPB interface */
470 		lapbeth = lapbeth_get_x25_dev(dev);
471 		if (lapbeth)
472 			lapbeth_free_device(lapbeth);
473 		break;
474 	}
475 
476 	return NOTIFY_DONE;
477 }
478 
479 /* ------------------------------------------------------------------------ */
480 
481 static struct packet_type lapbeth_packet_type __read_mostly = {
482 	.type = cpu_to_be16(ETH_P_DEC),
483 	.func = lapbeth_rcv,
484 };
485 
486 static struct notifier_block lapbeth_dev_notifier = {
487 	.notifier_call = lapbeth_device_event,
488 };
489 
490 static const char banner[] __initconst =
491 	KERN_INFO "LAPB Ethernet driver version 0.02\n";
492 
493 static int __init lapbeth_init_driver(void)
494 {
495 	dev_add_pack(&lapbeth_packet_type);
496 
497 	register_netdevice_notifier(&lapbeth_dev_notifier);
498 
499 	printk(banner);
500 
501 	return 0;
502 }
503 module_init(lapbeth_init_driver);
504 
505 static void __exit lapbeth_cleanup_driver(void)
506 {
507 	struct lapbethdev *lapbeth;
508 	struct list_head *entry, *tmp;
509 
510 	dev_remove_pack(&lapbeth_packet_type);
511 	unregister_netdevice_notifier(&lapbeth_dev_notifier);
512 
513 	rtnl_lock();
514 	list_for_each_safe(entry, tmp, &lapbeth_devices) {
515 		lapbeth = list_entry(entry, struct lapbethdev, node);
516 
517 		dev_put(lapbeth->ethdev);
518 		unregister_netdevice(lapbeth->axdev);
519 	}
520 	rtnl_unlock();
521 }
522 module_exit(lapbeth_cleanup_driver);
523 
524 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
525 MODULE_DESCRIPTION("The unofficial LAPB over Ethernet driver");
526 MODULE_LICENSE("GPL");
527