1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * G8BPQ compatible "AX.25 via ethernet" driver release 004 |
4 | * |
5 | * This code REQUIRES 2.0.0 or higher/ NET3.029 |
6 | * |
7 | * This is a "pseudo" network driver to allow AX.25 over Ethernet |
8 | * using G8BPQ encapsulation. It has been extracted from the protocol |
9 | * implementation because |
10 | * |
11 | * - things got unreadable within the protocol stack |
12 | * - to cure the protocol stack from "feature-ism" |
13 | * - a protocol implementation shouldn't need to know on |
14 | * which hardware it is running |
15 | * - user-level programs like the AX.25 utilities shouldn't |
16 | * need to know about the hardware. |
17 | * - IP over ethernet encapsulated AX.25 was impossible |
18 | * - rxecho.c did not work |
19 | * - to have room for extensions |
20 | * - it just deserves to "live" as an own driver |
21 | * |
22 | * This driver can use any ethernet destination address, and can be |
23 | * limited to accept frames from one dedicated ethernet card only. |
24 | * |
25 | * Note that the driver sets up the BPQ devices automagically on |
26 | * startup or (if started before the "insmod" of an ethernet device) |
27 | * on "ifconfig up". It hopefully will remove the BPQ on "rmmod"ing |
28 | * the ethernet device (in fact: as soon as another ethernet or bpq |
29 | * device gets "ifconfig"ured). |
30 | * |
31 | * I have heard that several people are thinking of experiments |
32 | * with highspeed packet radio using existing ethernet cards. |
33 | * Well, this driver is prepared for this purpose, just add |
34 | * your tx key control and a txdelay / tailtime algorithm, |
35 | * probably some buffering, and /voila/... |
36 | * |
37 | * History |
38 | * BPQ 001 Joerg(DL1BKE) Extracted BPQ code from AX.25 |
39 | * protocol stack and added my own |
40 | * yet existing patches |
41 | * BPQ 002 Joerg(DL1BKE) Scan network device list on |
42 | * startup. |
43 | * BPQ 003 Joerg(DL1BKE) Ethernet destination address |
44 | * and accepted source address |
45 | * can be configured by an ioctl() |
46 | * call. |
47 | * Fixed to match Linux networking |
48 | * changes - 2.1.15. |
49 | * BPQ 004 Joerg(DL1BKE) Fixed to not lock up on ifconfig. |
50 | */ |
51 | |
52 | #include <linux/errno.h> |
53 | #include <linux/types.h> |
54 | #include <linux/socket.h> |
55 | #include <linux/in.h> |
56 | #include <linux/kernel.h> |
57 | #include <linux/string.h> |
58 | #include <linux/net.h> |
59 | #include <linux/slab.h> |
60 | #include <net/ax25.h> |
61 | #include <linux/inet.h> |
62 | #include <linux/netdevice.h> |
63 | #include <linux/etherdevice.h> |
64 | #include <linux/if_arp.h> |
65 | #include <linux/skbuff.h> |
66 | #include <net/sock.h> |
67 | #include <linux/uaccess.h> |
68 | #include <linux/mm.h> |
69 | #include <linux/interrupt.h> |
70 | #include <linux/notifier.h> |
71 | #include <linux/proc_fs.h> |
72 | #include <linux/seq_file.h> |
73 | #include <linux/stat.h> |
74 | #include <linux/module.h> |
75 | #include <linux/init.h> |
76 | #include <linux/rtnetlink.h> |
77 | |
78 | #include <net/ip.h> |
79 | #include <net/arp.h> |
80 | #include <net/net_namespace.h> |
81 | |
82 | #include <linux/bpqether.h> |
83 | |
84 | static const char banner[] __initconst = KERN_INFO \ |
85 | "AX.25: bpqether driver version 004\n" ; |
86 | |
87 | static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); |
88 | static int bpq_device_event(struct notifier_block *, unsigned long, void *); |
89 | |
90 | static struct packet_type bpq_packet_type __read_mostly = { |
91 | .type = cpu_to_be16(ETH_P_BPQ), |
92 | .func = bpq_rcv, |
93 | }; |
94 | |
95 | static struct notifier_block bpq_dev_notifier = { |
96 | .notifier_call = bpq_device_event, |
97 | }; |
98 | |
99 | |
100 | struct bpqdev { |
101 | struct list_head bpq_list; /* list of bpq devices chain */ |
102 | struct net_device *ethdev; /* link to ethernet device */ |
103 | struct net_device *axdev; /* bpq device (bpq#) */ |
104 | char dest_addr[6]; /* ether destination address */ |
105 | char acpt_addr[6]; /* accept ether frames from this address only */ |
106 | }; |
107 | |
108 | static LIST_HEAD(bpq_devices); |
109 | |
110 | /* |
111 | * bpqether network devices are paired with ethernet devices below them, so |
112 | * form a special "super class" of normal ethernet devices; split their locks |
113 | * off into a separate class since they always nest. |
114 | */ |
115 | static struct lock_class_key bpq_netdev_xmit_lock_key; |
116 | static struct lock_class_key bpq_netdev_addr_lock_key; |
117 | |
118 | static void bpq_set_lockdep_class_one(struct net_device *dev, |
119 | struct netdev_queue *txq, |
120 | void *_unused) |
121 | { |
122 | lockdep_set_class(&txq->_xmit_lock, &bpq_netdev_xmit_lock_key); |
123 | } |
124 | |
125 | static void bpq_set_lockdep_class(struct net_device *dev) |
126 | { |
127 | lockdep_set_class(&dev->addr_list_lock, &bpq_netdev_addr_lock_key); |
128 | netdev_for_each_tx_queue(dev, f: bpq_set_lockdep_class_one, NULL); |
129 | } |
130 | |
131 | /* ------------------------------------------------------------------------ */ |
132 | |
133 | |
134 | /* |
135 | * Get the ethernet device for a BPQ device |
136 | */ |
137 | static inline struct net_device *bpq_get_ether_dev(struct net_device *dev) |
138 | { |
139 | struct bpqdev *bpq = netdev_priv(dev); |
140 | |
141 | return bpq ? bpq->ethdev : NULL; |
142 | } |
143 | |
144 | /* |
145 | * Get the BPQ device for the ethernet device |
146 | */ |
147 | static inline struct net_device *bpq_get_ax25_dev(struct net_device *dev) |
148 | { |
149 | struct bpqdev *bpq; |
150 | |
151 | list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list, |
152 | lockdep_rtnl_is_held()) { |
153 | if (bpq->ethdev == dev) |
154 | return bpq->axdev; |
155 | } |
156 | return NULL; |
157 | } |
158 | |
159 | static inline int dev_is_ethdev(struct net_device *dev) |
160 | { |
161 | return dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy" , 5); |
162 | } |
163 | |
164 | /* ------------------------------------------------------------------------ */ |
165 | |
166 | |
167 | /* |
168 | * Receive an AX.25 frame via an ethernet interface. |
169 | */ |
170 | static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) |
171 | { |
172 | int len; |
173 | char * ptr; |
174 | struct ethhdr *eth; |
175 | struct bpqdev *bpq; |
176 | |
177 | if (!net_eq(net1: dev_net(dev), net2: &init_net)) |
178 | goto drop; |
179 | |
180 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) |
181 | return NET_RX_DROP; |
182 | |
183 | if (!pskb_may_pull(skb, len: sizeof(struct ethhdr))) |
184 | goto drop; |
185 | |
186 | rcu_read_lock(); |
187 | dev = bpq_get_ax25_dev(dev); |
188 | |
189 | if (dev == NULL || !netif_running(dev)) |
190 | goto drop_unlock; |
191 | |
192 | /* |
193 | * if we want to accept frames from just one ethernet device |
194 | * we check the source address of the sender. |
195 | */ |
196 | |
197 | bpq = netdev_priv(dev); |
198 | |
199 | eth = eth_hdr(skb); |
200 | |
201 | if (!(bpq->acpt_addr[0] & 0x01) && |
202 | !ether_addr_equal(addr1: eth->h_source, addr2: bpq->acpt_addr)) |
203 | goto drop_unlock; |
204 | |
205 | if (skb_cow(skb, headroom: sizeof(struct ethhdr))) |
206 | goto drop_unlock; |
207 | |
208 | len = skb->data[0] + skb->data[1] * 256 - 5; |
209 | |
210 | skb_pull(skb, len: 2); /* Remove the length bytes */ |
211 | skb_trim(skb, len); /* Set the length of the data */ |
212 | |
213 | dev->stats.rx_packets++; |
214 | dev->stats.rx_bytes += len; |
215 | |
216 | ptr = skb_push(skb, len: 1); |
217 | *ptr = 0; |
218 | |
219 | skb->protocol = ax25_type_trans(skb, dev); |
220 | netif_rx(skb); |
221 | unlock: |
222 | |
223 | rcu_read_unlock(); |
224 | |
225 | return 0; |
226 | drop_unlock: |
227 | kfree_skb(skb); |
228 | goto unlock; |
229 | |
230 | drop: |
231 | kfree_skb(skb); |
232 | return 0; |
233 | } |
234 | |
235 | /* |
236 | * Send an AX.25 frame via an ethernet interface |
237 | */ |
238 | static netdev_tx_t bpq_xmit(struct sk_buff *skb, struct net_device *dev) |
239 | { |
240 | unsigned char *ptr; |
241 | struct bpqdev *bpq; |
242 | struct net_device *orig_dev; |
243 | int size; |
244 | |
245 | if (skb->protocol == htons(ETH_P_IP)) |
246 | return ax25_ip_xmit(skb); |
247 | |
248 | /* |
249 | * Just to be *really* sure not to send anything if the interface |
250 | * is down, the ethernet device may have gone. |
251 | */ |
252 | if (!netif_running(dev)) { |
253 | kfree_skb(skb); |
254 | return NETDEV_TX_OK; |
255 | } |
256 | |
257 | skb_pull(skb, len: 1); /* Drop KISS byte */ |
258 | size = skb->len; |
259 | |
260 | /* |
261 | * We're about to mess with the skb which may still shared with the |
262 | * generic networking code so unshare and ensure it's got enough |
263 | * space for the BPQ headers. |
264 | */ |
265 | if (skb_cow(skb, AX25_BPQ_HEADER_LEN)) { |
266 | if (net_ratelimit()) |
267 | pr_err("bpqether: out of memory\n" ); |
268 | kfree_skb(skb); |
269 | |
270 | return NETDEV_TX_OK; |
271 | } |
272 | |
273 | ptr = skb_push(skb, len: 2); /* Make space for length */ |
274 | |
275 | *ptr++ = (size + 5) % 256; |
276 | *ptr++ = (size + 5) / 256; |
277 | |
278 | bpq = netdev_priv(dev); |
279 | |
280 | orig_dev = dev; |
281 | if ((dev = bpq_get_ether_dev(dev)) == NULL) { |
282 | orig_dev->stats.tx_dropped++; |
283 | kfree_skb(skb); |
284 | return NETDEV_TX_OK; |
285 | } |
286 | |
287 | skb->protocol = ax25_type_trans(skb, dev); |
288 | skb_reset_network_header(skb); |
289 | dev_hard_header(skb, dev, ETH_P_BPQ, daddr: bpq->dest_addr, NULL, len: 0); |
290 | dev->stats.tx_packets++; |
291 | dev->stats.tx_bytes+=skb->len; |
292 | |
293 | dev_queue_xmit(skb); |
294 | netif_wake_queue(dev); |
295 | return NETDEV_TX_OK; |
296 | } |
297 | |
298 | /* |
299 | * Set AX.25 callsign |
300 | */ |
301 | static int bpq_set_mac_address(struct net_device *dev, void *addr) |
302 | { |
303 | struct sockaddr *sa = (struct sockaddr *)addr; |
304 | |
305 | dev_addr_set(dev, addr: sa->sa_data); |
306 | |
307 | return 0; |
308 | } |
309 | |
310 | /* Ioctl commands |
311 | * |
312 | * SIOCSBPQETHOPT reserved for enhancements |
313 | * SIOCSBPQETHADDR set the destination and accepted |
314 | * source ethernet address (broadcast |
315 | * or multicast: accept all) |
316 | */ |
317 | static int bpq_siocdevprivate(struct net_device *dev, struct ifreq *ifr, |
318 | void __user *data, int cmd) |
319 | { |
320 | struct bpq_ethaddr __user *ethaddr = data; |
321 | struct bpqdev *bpq = netdev_priv(dev); |
322 | struct bpq_req req; |
323 | |
324 | if (!capable(CAP_NET_ADMIN)) |
325 | return -EPERM; |
326 | |
327 | switch (cmd) { |
328 | case SIOCSBPQETHOPT: |
329 | if (copy_from_user(to: &req, from: data, n: sizeof(struct bpq_req))) |
330 | return -EFAULT; |
331 | switch (req.cmd) { |
332 | case SIOCGBPQETHPARAM: |
333 | case SIOCSBPQETHPARAM: |
334 | default: |
335 | return -EINVAL; |
336 | } |
337 | |
338 | break; |
339 | |
340 | case SIOCSBPQETHADDR: |
341 | if (copy_from_user(to: bpq->dest_addr, from: ethaddr->destination, ETH_ALEN)) |
342 | return -EFAULT; |
343 | if (copy_from_user(to: bpq->acpt_addr, from: ethaddr->accept, ETH_ALEN)) |
344 | return -EFAULT; |
345 | break; |
346 | |
347 | default: |
348 | return -EINVAL; |
349 | } |
350 | |
351 | return 0; |
352 | } |
353 | |
354 | /* |
355 | * open/close a device |
356 | */ |
357 | static int bpq_open(struct net_device *dev) |
358 | { |
359 | netif_start_queue(dev); |
360 | return 0; |
361 | } |
362 | |
363 | static int bpq_close(struct net_device *dev) |
364 | { |
365 | netif_stop_queue(dev); |
366 | return 0; |
367 | } |
368 | |
369 | |
370 | /* ------------------------------------------------------------------------ */ |
371 | |
372 | #ifdef CONFIG_PROC_FS |
373 | /* |
374 | * Proc filesystem |
375 | */ |
376 | static void *bpq_seq_start(struct seq_file *seq, loff_t *pos) |
377 | __acquires(RCU) |
378 | { |
379 | int i = 1; |
380 | struct bpqdev *bpqdev; |
381 | |
382 | rcu_read_lock(); |
383 | |
384 | if (*pos == 0) |
385 | return SEQ_START_TOKEN; |
386 | |
387 | list_for_each_entry_rcu(bpqdev, &bpq_devices, bpq_list) { |
388 | if (i == *pos) |
389 | return bpqdev; |
390 | } |
391 | return NULL; |
392 | } |
393 | |
394 | static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
395 | { |
396 | struct list_head *p; |
397 | struct bpqdev *bpqdev = v; |
398 | |
399 | ++*pos; |
400 | |
401 | if (v == SEQ_START_TOKEN) |
402 | p = rcu_dereference(list_next_rcu(&bpq_devices)); |
403 | else |
404 | p = rcu_dereference(list_next_rcu(&bpqdev->bpq_list)); |
405 | |
406 | return (p == &bpq_devices) ? NULL |
407 | : list_entry(p, struct bpqdev, bpq_list); |
408 | } |
409 | |
410 | static void bpq_seq_stop(struct seq_file *seq, void *v) |
411 | __releases(RCU) |
412 | { |
413 | rcu_read_unlock(); |
414 | } |
415 | |
416 | |
417 | static int bpq_seq_show(struct seq_file *seq, void *v) |
418 | { |
419 | if (v == SEQ_START_TOKEN) |
420 | seq_puts(m: seq, |
421 | s: "dev ether destination accept from\n" ); |
422 | else { |
423 | const struct bpqdev *bpqdev = v; |
424 | |
425 | seq_printf(m: seq, fmt: "%-5s %-10s %pM " , |
426 | bpqdev->axdev->name, bpqdev->ethdev->name, |
427 | bpqdev->dest_addr); |
428 | |
429 | if (is_multicast_ether_addr(addr: bpqdev->acpt_addr)) |
430 | seq_printf(m: seq, fmt: "*\n" ); |
431 | else |
432 | seq_printf(m: seq, fmt: "%pM\n" , bpqdev->acpt_addr); |
433 | |
434 | } |
435 | return 0; |
436 | } |
437 | |
438 | static const struct seq_operations bpq_seqops = { |
439 | .start = bpq_seq_start, |
440 | .next = bpq_seq_next, |
441 | .stop = bpq_seq_stop, |
442 | .show = bpq_seq_show, |
443 | }; |
444 | #endif |
445 | /* ------------------------------------------------------------------------ */ |
446 | |
447 | static const struct net_device_ops bpq_netdev_ops = { |
448 | .ndo_open = bpq_open, |
449 | .ndo_stop = bpq_close, |
450 | .ndo_start_xmit = bpq_xmit, |
451 | .ndo_set_mac_address = bpq_set_mac_address, |
452 | .ndo_siocdevprivate = bpq_siocdevprivate, |
453 | }; |
454 | |
455 | static void bpq_setup(struct net_device *dev) |
456 | { |
457 | dev->netdev_ops = &bpq_netdev_ops; |
458 | dev->needs_free_netdev = true; |
459 | |
460 | dev->flags = 0; |
461 | dev->features = NETIF_F_LLTX; /* Allow recursion */ |
462 | |
463 | #if IS_ENABLED(CONFIG_AX25) |
464 | dev->header_ops = &ax25_header_ops; |
465 | #endif |
466 | |
467 | dev->type = ARPHRD_AX25; |
468 | dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN; |
469 | dev->mtu = AX25_DEF_PACLEN; |
470 | dev->addr_len = AX25_ADDR_LEN; |
471 | |
472 | memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN); |
473 | dev_addr_set(dev, addr: (u8 *)&ax25_defaddr); |
474 | } |
475 | |
476 | /* |
477 | * Setup a new device. |
478 | */ |
479 | static int bpq_new_device(struct net_device *edev) |
480 | { |
481 | int err; |
482 | struct net_device *ndev; |
483 | struct bpqdev *bpq; |
484 | |
485 | ndev = alloc_netdev(sizeof(struct bpqdev), "bpq%d" , NET_NAME_UNKNOWN, |
486 | bpq_setup); |
487 | if (!ndev) |
488 | return -ENOMEM; |
489 | |
490 | |
491 | bpq = netdev_priv(dev: ndev); |
492 | dev_hold(dev: edev); |
493 | bpq->ethdev = edev; |
494 | bpq->axdev = ndev; |
495 | |
496 | eth_broadcast_addr(addr: bpq->dest_addr); |
497 | eth_broadcast_addr(addr: bpq->acpt_addr); |
498 | |
499 | err = register_netdevice(dev: ndev); |
500 | if (err) |
501 | goto error; |
502 | bpq_set_lockdep_class(dev: ndev); |
503 | |
504 | /* List protected by RTNL */ |
505 | list_add_rcu(new: &bpq->bpq_list, head: &bpq_devices); |
506 | return 0; |
507 | |
508 | error: |
509 | dev_put(dev: edev); |
510 | free_netdev(dev: ndev); |
511 | return err; |
512 | |
513 | } |
514 | |
515 | static void bpq_free_device(struct net_device *ndev) |
516 | { |
517 | struct bpqdev *bpq = netdev_priv(dev: ndev); |
518 | |
519 | dev_put(dev: bpq->ethdev); |
520 | list_del_rcu(entry: &bpq->bpq_list); |
521 | |
522 | unregister_netdevice(dev: ndev); |
523 | } |
524 | |
525 | /* |
526 | * Handle device status changes. |
527 | */ |
528 | static int bpq_device_event(struct notifier_block *this, |
529 | unsigned long event, void *ptr) |
530 | { |
531 | struct net_device *dev = netdev_notifier_info_to_dev(info: ptr); |
532 | |
533 | if (!net_eq(net1: dev_net(dev), net2: &init_net)) |
534 | return NOTIFY_DONE; |
535 | |
536 | if (!dev_is_ethdev(dev) && !bpq_get_ax25_dev(dev)) |
537 | return NOTIFY_DONE; |
538 | |
539 | switch (event) { |
540 | case NETDEV_UP: /* new ethernet device -> new BPQ interface */ |
541 | if (bpq_get_ax25_dev(dev) == NULL) |
542 | bpq_new_device(edev: dev); |
543 | break; |
544 | |
545 | case NETDEV_DOWN: /* ethernet device closed -> close BPQ interface */ |
546 | if ((dev = bpq_get_ax25_dev(dev)) != NULL) |
547 | dev_close(dev); |
548 | break; |
549 | |
550 | case NETDEV_UNREGISTER: /* ethernet device removed -> free BPQ interface */ |
551 | if ((dev = bpq_get_ax25_dev(dev)) != NULL) |
552 | bpq_free_device(ndev: dev); |
553 | break; |
554 | default: |
555 | break; |
556 | } |
557 | |
558 | return NOTIFY_DONE; |
559 | } |
560 | |
561 | |
562 | /* ------------------------------------------------------------------------ */ |
563 | |
564 | /* |
565 | * Initialize driver. To be called from af_ax25 if not compiled as a |
566 | * module |
567 | */ |
568 | static int __init bpq_init_driver(void) |
569 | { |
570 | #ifdef CONFIG_PROC_FS |
571 | if (!proc_create_seq("bpqether" , 0444, init_net.proc_net, &bpq_seqops)) { |
572 | printk(KERN_ERR |
573 | "bpq: cannot create /proc/net/bpqether entry.\n" ); |
574 | return -ENOENT; |
575 | } |
576 | #endif /* CONFIG_PROC_FS */ |
577 | |
578 | dev_add_pack(pt: &bpq_packet_type); |
579 | |
580 | register_netdevice_notifier(nb: &bpq_dev_notifier); |
581 | |
582 | printk(banner); |
583 | |
584 | return 0; |
585 | } |
586 | |
587 | static void __exit bpq_cleanup_driver(void) |
588 | { |
589 | struct bpqdev *bpq; |
590 | |
591 | dev_remove_pack(pt: &bpq_packet_type); |
592 | |
593 | unregister_netdevice_notifier(nb: &bpq_dev_notifier); |
594 | |
595 | remove_proc_entry("bpqether" , init_net.proc_net); |
596 | |
597 | rtnl_lock(); |
598 | while (!list_empty(head: &bpq_devices)) { |
599 | bpq = list_entry(bpq_devices.next, struct bpqdev, bpq_list); |
600 | bpq_free_device(ndev: bpq->axdev); |
601 | } |
602 | rtnl_unlock(); |
603 | } |
604 | |
605 | MODULE_AUTHOR("Joerg Reuter DL1BKE <jreuter@yaina.de>" ); |
606 | MODULE_DESCRIPTION("Transmit and receive AX.25 packets over Ethernet" ); |
607 | MODULE_LICENSE("GPL" ); |
608 | module_init(bpq_init_driver); |
609 | module_exit(bpq_cleanup_driver); |
610 | |