root/drivers/net/wan/hdlc_raw_eth.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. eth_tx
  2. raw_eth_ioctl
  3. mod_init
  4. mod_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Generic HDLC support routines for Linux
   4  * HDLC Ethernet emulation support
   5  *
   6  * Copyright (C) 2002-2006 Krzysztof Halasa <khc@pm.waw.pl>
   7  */
   8 
   9 #include <linux/errno.h>
  10 #include <linux/etherdevice.h>
  11 #include <linux/gfp.h>
  12 #include <linux/hdlc.h>
  13 #include <linux/if_arp.h>
  14 #include <linux/inetdevice.h>
  15 #include <linux/init.h>
  16 #include <linux/kernel.h>
  17 #include <linux/module.h>
  18 #include <linux/pkt_sched.h>
  19 #include <linux/poll.h>
  20 #include <linux/rtnetlink.h>
  21 #include <linux/skbuff.h>
  22 
  23 static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
  24 
  25 static netdev_tx_t eth_tx(struct sk_buff *skb, struct net_device *dev)
  26 {
  27         int pad = ETH_ZLEN - skb->len;
  28         if (pad > 0) {          /* Pad the frame with zeros */
  29                 int len = skb->len;
  30                 if (skb_tailroom(skb) < pad)
  31                         if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) {
  32                                 dev->stats.tx_dropped++;
  33                                 dev_kfree_skb(skb);
  34                                 return 0;
  35                         }
  36                 skb_put(skb, pad);
  37                 memset(skb->data + len, 0, pad);
  38         }
  39         return dev_to_hdlc(dev)->xmit(skb, dev);
  40 }
  41 
  42 
  43 static struct hdlc_proto proto = {
  44         .type_trans     = eth_type_trans,
  45         .xmit           = eth_tx,
  46         .ioctl          = raw_eth_ioctl,
  47         .module         = THIS_MODULE,
  48 };
  49 
  50 
  51 static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
  52 {
  53         raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
  54         const size_t size = sizeof(raw_hdlc_proto);
  55         raw_hdlc_proto new_settings;
  56         hdlc_device *hdlc = dev_to_hdlc(dev);
  57         unsigned int old_qlen;
  58         int result;
  59 
  60         switch (ifr->ifr_settings.type) {
  61         case IF_GET_PROTO:
  62                 if (dev_to_hdlc(dev)->proto != &proto)
  63                         return -EINVAL;
  64                 ifr->ifr_settings.type = IF_PROTO_HDLC_ETH;
  65                 if (ifr->ifr_settings.size < size) {
  66                         ifr->ifr_settings.size = size; /* data size wanted */
  67                         return -ENOBUFS;
  68                 }
  69                 if (copy_to_user(raw_s, hdlc->state, size))
  70                         return -EFAULT;
  71                 return 0;
  72 
  73         case IF_PROTO_HDLC_ETH:
  74                 if (!capable(CAP_NET_ADMIN))
  75                         return -EPERM;
  76 
  77                 if (dev->flags & IFF_UP)
  78                         return -EBUSY;
  79 
  80                 if (copy_from_user(&new_settings, raw_s, size))
  81                         return -EFAULT;
  82 
  83                 if (new_settings.encoding == ENCODING_DEFAULT)
  84                         new_settings.encoding = ENCODING_NRZ;
  85 
  86                 if (new_settings.parity == PARITY_DEFAULT)
  87                         new_settings.parity = PARITY_CRC16_PR1_CCITT;
  88 
  89                 result = hdlc->attach(dev, new_settings.encoding,
  90                                       new_settings.parity);
  91                 if (result)
  92                         return result;
  93 
  94                 result = attach_hdlc_protocol(dev, &proto,
  95                                               sizeof(raw_hdlc_proto));
  96                 if (result)
  97                         return result;
  98                 memcpy(hdlc->state, &new_settings, size);
  99                 old_qlen = dev->tx_queue_len;
 100                 ether_setup(dev);
 101                 dev->tx_queue_len = old_qlen;
 102                 eth_hw_addr_random(dev);
 103                 call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
 104                 netif_dormant_off(dev);
 105                 return 0;
 106         }
 107 
 108         return -EINVAL;
 109 }
 110 
 111 
 112 static int __init mod_init(void)
 113 {
 114         register_hdlc_protocol(&proto);
 115         return 0;
 116 }
 117 
 118 
 119 
 120 static void __exit mod_exit(void)
 121 {
 122         unregister_hdlc_protocol(&proto);
 123 }
 124 
 125 
 126 module_init(mod_init);
 127 module_exit(mod_exit);
 128 
 129 MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
 130 MODULE_DESCRIPTION("Ethernet encapsulation support for generic HDLC");
 131 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */