Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  "LAPB via ethernet" driver release 001
0004  *
0005  *  This code REQUIRES 2.1.15 or higher/ NET3.038
0006  *
0007  *  This is a "pseudo" network driver to allow LAPB over Ethernet.
0008  *
0009  *  This driver can use any ethernet destination address, and can be
0010  *  limited to accept frames from one dedicated ethernet card only.
0011  *
0012  *  History
0013  *  LAPBETH 001 Jonathan Naylor     Cloned from bpqether.c
0014  *  2000-10-29  Henner Eisen    lapb_data_indication() return status.
0015  *  2000-11-14  Henner Eisen    dev_hold/put, NETDEV_GOING_DOWN support
0016  */
0017 
0018 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0019 
0020 #include <linux/errno.h>
0021 #include <linux/types.h>
0022 #include <linux/socket.h>
0023 #include <linux/in.h>
0024 #include <linux/slab.h>
0025 #include <linux/kernel.h>
0026 #include <linux/string.h>
0027 #include <linux/net.h>
0028 #include <linux/inet.h>
0029 #include <linux/netdevice.h>
0030 #include <linux/if_arp.h>
0031 #include <linux/skbuff.h>
0032 #include <net/sock.h>
0033 #include <linux/uaccess.h>
0034 #include <linux/mm.h>
0035 #include <linux/interrupt.h>
0036 #include <linux/notifier.h>
0037 #include <linux/stat.h>
0038 #include <linux/module.h>
0039 #include <linux/lapb.h>
0040 #include <linux/init.h>
0041 
0042 #include <net/x25device.h>
0043 
0044 static const u8 bcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
0045 
0046 /* If this number is made larger, check that the temporary string buffer
0047  * in lapbeth_new_device is large enough to store the probe device name.
0048  */
0049 #define MAXLAPBDEV 100
0050 
0051 struct lapbethdev {
0052     struct list_head    node;
0053     struct net_device   *ethdev;    /* link to ethernet device */
0054     struct net_device   *axdev;     /* lapbeth device (lapb#) */
0055     bool            up;
0056     spinlock_t      up_lock;    /* Protects "up" */
0057     struct sk_buff_head rx_queue;
0058     struct napi_struct  napi;
0059 };
0060 
0061 static LIST_HEAD(lapbeth_devices);
0062 
0063 static void lapbeth_connected(struct net_device *dev, int reason);
0064 static void lapbeth_disconnected(struct net_device *dev, int reason);
0065 
0066 /* ------------------------------------------------------------------------ */
0067 
0068 /*  Get the LAPB device for the ethernet device
0069  */
0070 static struct lapbethdev *lapbeth_get_x25_dev(struct net_device *dev)
0071 {
0072     struct lapbethdev *lapbeth;
0073 
0074     list_for_each_entry_rcu(lapbeth, &lapbeth_devices, node, lockdep_rtnl_is_held()) {
0075         if (lapbeth->ethdev == dev)
0076             return lapbeth;
0077     }
0078     return NULL;
0079 }
0080 
0081 static __inline__ int dev_is_ethdev(struct net_device *dev)
0082 {
0083     return dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5);
0084 }
0085 
0086 /* ------------------------------------------------------------------------ */
0087 
0088 static int lapbeth_napi_poll(struct napi_struct *napi, int budget)
0089 {
0090     struct lapbethdev *lapbeth = container_of(napi, struct lapbethdev,
0091                           napi);
0092     struct sk_buff *skb;
0093     int processed = 0;
0094 
0095     for (; processed < budget; ++processed) {
0096         skb = skb_dequeue(&lapbeth->rx_queue);
0097         if (!skb)
0098             break;
0099         netif_receive_skb_core(skb);
0100     }
0101 
0102     if (processed < budget)
0103         napi_complete(napi);
0104 
0105     return processed;
0106 }
0107 
0108 /*  Receive a LAPB frame via an ethernet interface.
0109  */
0110 static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev,
0111                struct packet_type *ptype, struct net_device *orig_dev)
0112 {
0113     int len, err;
0114     struct lapbethdev *lapbeth;
0115 
0116     if (dev_net(dev) != &init_net)
0117         goto drop;
0118 
0119     skb = skb_share_check(skb, GFP_ATOMIC);
0120     if (!skb)
0121         return NET_RX_DROP;
0122 
0123     if (!pskb_may_pull(skb, 2))
0124         goto drop;
0125 
0126     rcu_read_lock();
0127     lapbeth = lapbeth_get_x25_dev(dev);
0128     if (!lapbeth)
0129         goto drop_unlock_rcu;
0130     spin_lock_bh(&lapbeth->up_lock);
0131     if (!lapbeth->up)
0132         goto drop_unlock;
0133 
0134     len = skb->data[0] + skb->data[1] * 256;
0135     dev->stats.rx_packets++;
0136     dev->stats.rx_bytes += len;
0137 
0138     skb_pull(skb, 2);   /* Remove the length bytes */
0139     skb_trim(skb, len); /* Set the length of the data */
0140 
0141     err = lapb_data_received(lapbeth->axdev, skb);
0142     if (err != LAPB_OK) {
0143         printk(KERN_DEBUG "lapbether: lapb_data_received err - %d\n", err);
0144         goto drop_unlock;
0145     }
0146 out:
0147     spin_unlock_bh(&lapbeth->up_lock);
0148     rcu_read_unlock();
0149     return 0;
0150 drop_unlock:
0151     kfree_skb(skb);
0152     goto out;
0153 drop_unlock_rcu:
0154     rcu_read_unlock();
0155 drop:
0156     kfree_skb(skb);
0157     return 0;
0158 }
0159 
0160 static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb)
0161 {
0162     struct lapbethdev *lapbeth = netdev_priv(dev);
0163     unsigned char *ptr;
0164 
0165     if (skb_cow(skb, 1)) {
0166         kfree_skb(skb);
0167         return NET_RX_DROP;
0168     }
0169 
0170     skb_push(skb, 1);
0171 
0172     ptr  = skb->data;
0173     *ptr = X25_IFACE_DATA;
0174 
0175     skb->protocol = x25_type_trans(skb, dev);
0176 
0177     skb_queue_tail(&lapbeth->rx_queue, skb);
0178     napi_schedule(&lapbeth->napi);
0179     return NET_RX_SUCCESS;
0180 }
0181 
0182 /*  Send a LAPB frame via an ethernet interface
0183  */
0184 static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
0185                 struct net_device *dev)
0186 {
0187     struct lapbethdev *lapbeth = netdev_priv(dev);
0188     int err;
0189 
0190     spin_lock_bh(&lapbeth->up_lock);
0191     if (!lapbeth->up)
0192         goto drop;
0193 
0194     /* There should be a pseudo header of 1 byte added by upper layers.
0195      * Check to make sure it is there before reading it.
0196      */
0197     if (skb->len < 1)
0198         goto drop;
0199 
0200     switch (skb->data[0]) {
0201     case X25_IFACE_DATA:
0202         break;
0203     case X25_IFACE_CONNECT:
0204         err = lapb_connect_request(dev);
0205         if (err == LAPB_CONNECTED)
0206             lapbeth_connected(dev, LAPB_OK);
0207         else if (err != LAPB_OK)
0208             pr_err("lapb_connect_request error: %d\n", err);
0209         goto drop;
0210     case X25_IFACE_DISCONNECT:
0211         err = lapb_disconnect_request(dev);
0212         if (err == LAPB_NOTCONNECTED)
0213             lapbeth_disconnected(dev, LAPB_OK);
0214         else if (err != LAPB_OK)
0215             pr_err("lapb_disconnect_request err: %d\n", err);
0216         fallthrough;
0217     default:
0218         goto drop;
0219     }
0220 
0221     skb_pull(skb, 1);
0222 
0223     err = lapb_data_request(dev, skb);
0224     if (err != LAPB_OK) {
0225         pr_err("lapb_data_request error - %d\n", err);
0226         goto drop;
0227     }
0228 out:
0229     spin_unlock_bh(&lapbeth->up_lock);
0230     return NETDEV_TX_OK;
0231 drop:
0232     kfree_skb(skb);
0233     goto out;
0234 }
0235 
0236 static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb)
0237 {
0238     struct lapbethdev *lapbeth = netdev_priv(ndev);
0239     unsigned char *ptr;
0240     struct net_device *dev;
0241     int size = skb->len;
0242 
0243     ptr = skb_push(skb, 2);
0244 
0245     *ptr++ = size % 256;
0246     *ptr++ = size / 256;
0247 
0248     ndev->stats.tx_packets++;
0249     ndev->stats.tx_bytes += size;
0250 
0251     skb->dev = dev = lapbeth->ethdev;
0252 
0253     skb->protocol = htons(ETH_P_DEC);
0254 
0255     skb_reset_network_header(skb);
0256 
0257     dev_hard_header(skb, dev, ETH_P_DEC, bcast_addr, NULL, 0);
0258 
0259     dev_queue_xmit(skb);
0260 }
0261 
0262 static void lapbeth_connected(struct net_device *dev, int reason)
0263 {
0264     struct lapbethdev *lapbeth = netdev_priv(dev);
0265     unsigned char *ptr;
0266     struct sk_buff *skb = __dev_alloc_skb(1, GFP_ATOMIC | __GFP_NOMEMALLOC);
0267 
0268     if (!skb)
0269         return;
0270 
0271     ptr  = skb_put(skb, 1);
0272     *ptr = X25_IFACE_CONNECT;
0273 
0274     skb->protocol = x25_type_trans(skb, dev);
0275 
0276     skb_queue_tail(&lapbeth->rx_queue, skb);
0277     napi_schedule(&lapbeth->napi);
0278 }
0279 
0280 static void lapbeth_disconnected(struct net_device *dev, int reason)
0281 {
0282     struct lapbethdev *lapbeth = netdev_priv(dev);
0283     unsigned char *ptr;
0284     struct sk_buff *skb = __dev_alloc_skb(1, GFP_ATOMIC | __GFP_NOMEMALLOC);
0285 
0286     if (!skb)
0287         return;
0288 
0289     ptr  = skb_put(skb, 1);
0290     *ptr = X25_IFACE_DISCONNECT;
0291 
0292     skb->protocol = x25_type_trans(skb, dev);
0293 
0294     skb_queue_tail(&lapbeth->rx_queue, skb);
0295     napi_schedule(&lapbeth->napi);
0296 }
0297 
0298 /*  Set AX.25 callsign
0299  */
0300 static int lapbeth_set_mac_address(struct net_device *dev, void *addr)
0301 {
0302     struct sockaddr *sa = addr;
0303 
0304     dev_addr_set(dev, sa->sa_data);
0305     return 0;
0306 }
0307 
0308 static const struct lapb_register_struct lapbeth_callbacks = {
0309     .connect_confirmation    = lapbeth_connected,
0310     .connect_indication      = lapbeth_connected,
0311     .disconnect_confirmation = lapbeth_disconnected,
0312     .disconnect_indication   = lapbeth_disconnected,
0313     .data_indication         = lapbeth_data_indication,
0314     .data_transmit           = lapbeth_data_transmit,
0315 };
0316 
0317 /* open/close a device
0318  */
0319 static int lapbeth_open(struct net_device *dev)
0320 {
0321     struct lapbethdev *lapbeth = netdev_priv(dev);
0322     int err;
0323 
0324     napi_enable(&lapbeth->napi);
0325 
0326     err = lapb_register(dev, &lapbeth_callbacks);
0327     if (err != LAPB_OK) {
0328         pr_err("lapb_register error: %d\n", err);
0329         return -ENODEV;
0330     }
0331 
0332     spin_lock_bh(&lapbeth->up_lock);
0333     lapbeth->up = true;
0334     spin_unlock_bh(&lapbeth->up_lock);
0335 
0336     return 0;
0337 }
0338 
0339 static int lapbeth_close(struct net_device *dev)
0340 {
0341     struct lapbethdev *lapbeth = netdev_priv(dev);
0342     int err;
0343 
0344     spin_lock_bh(&lapbeth->up_lock);
0345     lapbeth->up = false;
0346     spin_unlock_bh(&lapbeth->up_lock);
0347 
0348     err = lapb_unregister(dev);
0349     if (err != LAPB_OK)
0350         pr_err("lapb_unregister error: %d\n", err);
0351 
0352     napi_disable(&lapbeth->napi);
0353 
0354     return 0;
0355 }
0356 
0357 /* ------------------------------------------------------------------------ */
0358 
0359 static const struct net_device_ops lapbeth_netdev_ops = {
0360     .ndo_open        = lapbeth_open,
0361     .ndo_stop        = lapbeth_close,
0362     .ndo_start_xmit      = lapbeth_xmit,
0363     .ndo_set_mac_address = lapbeth_set_mac_address,
0364 };
0365 
0366 static void lapbeth_setup(struct net_device *dev)
0367 {
0368     dev->netdev_ops      = &lapbeth_netdev_ops;
0369     dev->needs_free_netdev = true;
0370     dev->type            = ARPHRD_X25;
0371     dev->hard_header_len = 0;
0372     dev->mtu             = 1000;
0373     dev->addr_len        = 0;
0374 }
0375 
0376 /*  Setup a new device.
0377  */
0378 static int lapbeth_new_device(struct net_device *dev)
0379 {
0380     struct net_device *ndev;
0381     struct lapbethdev *lapbeth;
0382     int rc = -ENOMEM;
0383 
0384     ASSERT_RTNL();
0385 
0386     ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", NET_NAME_UNKNOWN,
0387                 lapbeth_setup);
0388     if (!ndev)
0389         goto out;
0390 
0391     /* When transmitting data:
0392      * first this driver removes a pseudo header of 1 byte,
0393      * then the lapb module prepends an LAPB header of at most 3 bytes,
0394      * then this driver prepends a length field of 2 bytes,
0395      * then the underlying Ethernet device prepends its own header.
0396      */
0397     ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len
0398                        + dev->needed_headroom;
0399     ndev->needed_tailroom = dev->needed_tailroom;
0400 
0401     lapbeth = netdev_priv(ndev);
0402     lapbeth->axdev = ndev;
0403 
0404     dev_hold(dev);
0405     lapbeth->ethdev = dev;
0406 
0407     lapbeth->up = false;
0408     spin_lock_init(&lapbeth->up_lock);
0409 
0410     skb_queue_head_init(&lapbeth->rx_queue);
0411     netif_napi_add_weight(ndev, &lapbeth->napi, lapbeth_napi_poll, 16);
0412 
0413     rc = -EIO;
0414     if (register_netdevice(ndev))
0415         goto fail;
0416 
0417     list_add_rcu(&lapbeth->node, &lapbeth_devices);
0418     rc = 0;
0419 out:
0420     return rc;
0421 fail:
0422     dev_put(dev);
0423     free_netdev(ndev);
0424     goto out;
0425 }
0426 
0427 /*  Free a lapb network device.
0428  */
0429 static void lapbeth_free_device(struct lapbethdev *lapbeth)
0430 {
0431     dev_put(lapbeth->ethdev);
0432     list_del_rcu(&lapbeth->node);
0433     unregister_netdevice(lapbeth->axdev);
0434 }
0435 
0436 /*  Handle device status changes.
0437  *
0438  * Called from notifier with RTNL held.
0439  */
0440 static int lapbeth_device_event(struct notifier_block *this,
0441                 unsigned long event, void *ptr)
0442 {
0443     struct lapbethdev *lapbeth;
0444     struct net_device *dev = netdev_notifier_info_to_dev(ptr);
0445 
0446     if (dev_net(dev) != &init_net)
0447         return NOTIFY_DONE;
0448 
0449     if (!dev_is_ethdev(dev))
0450         return NOTIFY_DONE;
0451 
0452     switch (event) {
0453     case NETDEV_UP:
0454         /* New ethernet device -> new LAPB interface     */
0455         if (!lapbeth_get_x25_dev(dev))
0456             lapbeth_new_device(dev);
0457         break;
0458     case NETDEV_GOING_DOWN:
0459         /* ethernet device closes -> close LAPB interface */
0460         lapbeth = lapbeth_get_x25_dev(dev);
0461         if (lapbeth)
0462             dev_close(lapbeth->axdev);
0463         break;
0464     case NETDEV_UNREGISTER:
0465         /* ethernet device disappears -> remove LAPB interface */
0466         lapbeth = lapbeth_get_x25_dev(dev);
0467         if (lapbeth)
0468             lapbeth_free_device(lapbeth);
0469         break;
0470     }
0471 
0472     return NOTIFY_DONE;
0473 }
0474 
0475 /* ------------------------------------------------------------------------ */
0476 
0477 static struct packet_type lapbeth_packet_type __read_mostly = {
0478     .type = cpu_to_be16(ETH_P_DEC),
0479     .func = lapbeth_rcv,
0480 };
0481 
0482 static struct notifier_block lapbeth_dev_notifier = {
0483     .notifier_call = lapbeth_device_event,
0484 };
0485 
0486 static const char banner[] __initconst =
0487     KERN_INFO "LAPB Ethernet driver version 0.02\n";
0488 
0489 static int __init lapbeth_init_driver(void)
0490 {
0491     dev_add_pack(&lapbeth_packet_type);
0492 
0493     register_netdevice_notifier(&lapbeth_dev_notifier);
0494 
0495     printk(banner);
0496 
0497     return 0;
0498 }
0499 module_init(lapbeth_init_driver);
0500 
0501 static void __exit lapbeth_cleanup_driver(void)
0502 {
0503     struct lapbethdev *lapbeth;
0504     struct list_head *entry, *tmp;
0505 
0506     dev_remove_pack(&lapbeth_packet_type);
0507     unregister_netdevice_notifier(&lapbeth_dev_notifier);
0508 
0509     rtnl_lock();
0510     list_for_each_safe(entry, tmp, &lapbeth_devices) {
0511         lapbeth = list_entry(entry, struct lapbethdev, node);
0512 
0513         dev_put(lapbeth->ethdev);
0514         unregister_netdevice(lapbeth->axdev);
0515     }
0516     rtnl_unlock();
0517 }
0518 module_exit(lapbeth_cleanup_driver);
0519 
0520 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
0521 MODULE_DESCRIPTION("The unofficial LAPB over Ethernet driver");
0522 MODULE_LICENSE("GPL");