0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/errno.h>
0010 #include <linux/hdlc.h>
0011 #include <linux/if_arp.h>
0012 #include <linux/inetdevice.h>
0013 #include <linux/init.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/pkt_sched.h>
0017 #include <linux/poll.h>
0018 #include <linux/rtnetlink.h>
0019 #include <linux/skbuff.h>
0020
0021
0022 static int raw_ioctl(struct net_device *dev, struct if_settings *ifs);
0023
0024 static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev)
0025 {
0026 return cpu_to_be16(ETH_P_IP);
0027 }
0028
0029 static struct hdlc_proto proto = {
0030 .type_trans = raw_type_trans,
0031 .ioctl = raw_ioctl,
0032 .module = THIS_MODULE,
0033 };
0034
0035
0036 static int raw_ioctl(struct net_device *dev, struct if_settings *ifs)
0037 {
0038 raw_hdlc_proto __user *raw_s = ifs->ifs_ifsu.raw_hdlc;
0039 const size_t size = sizeof(raw_hdlc_proto);
0040 raw_hdlc_proto new_settings;
0041 hdlc_device *hdlc = dev_to_hdlc(dev);
0042 int result;
0043
0044 switch (ifs->type) {
0045 case IF_GET_PROTO:
0046 if (dev_to_hdlc(dev)->proto != &proto)
0047 return -EINVAL;
0048 ifs->type = IF_PROTO_HDLC;
0049 if (ifs->size < size) {
0050 ifs->size = size;
0051 return -ENOBUFS;
0052 }
0053 if (copy_to_user(raw_s, hdlc->state, size))
0054 return -EFAULT;
0055 return 0;
0056
0057 case IF_PROTO_HDLC:
0058 if (!capable(CAP_NET_ADMIN))
0059 return -EPERM;
0060
0061 if (dev->flags & IFF_UP)
0062 return -EBUSY;
0063
0064 if (copy_from_user(&new_settings, raw_s, size))
0065 return -EFAULT;
0066
0067 if (new_settings.encoding == ENCODING_DEFAULT)
0068 new_settings.encoding = ENCODING_NRZ;
0069
0070 if (new_settings.parity == PARITY_DEFAULT)
0071 new_settings.parity = PARITY_CRC16_PR1_CCITT;
0072
0073 result = hdlc->attach(dev, new_settings.encoding,
0074 new_settings.parity);
0075 if (result)
0076 return result;
0077
0078 result = attach_hdlc_protocol(dev, &proto,
0079 sizeof(raw_hdlc_proto));
0080 if (result)
0081 return result;
0082 memcpy(hdlc->state, &new_settings, size);
0083 dev->type = ARPHRD_RAWHDLC;
0084 call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
0085 netif_dormant_off(dev);
0086 return 0;
0087 }
0088
0089 return -EINVAL;
0090 }
0091
0092
0093 static int __init hdlc_raw_init(void)
0094 {
0095 register_hdlc_protocol(&proto);
0096 return 0;
0097 }
0098
0099
0100
0101 static void __exit hdlc_raw_exit(void)
0102 {
0103 unregister_hdlc_protocol(&proto);
0104 }
0105
0106
0107 module_init(hdlc_raw_init);
0108 module_exit(hdlc_raw_exit);
0109
0110 MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
0111 MODULE_DESCRIPTION("Raw HDLC protocol support for generic HDLC");
0112 MODULE_LICENSE("GPL v2");