diff options
Diffstat (limited to 'drivers/net/wan/hdlc_raw.c')
-rw-r--r-- | drivers/net/wan/hdlc_raw.c | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index f15aa6ba77f1..fe3cae5c6b9d 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Generic HDLC support routines for Linux | 2 | * Generic HDLC support routines for Linux |
3 | * HDLC support | 3 | * HDLC support |
4 | * | 4 | * |
5 | * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> | 5 | * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of version 2 of the GNU General Public License | 8 | * under the terms of version 2 of the GNU General Public License |
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/hdlc.h> | 24 | #include <linux/hdlc.h> |
25 | 25 | ||
26 | 26 | ||
27 | static int raw_ioctl(struct net_device *dev, struct ifreq *ifr); | ||
28 | |||
27 | static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) | 29 | static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) |
28 | { | 30 | { |
29 | return __constant_htons(ETH_P_IP); | 31 | return __constant_htons(ETH_P_IP); |
@@ -31,7 +33,14 @@ static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
31 | 33 | ||
32 | 34 | ||
33 | 35 | ||
34 | int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) | 36 | static struct hdlc_proto proto = { |
37 | .type_trans = raw_type_trans, | ||
38 | .ioctl = raw_ioctl, | ||
39 | .module = THIS_MODULE, | ||
40 | }; | ||
41 | |||
42 | |||
43 | static int raw_ioctl(struct net_device *dev, struct ifreq *ifr) | ||
35 | { | 44 | { |
36 | raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; | 45 | raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; |
37 | const size_t size = sizeof(raw_hdlc_proto); | 46 | const size_t size = sizeof(raw_hdlc_proto); |
@@ -41,12 +50,14 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
41 | 50 | ||
42 | switch (ifr->ifr_settings.type) { | 51 | switch (ifr->ifr_settings.type) { |
43 | case IF_GET_PROTO: | 52 | case IF_GET_PROTO: |
53 | if (dev_to_hdlc(dev)->proto != &proto) | ||
54 | return -EINVAL; | ||
44 | ifr->ifr_settings.type = IF_PROTO_HDLC; | 55 | ifr->ifr_settings.type = IF_PROTO_HDLC; |
45 | if (ifr->ifr_settings.size < size) { | 56 | if (ifr->ifr_settings.size < size) { |
46 | ifr->ifr_settings.size = size; /* data size wanted */ | 57 | ifr->ifr_settings.size = size; /* data size wanted */ |
47 | return -ENOBUFS; | 58 | return -ENOBUFS; |
48 | } | 59 | } |
49 | if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) | 60 | if (copy_to_user(raw_s, hdlc->state, size)) |
50 | return -EFAULT; | 61 | return -EFAULT; |
51 | return 0; | 62 | return 0; |
52 | 63 | ||
@@ -71,12 +82,11 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
71 | if (result) | 82 | if (result) |
72 | return result; | 83 | return result; |
73 | 84 | ||
74 | hdlc_proto_detach(hdlc); | 85 | result = attach_hdlc_protocol(dev, &proto, NULL, |
75 | memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); | 86 | sizeof(raw_hdlc_proto)); |
76 | memset(&hdlc->proto, 0, sizeof(hdlc->proto)); | 87 | if (result) |
77 | 88 | return result; | |
78 | hdlc->proto.type_trans = raw_type_trans; | 89 | memcpy(hdlc->state, &new_settings, size); |
79 | hdlc->proto.id = IF_PROTO_HDLC; | ||
80 | dev->hard_start_xmit = hdlc->xmit; | 90 | dev->hard_start_xmit = hdlc->xmit; |
81 | dev->hard_header = NULL; | 91 | dev->hard_header = NULL; |
82 | dev->type = ARPHRD_RAWHDLC; | 92 | dev->type = ARPHRD_RAWHDLC; |
@@ -88,3 +98,25 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
88 | 98 | ||
89 | return -EINVAL; | 99 | return -EINVAL; |
90 | } | 100 | } |
101 | |||
102 | |||
103 | static int __init mod_init(void) | ||
104 | { | ||
105 | register_hdlc_protocol(&proto); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | |||
110 | |||
111 | static void __exit mod_exit(void) | ||
112 | { | ||
113 | unregister_hdlc_protocol(&proto); | ||
114 | } | ||
115 | |||
116 | |||
117 | module_init(mod_init); | ||
118 | module_exit(mod_exit); | ||
119 | |||
120 | MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); | ||
121 | MODULE_DESCRIPTION("Raw HDLC protocol support for generic HDLC"); | ||
122 | MODULE_LICENSE("GPL v2"); | ||