diff options
author | John W. Linville <linville@tuxdriver.com> | 2006-10-17 10:54:36 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-10-19 17:08:19 -0400 |
commit | 98978edb6278f0fb30c8d636c6a79a28f9164cb9 (patch) | |
tree | 60cf0da6277e7deccd2a00591361e56dde75e88e /net/core | |
parent | 51018b0a3160d253283173c2f54f16746cee5852 (diff) |
[PATCH] wireless: WE-20 compatibility for ESSID and NICKN ioctls
WE-21 changed the ABI for the SIOC[SG]IW{ESSID,NICKN} ioctls by dropping
NULL termination. This patch adds compatibility code so that WE-21 can
work properly with WE-20 (and older) tools.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/wireless.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/net/core/wireless.c b/net/core/wireless.c index ffff0da46c6..cb1b8728d7e 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -748,11 +748,39 @@ static int ioctl_standard_call(struct net_device * dev, int extra_size; int user_length = 0; int err; + int essid_compat = 0; /* Calculate space needed by arguments. Always allocate * for max space. Easier, and won't last long... */ extra_size = descr->max_tokens * descr->token_size; + /* Check need for ESSID compatibility for WE < 21 */ + switch (cmd) { + case SIOCSIWESSID: + case SIOCGIWESSID: + case SIOCSIWNICKN: + case SIOCGIWNICKN: + if (iwr->u.data.length == descr->max_tokens + 1) + essid_compat = 1; + else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { + char essid[IW_ESSID_MAX_SIZE + 1]; + + err = copy_from_user(essid, iwr->u.data.pointer, + iwr->u.data.length * + descr->token_size); + if (err) + return -EFAULT; + + if (essid[iwr->u.data.length - 1] == '\0') + essid_compat = 1; + } + break; + default: + break; + } + + iwr->u.data.length -= essid_compat; + /* Check what user space is giving us */ if(IW_IS_SET(cmd)) { /* Check NULL pointer */ @@ -795,7 +823,8 @@ static int ioctl_standard_call(struct net_device * dev, #endif /* WE_IOCTL_DEBUG */ /* Create the kernel buffer */ - extra = kmalloc(extra_size, GFP_KERNEL); + /* kzalloc ensures NULL-termination for essid_compat */ + extra = kzalloc(extra_size, GFP_KERNEL); if (extra == NULL) { return -ENOMEM; } @@ -819,6 +848,8 @@ static int ioctl_standard_call(struct net_device * dev, /* Call the handler */ ret = handler(dev, &info, &(iwr->u), extra); + iwr->u.data.length += essid_compat; + /* If we have something to return to the user */ if (!ret && IW_IS_GET(cmd)) { /* Check if there is enough buffer up there */ |