xref: /openbmc/linux/drivers/net/wan/lapbether.c (revision 8e7a49e0)
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 	ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", NET_NAME_UNKNOWN,
388 			    lapbeth_setup);
389 	if (!ndev)
390 		goto out;
391 
392 	/* When transmitting data:
393 	 * first this driver removes a pseudo header of 1 byte,
394 	 * then the lapb module prepends an LAPB header of at most 3 bytes,
395 	 * then this driver prepends a length field of 2 bytes,
396 	 * then the underlying Ethernet device prepends its own header.
397 	 */
398 	ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len
399 					   + dev->needed_headroom;
400 	ndev->needed_tailroom = dev->needed_tailroom;
401 
402 	lapbeth = netdev_priv(ndev);
403 	lapbeth->axdev = ndev;
404 
405 	dev_hold(dev);
406 	lapbeth->ethdev = dev;
407 
408 	lapbeth->up = false;
409 	spin_lock_init(&lapbeth->up_lock);
410 
411 	skb_queue_head_init(&lapbeth->rx_queue);
412 	netif_napi_add_weight(ndev, &lapbeth->napi, lapbeth_napi_poll, 16);
413 
414 	rc = -EIO;
415 	if (register_netdevice(ndev))
416 		goto fail;
417 
418 	list_add_rcu(&lapbeth->node, &lapbeth_devices);
419 	rc = 0;
420 out:
421 	return rc;
422 fail:
423 	dev_put(dev);
424 	free_netdev(ndev);
425 	goto out;
426 }
427 
428 /*	Free a lapb network device.
429  */
430 static void lapbeth_free_device(struct lapbethdev *lapbeth)
431 {
432 	dev_put(lapbeth->ethdev);
433 	list_del_rcu(&lapbeth->node);
434 	unregister_netdevice(lapbeth->axdev);
435 }
436 
437 /*	Handle device status changes.
438  *
439  * Called from notifier with RTNL held.
440  */
441 static int lapbeth_device_event(struct notifier_block *this,
442 				unsigned long event, void *ptr)
443 {
444 	struct lapbethdev *lapbeth;
445 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
446 
447 	if (dev_net(dev) != &init_net)
448 		return NOTIFY_DONE;
449 
450 	if (!dev_is_ethdev(dev) && !lapbeth_get_x25_dev(dev))
451 		return NOTIFY_DONE;
452 
453 	switch (event) {
454 	case NETDEV_UP:
455 		/* New ethernet device -> new LAPB interface	 */
456 		if (!lapbeth_get_x25_dev(dev))
457 			lapbeth_new_device(dev);
458 		break;
459 	case NETDEV_GOING_DOWN:
460 		/* ethernet device closes -> close LAPB interface */
461 		lapbeth = lapbeth_get_x25_dev(dev);
462 		if (lapbeth)
463 			dev_close(lapbeth->axdev);
464 		break;
465 	case NETDEV_UNREGISTER:
466 		/* ethernet device disappears -> remove LAPB interface */
467 		lapbeth = lapbeth_get_x25_dev(dev);
468 		if (lapbeth)
469 			lapbeth_free_device(lapbeth);
470 		break;
471 	}
472 
473 	return NOTIFY_DONE;
474 }
475 
476 /* ------------------------------------------------------------------------ */
477 
478 static struct packet_type lapbeth_packet_type __read_mostly = {
479 	.type = cpu_to_be16(ETH_P_DEC),
480 	.func = lapbeth_rcv,
481 };
482 
483 static struct notifier_block lapbeth_dev_notifier = {
484 	.notifier_call = lapbeth_device_event,
485 };
486 
487 static const char banner[] __initconst =
488 	KERN_INFO "LAPB Ethernet driver version 0.02\n";
489 
490 static int __init lapbeth_init_driver(void)
491 {
492 	dev_add_pack(&lapbeth_packet_type);
493 
494 	register_netdevice_notifier(&lapbeth_dev_notifier);
495 
496 	printk(banner);
497 
498 	return 0;
499 }
500 module_init(lapbeth_init_driver);
501 
502 static void __exit lapbeth_cleanup_driver(void)
503 {
504 	struct lapbethdev *lapbeth;
505 	struct list_head *entry, *tmp;
506 
507 	dev_remove_pack(&lapbeth_packet_type);
508 	unregister_netdevice_notifier(&lapbeth_dev_notifier);
509 
510 	rtnl_lock();
511 	list_for_each_safe(entry, tmp, &lapbeth_devices) {
512 		lapbeth = list_entry(entry, struct lapbethdev, node);
513 
514 		dev_put(lapbeth->ethdev);
515 		unregister_netdevice(lapbeth->axdev);
516 	}
517 	rtnl_unlock();
518 }
519 module_exit(lapbeth_cleanup_driver);
520 
521 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
522 MODULE_DESCRIPTION("The unofficial LAPB over Ethernet driver");
523 MODULE_LICENSE("GPL");
524