diff options
Diffstat (limited to 'drivers/net/wan/hdlc_raw_eth.c')
-rw-r--r-- | drivers/net/wan/hdlc_raw_eth.c | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c index d1884987f94e..1a69a9aaa9b9 100644 --- a/drivers/net/wan/hdlc_raw_eth.c +++ b/drivers/net/wan/hdlc_raw_eth.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Generic HDLC support routines for Linux | 2 | * Generic HDLC support routines for Linux |
3 | * HDLC Ethernet emulation support | 3 | * HDLC Ethernet emulation support |
4 | * | 4 | * |
5 | * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl> | 5 | * Copyright (C) 2002-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 |
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <linux/hdlc.h> | 26 | #include <linux/hdlc.h> |
27 | 27 | ||
28 | static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr); | ||
28 | 29 | ||
29 | static int eth_tx(struct sk_buff *skb, struct net_device *dev) | 30 | static int eth_tx(struct sk_buff *skb, struct net_device *dev) |
30 | { | 31 | { |
@@ -44,7 +45,14 @@ static int eth_tx(struct sk_buff *skb, struct net_device *dev) | |||
44 | } | 45 | } |
45 | 46 | ||
46 | 47 | ||
47 | int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | 48 | static struct hdlc_proto proto = { |
49 | .type_trans = eth_type_trans, | ||
50 | .ioctl = raw_eth_ioctl, | ||
51 | .module = THIS_MODULE, | ||
52 | }; | ||
53 | |||
54 | |||
55 | static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | ||
48 | { | 56 | { |
49 | raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; | 57 | raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; |
50 | const size_t size = sizeof(raw_hdlc_proto); | 58 | const size_t size = sizeof(raw_hdlc_proto); |
@@ -56,12 +64,14 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
56 | 64 | ||
57 | switch (ifr->ifr_settings.type) { | 65 | switch (ifr->ifr_settings.type) { |
58 | case IF_GET_PROTO: | 66 | case IF_GET_PROTO: |
67 | if (dev_to_hdlc(dev)->proto != &proto) | ||
68 | return -EINVAL; | ||
59 | ifr->ifr_settings.type = IF_PROTO_HDLC_ETH; | 69 | ifr->ifr_settings.type = IF_PROTO_HDLC_ETH; |
60 | if (ifr->ifr_settings.size < size) { | 70 | if (ifr->ifr_settings.size < size) { |
61 | ifr->ifr_settings.size = size; /* data size wanted */ | 71 | ifr->ifr_settings.size = size; /* data size wanted */ |
62 | return -ENOBUFS; | 72 | return -ENOBUFS; |
63 | } | 73 | } |
64 | if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) | 74 | if (copy_to_user(raw_s, hdlc->state, size)) |
65 | return -EFAULT; | 75 | return -EFAULT; |
66 | return 0; | 76 | return 0; |
67 | 77 | ||
@@ -86,12 +96,11 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
86 | if (result) | 96 | if (result) |
87 | return result; | 97 | return result; |
88 | 98 | ||
89 | hdlc_proto_detach(hdlc); | 99 | result = attach_hdlc_protocol(dev, &proto, NULL, |
90 | memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); | 100 | sizeof(raw_hdlc_proto)); |
91 | memset(&hdlc->proto, 0, sizeof(hdlc->proto)); | 101 | if (result) |
92 | 102 | return result; | |
93 | hdlc->proto.type_trans = eth_type_trans; | 103 | memcpy(hdlc->state, &new_settings, size); |
94 | hdlc->proto.id = IF_PROTO_HDLC_ETH; | ||
95 | dev->hard_start_xmit = eth_tx; | 104 | dev->hard_start_xmit = eth_tx; |
96 | old_ch_mtu = dev->change_mtu; | 105 | old_ch_mtu = dev->change_mtu; |
97 | old_qlen = dev->tx_queue_len; | 106 | old_qlen = dev->tx_queue_len; |
@@ -106,3 +115,25 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
106 | 115 | ||
107 | return -EINVAL; | 116 | return -EINVAL; |
108 | } | 117 | } |
118 | |||
119 | |||
120 | static int __init mod_init(void) | ||
121 | { | ||
122 | register_hdlc_protocol(&proto); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | |||
127 | |||
128 | static void __exit mod_exit(void) | ||
129 | { | ||
130 | unregister_hdlc_protocol(&proto); | ||
131 | } | ||
132 | |||
133 | |||
134 | module_init(mod_init); | ||
135 | module_exit(mod_exit); | ||
136 | |||
137 | MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); | ||
138 | MODULE_DESCRIPTION("Ethernet encapsulation support for generic HDLC"); | ||
139 | MODULE_LICENSE("GPL v2"); | ||