diff options
Diffstat (limited to 'drivers/net/wan/hdlc_x25.c')
-rw-r--r-- | drivers/net/wan/hdlc_x25.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index a867fb411f89..e4bb9f8ad433 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Generic HDLC support routines for Linux | 2 | * Generic HDLC support routines for Linux |
3 | * X.25 support | 3 | * X.25 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 |
@@ -25,6 +25,8 @@ | |||
25 | 25 | ||
26 | #include <net/x25device.h> | 26 | #include <net/x25device.h> |
27 | 27 | ||
28 | static int x25_ioctl(struct net_device *dev, struct ifreq *ifr); | ||
29 | |||
28 | /* These functions are callbacks called by LAPB layer */ | 30 | /* These functions are callbacks called by LAPB layer */ |
29 | 31 | ||
30 | static void x25_connect_disconnect(struct net_device *dev, int reason, int code) | 32 | static void x25_connect_disconnect(struct net_device *dev, int reason, int code) |
@@ -162,30 +164,39 @@ static void x25_close(struct net_device *dev) | |||
162 | 164 | ||
163 | static int x25_rx(struct sk_buff *skb) | 165 | static int x25_rx(struct sk_buff *skb) |
164 | { | 166 | { |
165 | hdlc_device *hdlc = dev_to_hdlc(skb->dev); | 167 | struct hdlc_device_desc *desc = dev_to_desc(skb->dev); |
166 | 168 | ||
167 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { | 169 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { |
168 | hdlc->stats.rx_dropped++; | 170 | desc->stats.rx_dropped++; |
169 | return NET_RX_DROP; | 171 | return NET_RX_DROP; |
170 | } | 172 | } |
171 | 173 | ||
172 | if (lapb_data_received(skb->dev, skb) == LAPB_OK) | 174 | if (lapb_data_received(skb->dev, skb) == LAPB_OK) |
173 | return NET_RX_SUCCESS; | 175 | return NET_RX_SUCCESS; |
174 | 176 | ||
175 | hdlc->stats.rx_errors++; | 177 | desc->stats.rx_errors++; |
176 | dev_kfree_skb_any(skb); | 178 | dev_kfree_skb_any(skb); |
177 | return NET_RX_DROP; | 179 | return NET_RX_DROP; |
178 | } | 180 | } |
179 | 181 | ||
180 | 182 | ||
183 | static struct hdlc_proto proto = { | ||
184 | .open = x25_open, | ||
185 | .close = x25_close, | ||
186 | .ioctl = x25_ioctl, | ||
187 | .module = THIS_MODULE, | ||
188 | }; | ||
189 | |||
181 | 190 | ||
182 | int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) | 191 | static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) |
183 | { | 192 | { |
184 | hdlc_device *hdlc = dev_to_hdlc(dev); | 193 | hdlc_device *hdlc = dev_to_hdlc(dev); |
185 | int result; | 194 | int result; |
186 | 195 | ||
187 | switch (ifr->ifr_settings.type) { | 196 | switch (ifr->ifr_settings.type) { |
188 | case IF_GET_PROTO: | 197 | case IF_GET_PROTO: |
198 | if (dev_to_hdlc(dev)->proto != &proto) | ||
199 | return -EINVAL; | ||
189 | ifr->ifr_settings.type = IF_PROTO_X25; | 200 | ifr->ifr_settings.type = IF_PROTO_X25; |
190 | return 0; /* return protocol only, no settable parameters */ | 201 | return 0; /* return protocol only, no settable parameters */ |
191 | 202 | ||
@@ -200,14 +211,9 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
200 | if (result) | 211 | if (result) |
201 | return result; | 212 | return result; |
202 | 213 | ||
203 | hdlc_proto_detach(hdlc); | 214 | if ((result = attach_hdlc_protocol(dev, &proto, |
204 | memset(&hdlc->proto, 0, sizeof(hdlc->proto)); | 215 | x25_rx, 0)) != 0) |
205 | 216 | return result; | |
206 | hdlc->proto.open = x25_open; | ||
207 | hdlc->proto.close = x25_close; | ||
208 | hdlc->proto.netif_rx = x25_rx; | ||
209 | hdlc->proto.type_trans = NULL; | ||
210 | hdlc->proto.id = IF_PROTO_X25; | ||
211 | dev->hard_start_xmit = x25_xmit; | 217 | dev->hard_start_xmit = x25_xmit; |
212 | dev->hard_header = NULL; | 218 | dev->hard_header = NULL; |
213 | dev->type = ARPHRD_X25; | 219 | dev->type = ARPHRD_X25; |
@@ -218,3 +224,25 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
218 | 224 | ||
219 | return -EINVAL; | 225 | return -EINVAL; |
220 | } | 226 | } |
227 | |||
228 | |||
229 | static int __init mod_init(void) | ||
230 | { | ||
231 | register_hdlc_protocol(&proto); | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | |||
236 | |||
237 | static void __exit mod_exit(void) | ||
238 | { | ||
239 | unregister_hdlc_protocol(&proto); | ||
240 | } | ||
241 | |||
242 | |||
243 | module_init(mod_init); | ||
244 | module_exit(mod_exit); | ||
245 | |||
246 | MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); | ||
247 | MODULE_DESCRIPTION("X.25 protocol support for generic HDLC"); | ||
248 | MODULE_LICENSE("GPL v2"); | ||