This source file includes following definitions.
- x25_connect_disconnect
- x25_connected
- x25_disconnected
- x25_data_indication
- x25_data_transmit
- x25_xmit
- x25_open
- x25_close
- x25_rx
- x25_ioctl
- mod_init
- mod_exit
1
2
3
4
5
6
7
8
9 #include <linux/errno.h>
10 #include <linux/gfp.h>
11 #include <linux/hdlc.h>
12 #include <linux/if_arp.h>
13 #include <linux/inetdevice.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/lapb.h>
17 #include <linux/module.h>
18 #include <linux/pkt_sched.h>
19 #include <linux/poll.h>
20 #include <linux/rtnetlink.h>
21 #include <linux/skbuff.h>
22 #include <net/x25device.h>
23
24 static int x25_ioctl(struct net_device *dev, struct ifreq *ifr);
25
26
27
28 static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
29 {
30 struct sk_buff *skb;
31 unsigned char *ptr;
32
33 if ((skb = dev_alloc_skb(1)) == NULL) {
34 netdev_err(dev, "out of memory\n");
35 return;
36 }
37
38 ptr = skb_put(skb, 1);
39 *ptr = code;
40
41 skb->protocol = x25_type_trans(skb, dev);
42 netif_rx(skb);
43 }
44
45
46
47 static void x25_connected(struct net_device *dev, int reason)
48 {
49 x25_connect_disconnect(dev, reason, X25_IFACE_CONNECT);
50 }
51
52
53
54 static void x25_disconnected(struct net_device *dev, int reason)
55 {
56 x25_connect_disconnect(dev, reason, X25_IFACE_DISCONNECT);
57 }
58
59
60
61 static int x25_data_indication(struct net_device *dev, struct sk_buff *skb)
62 {
63 unsigned char *ptr;
64
65 if (skb_cow(skb, 1))
66 return NET_RX_DROP;
67
68 skb_push(skb, 1);
69 skb_reset_network_header(skb);
70
71 ptr = skb->data;
72 *ptr = X25_IFACE_DATA;
73
74 skb->protocol = x25_type_trans(skb, dev);
75 return netif_rx(skb);
76 }
77
78
79
80 static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb)
81 {
82 hdlc_device *hdlc = dev_to_hdlc(dev);
83
84 skb_reset_network_header(skb);
85 skb->protocol = hdlc_type_trans(skb, dev);
86
87 if (dev_nit_active(dev))
88 dev_queue_xmit_nit(skb, dev);
89
90 hdlc->xmit(skb, dev);
91 }
92
93
94
95 static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
96 {
97 int result;
98
99
100
101 switch (skb->data[0]) {
102 case X25_IFACE_DATA:
103 skb_pull(skb, 1);
104 skb_reset_network_header(skb);
105 if ((result = lapb_data_request(dev, skb)) != LAPB_OK)
106 dev_kfree_skb(skb);
107 return NETDEV_TX_OK;
108
109 case X25_IFACE_CONNECT:
110 if ((result = lapb_connect_request(dev))!= LAPB_OK) {
111 if (result == LAPB_CONNECTED)
112
113 x25_connected(dev, 0);
114 else
115 netdev_err(dev, "LAPB connect request failed, error code = %i\n",
116 result);
117 }
118 break;
119
120 case X25_IFACE_DISCONNECT:
121 if ((result = lapb_disconnect_request(dev)) != LAPB_OK) {
122 if (result == LAPB_NOTCONNECTED)
123
124 x25_disconnected(dev, 0);
125 else
126 netdev_err(dev, "LAPB disconnect request failed, error code = %i\n",
127 result);
128 }
129 break;
130
131 default:
132 break;
133 }
134
135 dev_kfree_skb(skb);
136 return NETDEV_TX_OK;
137 }
138
139
140
141 static int x25_open(struct net_device *dev)
142 {
143 int result;
144 static const struct lapb_register_struct cb = {
145 .connect_confirmation = x25_connected,
146 .connect_indication = x25_connected,
147 .disconnect_confirmation = x25_disconnected,
148 .disconnect_indication = x25_disconnected,
149 .data_indication = x25_data_indication,
150 .data_transmit = x25_data_transmit,
151 };
152
153 result = lapb_register(dev, &cb);
154 if (result != LAPB_OK)
155 return result;
156 return 0;
157 }
158
159
160
161 static void x25_close(struct net_device *dev)
162 {
163 lapb_unregister(dev);
164 }
165
166
167
168 static int x25_rx(struct sk_buff *skb)
169 {
170 struct net_device *dev = skb->dev;
171
172 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
173 dev->stats.rx_dropped++;
174 return NET_RX_DROP;
175 }
176
177 if (lapb_data_received(dev, skb) == LAPB_OK)
178 return NET_RX_SUCCESS;
179
180 dev->stats.rx_errors++;
181 dev_kfree_skb_any(skb);
182 return NET_RX_DROP;
183 }
184
185
186 static struct hdlc_proto proto = {
187 .open = x25_open,
188 .close = x25_close,
189 .ioctl = x25_ioctl,
190 .netif_rx = x25_rx,
191 .xmit = x25_xmit,
192 .module = THIS_MODULE,
193 };
194
195
196 static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
197 {
198 hdlc_device *hdlc = dev_to_hdlc(dev);
199 int result;
200
201 switch (ifr->ifr_settings.type) {
202 case IF_GET_PROTO:
203 if (dev_to_hdlc(dev)->proto != &proto)
204 return -EINVAL;
205 ifr->ifr_settings.type = IF_PROTO_X25;
206 return 0;
207
208 case IF_PROTO_X25:
209 if (!capable(CAP_NET_ADMIN))
210 return -EPERM;
211
212 if (dev->flags & IFF_UP)
213 return -EBUSY;
214
215 result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
216 if (result)
217 return result;
218
219 if ((result = attach_hdlc_protocol(dev, &proto, 0)))
220 return result;
221 dev->type = ARPHRD_X25;
222 call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
223 netif_dormant_off(dev);
224 return 0;
225 }
226
227 return -EINVAL;
228 }
229
230
231 static int __init mod_init(void)
232 {
233 register_hdlc_protocol(&proto);
234 return 0;
235 }
236
237
238
239 static void __exit mod_exit(void)
240 {
241 unregister_hdlc_protocol(&proto);
242 }
243
244
245 module_init(mod_init);
246 module_exit(mod_exit);
247
248 MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
249 MODULE_DESCRIPTION("X.25 protocol support for generic HDLC");
250 MODULE_LICENSE("GPL v2");