summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sparc64/kernel/ioctl32.c322
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c74
2 files changed, 384 insertions, 12 deletions
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 93efd4fd02bd..6940790ca34e 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -46,6 +46,7 @@
#include <linux/netdevice.h>
#include <linux/raw.h>
#include <linux/smb_fs.h>
+#include <linux/ncp_fs.h>
#include <linux/blkpg.h>
#include <linux/blk.h>
#include <linux/elevator.h>
@@ -2225,6 +2226,307 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a
return err;
}
+struct ncp_ioctl_request_32 {
+ unsigned int function;
+ unsigned int size;
+ __kernel_caddr_t32 data;
+};
+
+struct ncp_fs_info_v2_32 {
+ int version;
+ unsigned int mounted_uid;
+ unsigned int connection;
+ unsigned int buffer_size;
+
+ unsigned int volume_number;
+ __u32 directory_id;
+
+ __u32 dummy1;
+ __u32 dummy2;
+ __u32 dummy3;
+};
+
+struct ncp_objectname_ioctl_32
+{
+ int auth_type;
+ unsigned int object_name_len;
+ __kernel_caddr_t32 object_name; /* an userspace data, in most cases user name */
+};
+
+struct ncp_privatedata_ioctl_32
+{
+ unsigned int len;
+ __kernel_caddr_t32 data; /* ~1000 for NDS */
+};
+
+#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct ncp_ioctl_request_32)
+
+#define NCP_IOC_GETMOUNTUID2_32 _IOW('n', 2, unsigned int)
+
+#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct ncp_fs_info_v2_32)
+
+#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct ncp_objectname_ioctl_32)
+#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct ncp_objectname_ioctl_32)
+#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct ncp_privatedata_ioctl_32)
+#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct ncp_privatedata_ioctl_32)
+
+static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct ncp_ioctl_request_32 n32;
+ struct ncp_ioctl_request n;
+ mm_segment_t old_fs;
+ int err;
+
+ if (copy_from_user(&n32, (struct ncp_ioctl_request_32*)arg,
+ sizeof(n32)))
+ return -EFAULT;
+
+ n.function = n32.function;
+ n.size = n32.size;
+ if (n.size > 65536)
+ return -EINVAL;
+ n.data = vmalloc(65536); /* 65536 must be same as NCP_PACKET_SIZE_INTERNAL in ncpfs */
+ if (!n.data)
+ return -ENOMEM;
+ err = -EFAULT;
+ if (copy_from_user(n.data, A(n32.data), n.size))
+ goto out;
+
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, NCP_IOC_NCPREQUEST, (unsigned long)&n);
+ set_fs (old_fs);
+ if(err <= 0)
+ goto out;
+ if (err > 65536) {
+ err = -EINVAL;
+ goto out;
+ }
+ if (copy_to_user(A(n32.data), n.data, err)) {
+ err = -EFAULT;
+ goto out;
+ }
+ out:
+ vfree(n.data);
+ return err;
+}
+
+static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ mm_segment_t old_fs = get_fs();
+ __kernel_uid_t kuid;
+ int err;
+
+ cmd = NCP_IOC_GETMOUNTUID2;
+
+ set_fs(KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
+ set_fs(old_fs);
+
+ if (!err)
+ err = put_user(kuid, (unsigned int*)arg);
+
+ return err;
+}
+
+static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ mm_segment_t old_fs = get_fs();
+ struct ncp_fs_info_v2_32 n32;
+ struct ncp_fs_info_v2 n;
+ int err;
+
+ if (copy_from_user(&n32, (struct ncp_fs_info_v2_32*)arg, sizeof(n32)))
+ return -EFAULT;
+ if (n32.version != NCP_GET_FS_INFO_VERSION_V2)
+ return -EINVAL;
+ n.version = NCP_GET_FS_INFO_VERSION_V2;
+
+ set_fs(KERNEL_DS);
+ err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n);
+ set_fs(old_fs);
+
+ if (!err) {
+ n32.version = n.version;
+ n32.mounted_uid = n.mounted_uid;
+ n32.connection = n.connection;
+ n32.buffer_size = n.buffer_size;
+ n32.volume_number = n.volume_number;
+ n32.directory_id = n.directory_id;
+ n32.dummy1 = n.dummy1;
+ n32.dummy2 = n.dummy2;
+ n32.dummy3 = n.dummy3;
+ err = copy_to_user((struct ncp_fs_info_v2_32*)arg, &n32, sizeof(n32)) ? -EFAULT : 0;
+ }
+ return err;
+}
+
+static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct ncp_objectname_ioctl_32 n32;
+ struct ncp_objectname_ioctl n;
+ mm_segment_t old_fs;
+ int err;
+ size_t tl;
+
+ if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg,
+ sizeof(n32)))
+ return -EFAULT;
+
+ n.object_name_len = tl = n32.object_name_len;
+ if (tl) {
+ n.object_name = kmalloc(tl, GFP_KERNEL);
+ if (!n.object_name)
+ return -ENOMEM;
+ } else {
+ n.object_name = NULL;
+ }
+
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, NCP_IOC_GETOBJECTNAME, (unsigned long)&n);
+ set_fs (old_fs);
+ if(err)
+ goto out;
+
+ if (tl > n.object_name_len)
+ tl = n.object_name_len;
+
+ err = -EFAULT;
+ if (tl && copy_to_user(A(n32.object_name), n.object_name, tl))
+ goto out;
+
+ n32.auth_type = n.auth_type;
+ n32.object_name_len = n.object_name_len;
+
+ if (copy_to_user((struct ncp_objectname_ioctl_32*)arg, &n32, sizeof(n32)))
+ goto out;
+
+ err = 0;
+ out:
+ if (n.object_name)
+ kfree(n.object_name);
+
+ return err;
+}
+
+static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct ncp_objectname_ioctl_32 n32;
+ struct ncp_objectname_ioctl n;
+ mm_segment_t old_fs;
+ int err;
+ size_t tl;
+
+ if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg,
+ sizeof(n32)))
+ return -EFAULT;
+
+ n.auth_type = n32.auth_type;
+ n.object_name_len = tl = n32.object_name_len;
+ if (tl) {
+ n.object_name = kmalloc(tl, GFP_KERNEL);
+ if (!n.object_name)
+ return -ENOMEM;
+ err = -EFAULT;
+ if (copy_from_user(n.object_name, A(n32.object_name), tl))
+ goto out;
+ } else {
+ n.object_name = NULL;
+ }
+
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, NCP_IOC_SETOBJECTNAME, (unsigned long)&n);
+ set_fs (old_fs);
+
+ out:
+ if (n.object_name)
+ kfree(n.object_name);
+
+ return err;
+}
+
+static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct ncp_privatedata_ioctl_32 n32;
+ struct ncp_privatedata_ioctl n;
+ mm_segment_t old_fs;
+ int err;
+ size_t tl;
+
+ if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg,
+ sizeof(n32)))
+ return -EFAULT;
+
+ n.len = tl = n32.len;
+ if (tl) {
+ n.data = kmalloc(tl, GFP_KERNEL);
+ if (!n.data)
+ return -ENOMEM;
+ } else {
+ n.data = NULL;
+ }
+
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)&n);
+ set_fs (old_fs);
+ if(err)
+ goto out;
+
+ if (tl > n.len)
+ tl = n.len;
+
+ err = -EFAULT;
+ if (tl && copy_to_user(A(n32.data), n.data, tl))
+ goto out;
+
+ n32.len = n.len;
+
+ if (copy_to_user((struct ncp_privatedata_ioctl_32*)arg, &n32, sizeof(n32)))
+ goto out;
+
+ err = 0;
+ out:
+ if (n.data)
+ kfree(n.data);
+
+ return err;
+}
+
+static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct ncp_privatedata_ioctl_32 n32;
+ struct ncp_privatedata_ioctl n;
+ mm_segment_t old_fs;
+ int err;
+ size_t tl;
+
+ if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg,
+ sizeof(n32)))
+ return -EFAULT;
+
+ n.len = tl = n32.len;
+ if (tl) {
+ n.data = kmalloc(tl, GFP_KERNEL);
+ if (!n.data)
+ return -ENOMEM;
+ err = -EFAULT;
+ if (copy_from_user(n.data, A(n32.data), tl))
+ goto out;
+ } else {
+ n.data = NULL;
+ }
+
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)&n);
+ set_fs (old_fs);
+
+ out:
+ if (n.data)
+ kfree(n.data);
+
+ return err;
+}
+
+
struct atmif_sioc32 {
int number;
int length;
@@ -4508,6 +4810,18 @@ COMPATIBLE_IOCTL(RAW_SETBIND)
COMPATIBLE_IOCTL(RAW_GETBIND)
/* SMB ioctls which do not need any translations */
COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
+/* NCP ioctls which do not need any translations */
+COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN)
+COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT)
+COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED)
+COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED)
+COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK)
+COMPATIBLE_IOCTL(NCP_IOC_GETROOT)
+COMPATIBLE_IOCTL(NCP_IOC_SETROOT)
+COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS)
+COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS)
+COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL)
+COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL)
/* Little a */
COMPATIBLE_IOCTL(ATMSIGD_CTRL)
COMPATIBLE_IOCTL(ATMARPD_CTRL)
@@ -4754,6 +5068,14 @@ HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl)
/* One SMB ioctl needs translations. */
#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, __kernel_uid_t32)
HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
+/* NCPFS */
+HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
+HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2)
+HANDLE_IOCTL(NCP_IOC_GET_FS_INFO_V2_32, do_ncp_getfsinfo2)
+HANDLE_IOCTL(NCP_IOC_GETOBJECTNAME_32, do_ncp_getobjectname)
+HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname)
+HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata)
+HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata)
HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl)
HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl)
HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl)
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 764bdbdd4e32..c893ffb441fe 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1489,7 +1489,7 @@ asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
return sys_sysfs(option, arg1, arg2);
}
-struct ncp_mount_data32 {
+struct ncp_mount_data32_v3 {
int version;
unsigned int ncp_fd;
__kernel_uid_t32 mounted_uid;
@@ -1504,19 +1504,69 @@ struct ncp_mount_data32 {
__kernel_mode_t32 dir_mode;
};
+struct ncp_mount_data32_v4 {
+ int version;
+ /* all members below are "long" in ABI ... i.e. 32bit on sparc32, while 64bits on sparc64 */
+ unsigned int flags;
+ unsigned int mounted_uid;
+ int wdog_pid;
+
+ unsigned int ncp_fd;
+ unsigned int time_out;
+ unsigned int retry_count;
+
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int file_mode;
+ unsigned int dir_mode;
+};
+
static void *do_ncp_super_data_conv(void *raw_data)
{
- struct ncp_mount_data news, *n = &news;
- struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
-
- n->dir_mode = n32->dir_mode;
- n->file_mode = n32->file_mode;
- n->gid = low2highgid(n32->gid);
- n->uid = low2highuid(n32->uid);
- memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
- n->wdog_pid = n32->wdog_pid;
- n->mounted_uid = low2highuid(n32->mounted_uid);
- memcpy(raw_data, n, sizeof(struct ncp_mount_data));
+ switch (*(int*)raw_data) {
+ case NCP_MOUNT_VERSION:
+ {
+ struct ncp_mount_data news, *n = &news;
+ struct ncp_mount_data32_v3 *n32 = (struct ncp_mount_data32_v3 *)raw_data;
+
+ n->version = n32->version;
+ n->ncp_fd = n32->ncp_fd;
+ n->mounted_uid = low2highuid(n32->mounted_uid);
+ n->wdog_pid = n32->wdog_pid;
+ memmove (n->mounted_vol, n32->mounted_vol, sizeof (n32->mounted_vol));
+ n->time_out = n32->time_out;
+ n->retry_count = n32->retry_count;
+ n->flags = n32->flags;
+ n->uid = low2highuid(n32->uid);
+ n->gid = low2highgid(n32->gid);
+ n->file_mode = n32->file_mode;
+ n->dir_mode = n32->dir_mode;
+ memcpy(raw_data, n, sizeof(*n));
+ }
+ break;
+ case NCP_MOUNT_VERSION_V4:
+ {
+ struct ncp_mount_data_v4 news, *n = &news;
+ struct ncp_mount_data32_v4 *n32 = (struct ncp_mount_data32_v4 *)raw_data;
+
+ n->version = n32->version;
+ n->flags = n32->flags;
+ n->mounted_uid = n32->mounted_uid;
+ n->wdog_pid = n32->wdog_pid;
+ n->ncp_fd = n32->ncp_fd;
+ n->time_out = n32->time_out;
+ n->retry_count = n32->retry_count;
+ n->uid = n32->uid;
+ n->gid = n32->gid;
+ n->file_mode = n32->file_mode;
+ n->dir_mode = n32->dir_mode;
+ memcpy(raw_data, n, sizeof(*n));
+ }
+ break;
+ default:
+ /* do not touch unknown structures */
+ break;
+ }
return raw_data;
}