0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/errno.h>
0010 #include <linux/etherdevice.h>
0011 #include <linux/gfp.h>
0012 #include <linux/hdlc.h>
0013 #include <linux/if_arp.h>
0014 #include <linux/inetdevice.h>
0015 #include <linux/init.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/pkt_sched.h>
0019 #include <linux/poll.h>
0020 #include <linux/rtnetlink.h>
0021 #include <linux/skbuff.h>
0022
0023 static int raw_eth_ioctl(struct net_device *dev, struct if_settings *ifs);
0024
0025 static netdev_tx_t eth_tx(struct sk_buff *skb, struct net_device *dev)
0026 {
0027 int pad = ETH_ZLEN - skb->len;
0028 if (pad > 0) {
0029 int len = skb->len;
0030 if (skb_tailroom(skb) < pad)
0031 if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) {
0032 dev->stats.tx_dropped++;
0033 dev_kfree_skb(skb);
0034 return 0;
0035 }
0036 skb_put(skb, pad);
0037 memset(skb->data + len, 0, pad);
0038 }
0039 return dev_to_hdlc(dev)->xmit(skb, dev);
0040 }
0041
0042
0043 static struct hdlc_proto proto = {
0044 .type_trans = eth_type_trans,
0045 .xmit = eth_tx,
0046 .ioctl = raw_eth_ioctl,
0047 .module = THIS_MODULE,
0048 };
0049
0050
0051 static int raw_eth_ioctl(struct net_device *dev, struct if_settings *ifs)
0052 {
0053 raw_hdlc_proto __user *raw_s = ifs->ifs_ifsu.raw_hdlc;
0054 const size_t size = sizeof(raw_hdlc_proto);
0055 raw_hdlc_proto new_settings;
0056 hdlc_device *hdlc = dev_to_hdlc(dev);
0057 unsigned int old_qlen;
0058 int result;
0059
0060 switch (ifs->type) {
0061 case IF_GET_PROTO:
0062 if (dev_to_hdlc(dev)->proto != &proto)
0063 return -EINVAL;
0064 ifs->type = IF_PROTO_HDLC_ETH;
0065 if (ifs->size < size) {
0066 ifs->size = size;
0067 return -ENOBUFS;
0068 }
0069 if (copy_to_user(raw_s, hdlc->state, size))
0070 return -EFAULT;
0071 return 0;
0072
0073 case IF_PROTO_HDLC_ETH:
0074 if (!capable(CAP_NET_ADMIN))
0075 return -EPERM;
0076
0077 if (dev->flags & IFF_UP)
0078 return -EBUSY;
0079
0080 if (copy_from_user(&new_settings, raw_s, size))
0081 return -EFAULT;
0082
0083 if (new_settings.encoding == ENCODING_DEFAULT)
0084 new_settings.encoding = ENCODING_NRZ;
0085
0086 if (new_settings.parity == PARITY_DEFAULT)
0087 new_settings.parity = PARITY_CRC16_PR1_CCITT;
0088
0089 result = hdlc->attach(dev, new_settings.encoding,
0090 new_settings.parity);
0091 if (result)
0092 return result;
0093
0094 result = attach_hdlc_protocol(dev, &proto,
0095 sizeof(raw_hdlc_proto));
0096 if (result)
0097 return result;
0098 memcpy(hdlc->state, &new_settings, size);
0099 old_qlen = dev->tx_queue_len;
0100 ether_setup(dev);
0101 dev->tx_queue_len = old_qlen;
0102 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
0103 eth_hw_addr_random(dev);
0104 call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
0105 netif_dormant_off(dev);
0106 return 0;
0107 }
0108
0109 return -EINVAL;
0110 }
0111
0112
0113 static int __init hdlc_eth_init(void)
0114 {
0115 register_hdlc_protocol(&proto);
0116 return 0;
0117 }
0118
0119
0120
0121 static void __exit hdlc_eth_exit(void)
0122 {
0123 unregister_hdlc_protocol(&proto);
0124 }
0125
0126
0127 module_init(hdlc_eth_init);
0128 module_exit(hdlc_eth_exit);
0129
0130 MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
0131 MODULE_DESCRIPTION("Ethernet encapsulation support for generic HDLC");
0132 MODULE_LICENSE("GPL v2");