Skip to content

Commit f362e5f

Browse files
sch-mdavem330
authored andcommitted
wan/hdlc_x25: make lapb params configurable
This enables you to configure mode (DTE/DCE), Modulo, Window, T1, T2, N2 via sethdlc (which needs to be patched as well). Signed-off-by: Martin Schiller <ms@dev.tdt.de> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 29237d2 commit f362e5f

File tree

3 files changed

+87
-3
lines changed

3 files changed

+87
-3
lines changed

drivers/net/wan/hdlc_x25.c

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,17 @@
2121
#include <linux/skbuff.h>
2222
#include <net/x25device.h>
2323

24+
struct x25_state {
25+
x25_hdlc_proto settings;
26+
};
27+
2428
static int x25_ioctl(struct net_device *dev, struct ifreq *ifr);
2529

30+
static struct x25_state *state(hdlc_device *hdlc)
31+
{
32+
return hdlc->state;
33+
}
34+
2635
/* These functions are callbacks called by LAPB layer */
2736

2837
static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
@@ -131,7 +140,6 @@ static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
131140

132141
static int x25_open(struct net_device *dev)
133142
{
134-
int result;
135143
static const struct lapb_register_struct cb = {
136144
.connect_confirmation = x25_connected,
137145
.connect_indication = x25_connected,
@@ -140,10 +148,33 @@ static int x25_open(struct net_device *dev)
140148
.data_indication = x25_data_indication,
141149
.data_transmit = x25_data_transmit,
142150
};
151+
hdlc_device *hdlc = dev_to_hdlc(dev);
152+
struct lapb_parms_struct params;
153+
int result;
143154

144155
result = lapb_register(dev, &cb);
145156
if (result != LAPB_OK)
146157
return result;
158+
159+
result = lapb_getparms(dev, &params);
160+
if (result != LAPB_OK)
161+
return result;
162+
163+
if (state(hdlc)->settings.dce)
164+
params.mode = params.mode | LAPB_DCE;
165+
166+
if (state(hdlc)->settings.modulo == 128)
167+
params.mode = params.mode | LAPB_EXTENDED;
168+
169+
params.window = state(hdlc)->settings.window;
170+
params.t1 = state(hdlc)->settings.t1;
171+
params.t2 = state(hdlc)->settings.t2;
172+
params.n2 = state(hdlc)->settings.n2;
173+
174+
result = lapb_setparms(dev, &params);
175+
if (result != LAPB_OK)
176+
return result;
177+
147178
return 0;
148179
}
149180

@@ -186,15 +217,24 @@ static struct hdlc_proto proto = {
186217

187218
static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
188219
{
220+
x25_hdlc_proto __user *x25_s = ifr->ifr_settings.ifs_ifsu.x25;
221+
const size_t size = sizeof(x25_hdlc_proto);
189222
hdlc_device *hdlc = dev_to_hdlc(dev);
223+
x25_hdlc_proto new_settings;
190224
int result;
191225

192226
switch (ifr->ifr_settings.type) {
193227
case IF_GET_PROTO:
194228
if (dev_to_hdlc(dev)->proto != &proto)
195229
return -EINVAL;
196230
ifr->ifr_settings.type = IF_PROTO_X25;
197-
return 0; /* return protocol only, no settable parameters */
231+
if (ifr->ifr_settings.size < size) {
232+
ifr->ifr_settings.size = size; /* data size wanted */
233+
return -ENOBUFS;
234+
}
235+
if (copy_to_user(x25_s, &state(hdlc)->settings, size))
236+
return -EFAULT;
237+
return 0;
198238

199239
case IF_PROTO_X25:
200240
if (!capable(CAP_NET_ADMIN))
@@ -203,12 +243,46 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
203243
if (dev->flags & IFF_UP)
204244
return -EBUSY;
205245

246+
/* backward compatibility */
247+
if (ifr->ifr_settings.size = 0) {
248+
new_settings.dce = 0;
249+
new_settings.modulo = 8;
250+
new_settings.window = 7;
251+
new_settings.t1 = 3;
252+
new_settings.t2 = 1;
253+
new_settings.n2 = 10;
254+
}
255+
else {
256+
if (copy_from_user(&new_settings, x25_s, size))
257+
return -EFAULT;
258+
259+
if ((new_settings.dce != 0 &&
260+
new_settings.dce != 1) ||
261+
(new_settings.modulo != 8 &&
262+
new_settings.modulo != 128) ||
263+
new_settings.window < 1 ||
264+
(new_settings.modulo == 8 &&
265+
new_settings.window > 7) ||
266+
(new_settings.modulo == 128 &&
267+
new_settings.window > 127) ||
268+
new_settings.t1 < 1 ||
269+
new_settings.t1 > 255 ||
270+
new_settings.t2 < 1 ||
271+
new_settings.t2 > 255 ||
272+
new_settings.n2 < 1 ||
273+
new_settings.n2 > 255)
274+
return -EINVAL;
275+
}
276+
206277
result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
207278
if (result)
208279
return result;
209280

210-
if ((result = attach_hdlc_protocol(dev, &proto, 0)))
281+
if ((result = attach_hdlc_protocol(dev, &proto,
282+
sizeof(struct x25_state))))
211283
return result;
284+
285+
memcpy(&state(hdlc)->settings, &new_settings, size);
212286
dev->type = ARPHRD_X25;
213287
call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
214288
netif_dormant_off(dev);

include/uapi/linux/hdlc/ioctl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ typedef struct {
7979
unsigned int timeout;
8080
} cisco_proto;
8181

82+
typedef struct {
83+
unsigned short dce; /* 1 for DCE (network side) operation */
84+
unsigned int modulo; /* modulo (8 = basic / 128 = extended) */
85+
unsigned int window; /* frame window size */
86+
unsigned int t1; /* timeout t1 */
87+
unsigned int t2; /* timeout t2 */
88+
unsigned int n2; /* frame retry counter */
89+
} x25_hdlc_proto;
90+
8291
/* PPP doesn't need any info now - supply length = 0 to ioctl */
8392

8493
#endif /* __ASSEMBLY__ */

include/uapi/linux/if.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ struct if_settings {
213213
fr_proto __user *fr;
214214
fr_proto_pvc __user *fr_pvc;
215215
fr_proto_pvc_info __user *fr_pvc_info;
216+
x25_hdlc_proto __user *x25;
216217

217218
/* interface settings */
218219
sync_serial_settings __user *sync;

0 commit comments

Comments
 (0)