Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Generic HDLC support routines for Linux
0004  * HDLC support
0005  *
0006  * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
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; /* data size wanted */
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");