blob: 12550c2320ccbb79f69868a2eeafa67fdfaa82ee [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ioctl.c
3 *
4 * Copyright (C) 1995, 1996 by Volker Lendecke
5 * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
6 * Modified 1998, 1999 Wolfram Pienkoss for NLS
7 *
8 */
9
Randy Dunlap16f7e0f2006-01-11 12:17:46 -080010#include <linux/capability.h>
Petr Vandrovec54f67f62006-09-30 23:27:55 -070011#include <linux/compat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/errno.h>
13#include <linux/fs.h>
14#include <linux/ioctl.h>
15#include <linux/time.h>
16#include <linux/mm.h>
Dave Hansena761a1c2008-02-15 14:37:39 -080017#include <linux/mount.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/highuid.h>
20#include <linux/vmalloc.h>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +040021#include <linux/sched.h>
Ingo Molnar5b825c32017-02-02 17:54:15 +010022#include <linux/cred.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080024#include <linux/uaccess.h>
Petr Vandrovec54f67f62006-09-30 23:27:55 -070025
Al Viro32c419d2011-01-12 17:37:47 -050026#include "ncp_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
28/* maximum limit for ncp_objectname_ioctl */
29#define NCP_OBJECT_NAME_MAX_LEN 4096
30/* maximum limit for ncp_privatedata_ioctl */
31#define NCP_PRIVATE_DATA_MAX_LEN 8192
32/* maximum negotiable packet size */
33#define NCP_PACKET_SIZE_INTERNAL 65536
34
35static int
Petr Vandrovec2e54eb92010-09-27 01:47:33 +020036ncp_get_fs_info(struct ncp_server * server, struct inode *inode,
Christoph Hellwig8c744fb2005-11-08 21:35:04 -080037 struct ncp_fs_info __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038{
39 struct ncp_fs_info info;
40
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 if (copy_from_user(&info, arg, sizeof(info)))
42 return -EFAULT;
43
44 if (info.version != NCP_GET_FS_INFO_VERSION) {
Joe Perchesd3b73ca2014-04-08 16:04:15 -070045 ncp_dbg(1, "info.version invalid: %d\n", info.version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 return -EINVAL;
47 }
48 /* TODO: info.addr = server->m.serv_addr; */
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -080049 SET_UID(info.mounted_uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid));
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 info.connection = server->connection;
51 info.buffer_size = server->buffer_size;
52 info.volume_number = NCP_FINFO(inode)->volNumber;
53 info.directory_id = NCP_FINFO(inode)->DosDirNum;
54
55 if (copy_to_user(arg, &info, sizeof(info)))
56 return -EFAULT;
57 return 0;
58}
59
60static int
Petr Vandrovec2e54eb92010-09-27 01:47:33 +020061ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,
Christoph Hellwig8c744fb2005-11-08 21:35:04 -080062 struct ncp_fs_info_v2 __user * arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -070063{
64 struct ncp_fs_info_v2 info2;
65
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 if (copy_from_user(&info2, arg, sizeof(info2)))
67 return -EFAULT;
68
69 if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
Joe Perchesd3b73ca2014-04-08 16:04:15 -070070 ncp_dbg(1, "info.version invalid: %d\n", info2.version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 return -EINVAL;
72 }
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -080073 info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 info2.connection = server->connection;
75 info2.buffer_size = server->buffer_size;
76 info2.volume_number = NCP_FINFO(inode)->volNumber;
77 info2.directory_id = NCP_FINFO(inode)->DosDirNum;
78 info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
79
80 if (copy_to_user(arg, &info2, sizeof(info2)))
81 return -EFAULT;
82 return 0;
83}
84
Petr Vandrovec54f67f62006-09-30 23:27:55 -070085#ifdef CONFIG_COMPAT
86struct compat_ncp_objectname_ioctl
87{
88 s32 auth_type;
89 u32 object_name_len;
Frederik Schwarzer0211a9c2008-12-29 22:14:56 +010090 compat_caddr_t object_name; /* a userspace data, in most cases user name */
Petr Vandrovec54f67f62006-09-30 23:27:55 -070091};
92
93struct compat_ncp_fs_info_v2 {
94 s32 version;
95 u32 mounted_uid;
96 u32 connection;
97 u32 buffer_size;
98
99 u32 volume_number;
100 u32 directory_id;
101
102 u32 dummy1;
103 u32 dummy2;
104 u32 dummy3;
105};
106
107struct compat_ncp_ioctl_request {
108 u32 function;
109 u32 size;
110 compat_caddr_t data;
111};
112
113struct compat_ncp_privatedata_ioctl
114{
115 u32 len;
116 compat_caddr_t data; /* ~1000 for NDS */
117};
118
119#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct compat_ncp_fs_info_v2)
120#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct compat_ncp_ioctl_request)
121#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct compat_ncp_objectname_ioctl)
122#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct compat_ncp_objectname_ioctl)
123#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct compat_ncp_privatedata_ioctl)
124#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
125
126static int
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200127ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700128 struct compat_ncp_fs_info_v2 __user * arg)
129{
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700130 struct compat_ncp_fs_info_v2 info2;
131
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700132 if (copy_from_user(&info2, arg, sizeof(info2)))
133 return -EFAULT;
134
135 if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
Joe Perchesd3b73ca2014-04-08 16:04:15 -0700136 ncp_dbg(1, "info.version invalid: %d\n", info2.version);
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700137 return -EINVAL;
138 }
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -0800139 info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700140 info2.connection = server->connection;
141 info2.buffer_size = server->buffer_size;
142 info2.volume_number = NCP_FINFO(inode)->volNumber;
143 info2.directory_id = NCP_FINFO(inode)->DosDirNum;
144 info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
145
146 if (copy_to_user(arg, &info2, sizeof(info2)))
147 return -EFAULT;
148 return 0;
149}
150#endif
151
152#define NCP_IOC_GETMOUNTUID16 _IOW('n', 2, u16)
153#define NCP_IOC_GETMOUNTUID32 _IOW('n', 2, u32)
154#define NCP_IOC_GETMOUNTUID64 _IOW('n', 2, u64)
155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156#ifdef CONFIG_NCPFS_NLS
157/* Here we are select the iocharset and the codepage for NLS.
158 * Thanks Petr Vandrovec for idea and many hints.
159 */
160static int
161ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
162{
163 struct ncp_nls_ioctl user;
164 struct nls_table *codepage;
165 struct nls_table *iocharset;
166 struct nls_table *oldset_io;
167 struct nls_table *oldset_cp;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200168 int utf8;
169 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
171 if (copy_from_user(&user, arg, sizeof(user)))
172 return -EFAULT;
173
174 codepage = NULL;
175 user.codepage[NCP_IOCSNAME_LEN] = 0;
176 if (!user.codepage[0] || !strcmp(user.codepage, "default"))
177 codepage = load_nls_default();
178 else {
179 codepage = load_nls(user.codepage);
180 if (!codepage) {
181 return -EBADRQC;
182 }
183 }
184
185 iocharset = NULL;
186 user.iocharset[NCP_IOCSNAME_LEN] = 0;
187 if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
188 iocharset = load_nls_default();
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200189 utf8 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 } else if (!strcmp(user.iocharset, "utf8")) {
191 iocharset = load_nls_default();
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200192 utf8 = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 } else {
194 iocharset = load_nls(user.iocharset);
195 if (!iocharset) {
196 unload_nls(codepage);
197 return -EBADRQC;
198 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200199 utf8 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 }
201
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200202 mutex_lock(&server->root_setup_lock);
203 if (server->root_setuped) {
204 oldset_cp = codepage;
205 oldset_io = iocharset;
206 err = -EBUSY;
207 } else {
208 if (utf8)
209 NCP_SET_FLAG(server, NCP_FLAG_UTF8);
210 else
211 NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
212 oldset_cp = server->nls_vol;
213 server->nls_vol = codepage;
214 oldset_io = server->nls_io;
215 server->nls_io = iocharset;
216 err = 0;
217 }
218 mutex_unlock(&server->root_setup_lock);
Thomas Gleixner6d729e42009-08-16 21:05:08 +0000219 unload_nls(oldset_cp);
220 unload_nls(oldset_io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200222 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223}
224
225static int
226ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
227{
228 struct ncp_nls_ioctl user;
229 int len;
230
231 memset(&user, 0, sizeof(user));
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200232 mutex_lock(&server->root_setup_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 if (server->nls_vol && server->nls_vol->charset) {
234 len = strlen(server->nls_vol->charset);
235 if (len > NCP_IOCSNAME_LEN)
236 len = NCP_IOCSNAME_LEN;
237 strncpy(user.codepage, server->nls_vol->charset, len);
238 user.codepage[len] = 0;
239 }
240
241 if (NCP_IS_FLAG(server, NCP_FLAG_UTF8))
242 strcpy(user.iocharset, "utf8");
243 else if (server->nls_io && server->nls_io->charset) {
244 len = strlen(server->nls_io->charset);
245 if (len > NCP_IOCSNAME_LEN)
246 len = NCP_IOCSNAME_LEN;
247 strncpy(user.iocharset, server->nls_io->charset, len);
248 user.iocharset[len] = 0;
249 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200250 mutex_unlock(&server->root_setup_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
252 if (copy_to_user(arg, &user, sizeof(user)))
253 return -EFAULT;
254 return 0;
255}
256#endif /* CONFIG_NCPFS_NLS */
257
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200258static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259{
260 struct ncp_server *server = NCP_SERVER(inode);
261 int result;
262 struct ncp_ioctl_request request;
263 char* bouncebuffer;
264 void __user *argp = (void __user *)arg;
265
266 switch (cmd) {
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700267#ifdef CONFIG_COMPAT
268 case NCP_IOC_NCPREQUEST_32:
269#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 case NCP_IOC_NCPREQUEST:
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700271#ifdef CONFIG_COMPAT
272 if (cmd == NCP_IOC_NCPREQUEST_32) {
273 struct compat_ncp_ioctl_request request32;
274 if (copy_from_user(&request32, argp, sizeof(request32)))
275 return -EFAULT;
276 request.function = request32.function;
277 request.size = request32.size;
278 request.data = compat_ptr(request32.data);
279 } else
280#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 if (copy_from_user(&request, argp, sizeof(request)))
282 return -EFAULT;
283
284 if ((request.function > 255)
285 || (request.size >
286 NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
287 return -EINVAL;
288 }
289 bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL);
290 if (!bouncebuffer)
291 return -ENOMEM;
292 if (copy_from_user(bouncebuffer, request.data, request.size)) {
293 vfree(bouncebuffer);
294 return -EFAULT;
295 }
296 ncp_lock_server(server);
297
298 /* FIXME: We hack around in the server's structures
299 here to be able to use ncp_request */
300
301 server->has_subfunction = 0;
302 server->current_size = request.size;
303 memcpy(server->packet, bouncebuffer, request.size);
304
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200305 result = ncp_request2(server, request.function,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
307 if (result < 0)
308 result = -EIO;
309 else
310 result = server->reply_size;
311 ncp_unlock_server(server);
Joe Perchesd3b73ca2014-04-08 16:04:15 -0700312 ncp_dbg(1, "copy %d bytes\n", result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 if (result >= 0)
314 if (copy_to_user(request.data, bouncebuffer, result))
315 result = -EFAULT;
316 vfree(bouncebuffer);
317 return result;
318
319 case NCP_IOC_CONN_LOGGED_IN:
320
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
322 return -EINVAL;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200323 mutex_lock(&server->root_setup_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 if (server->root_setuped)
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200325 result = -EBUSY;
326 else {
327 result = ncp_conn_logged_in(inode->i_sb);
328 if (result == 0)
329 server->root_setuped = 1;
330 }
331 mutex_unlock(&server->root_setup_lock);
332 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334 case NCP_IOC_GET_FS_INFO:
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200335 return ncp_get_fs_info(server, inode, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337 case NCP_IOC_GET_FS_INFO_V2:
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200338 return ncp_get_fs_info_v2(server, inode, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700340#ifdef CONFIG_COMPAT
341 case NCP_IOC_GET_FS_INFO_V2_32:
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200342 return ncp_get_compat_fs_info_v2(server, inode, argp);
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700343#endif
344 /* we have too many combinations of CONFIG_COMPAT,
345 * CONFIG_64BIT and CONFIG_UID16, so just handle
346 * any of the possible ioctls */
347 case NCP_IOC_GETMOUNTUID16:
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200348 {
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700349 u16 uid;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200350
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -0800351 SET_UID(uid, from_kuid_munged(current_user_ns(), server->m.mounted_uid));
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700352 if (put_user(uid, (u16 __user *)argp))
353 return -EFAULT;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200354 return 0;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700355 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200356 case NCP_IOC_GETMOUNTUID32:
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -0800357 {
358 uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
359 if (put_user(uid, (u32 __user *)argp))
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200360 return -EFAULT;
361 return 0;
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -0800362 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200363 case NCP_IOC_GETMOUNTUID64:
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -0800364 {
365 uid_t uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid);
366 if (put_user(uid, (u64 __user *)argp))
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200367 return -EFAULT;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700368 return 0;
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -0800369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 case NCP_IOC_GETROOT:
371 {
372 struct ncp_setroot_ioctl sr;
373
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200374 result = -EACCES;
375 mutex_lock(&server->root_setup_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 if (server->m.mounted_vol[0]) {
377 struct dentry* dentry = inode->i_sb->s_root;
378
379 if (dentry) {
David Howells2b0143b2015-03-17 22:25:59 +0000380 struct inode* s_inode = d_inode(dentry);
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200381
Harvey Harrison305787e2008-04-28 02:14:00 -0700382 if (s_inode) {
383 sr.volNumber = NCP_FINFO(s_inode)->volNumber;
384 sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 sr.namespace = server->name_space[sr.volNumber];
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200386 result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 } else
David Howells2b0143b2015-03-17 22:25:59 +0000388 ncp_dbg(1, "d_inode(s_root)==NULL\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 } else
Joe Perchesd3b73ca2014-04-08 16:04:15 -0700390 ncp_dbg(1, "s_root==NULL\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 } else {
392 sr.volNumber = -1;
393 sr.namespace = 0;
394 sr.dirEntNum = 0;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200395 result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200397 mutex_unlock(&server->root_setup_lock);
398 if (!result && copy_to_user(argp, &sr, sizeof(sr)))
399 result = -EFAULT;
400 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
David Howells48937022008-11-14 10:38:58 +1100402
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 case NCP_IOC_SETROOT:
404 {
405 struct ncp_setroot_ioctl sr;
406 __u32 vnum;
407 __le32 de;
408 __le32 dosde;
409 struct dentry* dentry;
410
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 if (copy_from_user(&sr, argp, sizeof(sr)))
412 return -EFAULT;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200413 mutex_lock(&server->root_setup_lock);
414 if (server->root_setuped)
415 result = -EBUSY;
416 else {
417 if (sr.volNumber < 0) {
418 server->m.mounted_vol[0] = 0;
419 vnum = NCP_NUMBER_OF_VOLUMES;
420 de = 0;
421 dosde = 0;
422 result = 0;
423 } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
424 result = -EINVAL;
425 } else if (ncp_mount_subdir(server, sr.volNumber,
426 sr.namespace, sr.dirEntNum,
427 &vnum, &de, &dosde)) {
428 result = -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 } else
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200430 result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200432 if (result == 0) {
433 dentry = inode->i_sb->s_root;
434 if (dentry) {
David Howells2b0143b2015-03-17 22:25:59 +0000435 struct inode* s_inode = d_inode(dentry);
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200436
437 if (s_inode) {
438 NCP_FINFO(s_inode)->volNumber = vnum;
439 NCP_FINFO(s_inode)->dirEntNum = de;
440 NCP_FINFO(s_inode)->DosDirNum = dosde;
441 server->root_setuped = 1;
442 } else {
David Howells2b0143b2015-03-17 22:25:59 +0000443 ncp_dbg(1, "d_inode(s_root)==NULL\n");
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200444 result = -EIO;
445 }
446 } else {
Joe Perchesd3b73ca2014-04-08 16:04:15 -0700447 ncp_dbg(1, "s_root==NULL\n");
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200448 result = -EIO;
449 }
450 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200451 }
452 mutex_unlock(&server->root_setup_lock);
453
454 return result;
455 }
456
457#ifdef CONFIG_NCPFS_PACKET_SIGNING
458 case NCP_IOC_SIGN_INIT:
459 {
460 struct ncp_sign_init sign;
461
462 if (argp)
463 if (copy_from_user(&sign, argp, sizeof(sign)))
464 return -EFAULT;
465 ncp_lock_server(server);
466 mutex_lock(&server->rcv.creq_mutex);
467 if (argp) {
468 if (server->sign_wanted) {
469 memcpy(server->sign_root,sign.sign_root,8);
470 memcpy(server->sign_last,sign.sign_last,16);
471 server->sign_active = 1;
472 }
473 /* ignore when signatures not wanted */
474 } else {
475 server->sign_active = 0;
476 }
477 mutex_unlock(&server->rcv.creq_mutex);
478 ncp_unlock_server(server);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 return 0;
480 }
481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 case NCP_IOC_SIGN_WANTED:
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200483 {
484 int state;
485
486 ncp_lock_server(server);
487 state = server->sign_wanted;
488 ncp_unlock_server(server);
489 if (put_user(state, (int __user *)argp))
490 return -EFAULT;
491 return 0;
492 }
David Howells48937022008-11-14 10:38:58 +1100493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 case NCP_IOC_SET_SIGN_WANTED:
495 {
496 int newstate;
497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 /* get only low 8 bits... */
499 if (get_user(newstate, (unsigned char __user *)argp))
500 return -EFAULT;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200501 result = 0;
502 ncp_lock_server(server);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 if (server->sign_active) {
504 /* cannot turn signatures OFF when active */
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200505 if (!newstate)
506 result = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 } else {
508 server->sign_wanted = newstate != 0;
509 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200510 ncp_unlock_server(server);
511 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 }
513
514#endif /* CONFIG_NCPFS_PACKET_SIGNING */
515
516#ifdef CONFIG_NCPFS_IOCTL_LOCKING
517 case NCP_IOC_LOCKUNLOCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 {
519 struct ncp_lock_ioctl rqdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
521 if (copy_from_user(&rqdata, argp, sizeof(rqdata)))
522 return -EFAULT;
523 if (rqdata.origin != 0)
524 return -EINVAL;
525 /* check for cmd */
526 switch (rqdata.cmd) {
527 case NCP_LOCK_EX:
528 case NCP_LOCK_SH:
Dan Carpenter1491e302015-11-20 15:56:56 -0800529 if (rqdata.timeout < 0)
530 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if (rqdata.timeout == 0)
532 rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT;
533 else if (rqdata.timeout > NCP_LOCK_MAX_TIMEOUT)
534 rqdata.timeout = NCP_LOCK_MAX_TIMEOUT;
535 break;
536 case NCP_LOCK_LOG:
537 rqdata.timeout = NCP_LOCK_DEFAULT_TIMEOUT; /* has no effect */
538 case NCP_LOCK_CLEAR:
539 break;
540 default:
541 return -EINVAL;
542 }
543 /* locking needs both read and write access */
544 if ((result = ncp_make_open(inode, O_RDWR)) != 0)
545 {
546 return result;
547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 result = -EISDIR;
549 if (!S_ISREG(inode->i_mode))
550 goto outrel;
551 if (rqdata.cmd == NCP_LOCK_CLEAR)
552 {
553 result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200554 NCP_FINFO(inode)->file_handle,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 rqdata.offset,
556 rqdata.length);
557 if (result > 0) result = 0; /* no such lock */
558 }
559 else
560 {
561 int lockcmd;
562
563 switch (rqdata.cmd)
564 {
565 case NCP_LOCK_EX: lockcmd=1; break;
566 case NCP_LOCK_SH: lockcmd=3; break;
567 default: lockcmd=0; break;
568 }
569 result = ncp_LogPhysicalRecord(NCP_SERVER(inode),
570 NCP_FINFO(inode)->file_handle,
571 lockcmd,
572 rqdata.offset,
573 rqdata.length,
574 rqdata.timeout);
575 if (result > 0) result = -EAGAIN;
576 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200577outrel:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 ncp_inode_close(inode);
579 return result;
580 }
581#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
582
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700583#ifdef CONFIG_COMPAT
584 case NCP_IOC_GETOBJECTNAME_32:
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700585 {
586 struct compat_ncp_objectname_ioctl user;
587 size_t outl;
588
589 if (copy_from_user(&user, argp, sizeof(user)))
590 return -EFAULT;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200591 down_read(&server->auth_rwsem);
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700592 user.auth_type = server->auth.auth_type;
593 outl = user.object_name_len;
594 user.object_name_len = server->auth.object_name_len;
595 if (outl > user.object_name_len)
596 outl = user.object_name_len;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200597 result = 0;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700598 if (outl) {
599 if (copy_to_user(compat_ptr(user.object_name),
600 server->auth.object_name,
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200601 outl))
602 result = -EFAULT;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700603 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200604 up_read(&server->auth_rwsem);
605 if (!result && copy_to_user(argp, &user, sizeof(user)))
606 result = -EFAULT;
607 return result;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700608 }
609#endif
David Howells48937022008-11-14 10:38:58 +1100610
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 case NCP_IOC_GETOBJECTNAME:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 {
613 struct ncp_objectname_ioctl user;
614 size_t outl;
615
616 if (copy_from_user(&user, argp, sizeof(user)))
617 return -EFAULT;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200618 down_read(&server->auth_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 user.auth_type = server->auth.auth_type;
620 outl = user.object_name_len;
621 user.object_name_len = server->auth.object_name_len;
622 if (outl > user.object_name_len)
623 outl = user.object_name_len;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200624 result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 if (outl) {
626 if (copy_to_user(user.object_name,
627 server->auth.object_name,
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200628 outl))
629 result = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200631 up_read(&server->auth_rwsem);
632 if (!result && copy_to_user(argp, &user, sizeof(user)))
633 result = -EFAULT;
634 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 }
David Howells48937022008-11-14 10:38:58 +1100636
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700637#ifdef CONFIG_COMPAT
638 case NCP_IOC_SETOBJECTNAME_32:
639#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 case NCP_IOC_SETOBJECTNAME:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 {
642 struct ncp_objectname_ioctl user;
643 void* newname;
644 void* oldname;
645 size_t oldnamelen;
646 void* oldprivate;
647 size_t oldprivatelen;
648
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700649#ifdef CONFIG_COMPAT
650 if (cmd == NCP_IOC_SETOBJECTNAME_32) {
651 struct compat_ncp_objectname_ioctl user32;
652 if (copy_from_user(&user32, argp, sizeof(user32)))
653 return -EFAULT;
654 user.auth_type = user32.auth_type;
655 user.object_name_len = user32.object_name_len;
656 user.object_name = compat_ptr(user32.object_name);
657 } else
658#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 if (copy_from_user(&user, argp, sizeof(user)))
660 return -EFAULT;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700661
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
663 return -ENOMEM;
664 if (user.object_name_len) {
Li Zefana9482eb2009-04-08 15:08:53 +0800665 newname = memdup_user(user.object_name,
666 user.object_name_len);
667 if (IS_ERR(newname))
668 return PTR_ERR(newname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 } else {
670 newname = NULL;
671 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200672 down_write(&server->auth_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 oldname = server->auth.object_name;
674 oldnamelen = server->auth.object_name_len;
675 oldprivate = server->priv.data;
676 oldprivatelen = server->priv.len;
677 server->auth.auth_type = user.auth_type;
678 server->auth.object_name_len = user.object_name_len;
679 server->auth.object_name = newname;
680 server->priv.len = 0;
681 server->priv.data = NULL;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200682 up_write(&server->auth_rwsem);
Pekka Enberg44db77f2006-01-14 13:21:12 -0800683 kfree(oldprivate);
684 kfree(oldname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 return 0;
686 }
David Howells48937022008-11-14 10:38:58 +1100687
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700688#ifdef CONFIG_COMPAT
689 case NCP_IOC_GETPRIVATEDATA_32:
690#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 case NCP_IOC_GETPRIVATEDATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 {
693 struct ncp_privatedata_ioctl user;
694 size_t outl;
695
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700696#ifdef CONFIG_COMPAT
697 if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
698 struct compat_ncp_privatedata_ioctl user32;
699 if (copy_from_user(&user32, argp, sizeof(user32)))
700 return -EFAULT;
701 user.len = user32.len;
702 user.data = compat_ptr(user32.data);
703 } else
704#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 if (copy_from_user(&user, argp, sizeof(user)))
706 return -EFAULT;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700707
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200708 down_read(&server->auth_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 outl = user.len;
710 user.len = server->priv.len;
711 if (outl > user.len) outl = user.len;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200712 result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 if (outl) {
714 if (copy_to_user(user.data,
715 server->priv.data,
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200716 outl))
717 result = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200719 up_read(&server->auth_rwsem);
720 if (result)
721 return result;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700722#ifdef CONFIG_COMPAT
723 if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
724 struct compat_ncp_privatedata_ioctl user32;
725 user32.len = user.len;
726 user32.data = (unsigned long) user.data;
Al Viro5c09d962006-10-09 20:24:49 +0100727 if (copy_to_user(argp, &user32, sizeof(user32)))
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700728 return -EFAULT;
729 } else
730#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 if (copy_to_user(argp, &user, sizeof(user)))
732 return -EFAULT;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 return 0;
735 }
David Howells48937022008-11-14 10:38:58 +1100736
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700737#ifdef CONFIG_COMPAT
738 case NCP_IOC_SETPRIVATEDATA_32:
739#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 case NCP_IOC_SETPRIVATEDATA:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 {
742 struct ncp_privatedata_ioctl user;
743 void* new;
744 void* old;
745 size_t oldlen;
746
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700747#ifdef CONFIG_COMPAT
748 if (cmd == NCP_IOC_SETPRIVATEDATA_32) {
749 struct compat_ncp_privatedata_ioctl user32;
750 if (copy_from_user(&user32, argp, sizeof(user32)))
751 return -EFAULT;
752 user.len = user32.len;
753 user.data = compat_ptr(user32.data);
754 } else
755#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 if (copy_from_user(&user, argp, sizeof(user)))
757 return -EFAULT;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700758
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
760 return -ENOMEM;
761 if (user.len) {
Li Zefana9482eb2009-04-08 15:08:53 +0800762 new = memdup_user(user.data, user.len);
763 if (IS_ERR(new))
764 return PTR_ERR(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 } else {
766 new = NULL;
767 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200768 down_write(&server->auth_rwsem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 old = server->priv.data;
770 oldlen = server->priv.len;
771 server->priv.len = user.len;
772 server->priv.data = new;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200773 up_write(&server->auth_rwsem);
Pekka Enberg44db77f2006-01-14 13:21:12 -0800774 kfree(old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 return 0;
776 }
777
778#ifdef CONFIG_NCPFS_NLS
779 case NCP_IOC_SETCHARSETS:
780 return ncp_set_charsets(server, argp);
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200781
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 case NCP_IOC_GETCHARSETS:
783 return ncp_get_charsets(server, argp);
784
785#endif /* CONFIG_NCPFS_NLS */
786
787 case NCP_IOC_SETDENTRYTTL:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 {
789 u_int32_t user;
790
791 if (copy_from_user(&user, argp, sizeof(user)))
792 return -EFAULT;
793 /* 20 secs at most... */
794 if (user > 20000)
795 return -EINVAL;
796 user = (user * HZ) / 1000;
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200797 atomic_set(&server->dentry_ttl, user);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 return 0;
799 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200800
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 case NCP_IOC_GETDENTRYTTL:
802 {
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200803 u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 if (copy_to_user(argp, &user, sizeof(user)))
805 return -EFAULT;
806 return 0;
807 }
808
809 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 return -EINVAL;
811}
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700812
John Kacur93d84b62010-05-05 15:15:37 +0200813long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Dave Hansena761a1c2008-02-15 14:37:39 -0800814{
Al Viro496ad9a2013-01-23 17:07:38 -0500815 struct inode *inode = file_inode(filp);
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200816 struct ncp_server *server = NCP_SERVER(inode);
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -0800817 kuid_t uid = current_uid();
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200818 int need_drop_write = 0;
John Kacur93d84b62010-05-05 15:15:37 +0200819 long ret;
Dave Hansena761a1c2008-02-15 14:37:39 -0800820
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200821 switch (cmd) {
822 case NCP_IOC_SETCHARSETS:
823 case NCP_IOC_CONN_LOGGED_IN:
824 case NCP_IOC_SETROOT:
825 if (!capable(CAP_SYS_ADMIN)) {
Zhao Hongjiang41735812013-02-20 13:13:55 +1100826 ret = -EPERM;
John Kacur93d84b62010-05-05 15:15:37 +0200827 goto out;
828 }
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200829 break;
Dave Hansena761a1c2008-02-15 14:37:39 -0800830 }
Eric W. Biederman1ac7fd82012-02-07 16:28:28 -0800831 if (!uid_eq(server->m.mounted_uid, uid)) {
Petr Vandrovec2e54eb92010-09-27 01:47:33 +0200832 switch (cmd) {
833 /*
834 * Only mount owner can issue these ioctls. Information
835 * necessary to authenticate to other NDS servers are
836 * stored here.
837 */
838 case NCP_IOC_GETOBJECTNAME:
839 case NCP_IOC_SETOBJECTNAME:
840 case NCP_IOC_GETPRIVATEDATA:
841 case NCP_IOC_SETPRIVATEDATA:
842#ifdef CONFIG_COMPAT
843 case NCP_IOC_GETOBJECTNAME_32:
844 case NCP_IOC_SETOBJECTNAME_32:
845 case NCP_IOC_GETPRIVATEDATA_32:
846 case NCP_IOC_SETPRIVATEDATA_32:
847#endif
848 ret = -EACCES;
849 goto out;
850 /*
851 * These require write access on the inode if user id
852 * does not match. Note that they do not write to the
853 * file... But old code did mnt_want_write, so I keep
854 * it as is. Of course not for mountpoint owner, as
855 * that breaks read-only mounts altogether as ncpmount
856 * needs working NCP_IOC_NCPREQUEST and
857 * NCP_IOC_GET_FS_INFO. Some of these codes (setdentryttl,
858 * signinit, setsignwanted) should be probably restricted
859 * to owner only, or even more to CAP_SYS_ADMIN).
860 */
861 case NCP_IOC_GET_FS_INFO:
862 case NCP_IOC_GET_FS_INFO_V2:
863 case NCP_IOC_NCPREQUEST:
864 case NCP_IOC_SETDENTRYTTL:
865 case NCP_IOC_SIGN_INIT:
866 case NCP_IOC_LOCKUNLOCK:
867 case NCP_IOC_SET_SIGN_WANTED:
868#ifdef CONFIG_COMPAT
869 case NCP_IOC_GET_FS_INFO_V2_32:
870 case NCP_IOC_NCPREQUEST_32:
871#endif
872 ret = mnt_want_write_file(filp);
873 if (ret)
874 goto out;
875 need_drop_write = 1;
876 ret = inode_permission(inode, MAY_WRITE);
877 if (ret)
878 goto outDropWrite;
879 break;
880 /*
881 * Read access required.
882 */
883 case NCP_IOC_GETMOUNTUID16:
884 case NCP_IOC_GETMOUNTUID32:
885 case NCP_IOC_GETMOUNTUID64:
886 case NCP_IOC_GETROOT:
887 case NCP_IOC_SIGN_WANTED:
888 ret = inode_permission(inode, MAY_READ);
889 if (ret)
890 goto out;
891 break;
892 /*
893 * Anybody can read these.
894 */
895 case NCP_IOC_GETCHARSETS:
896 case NCP_IOC_GETDENTRYTTL:
897 default:
898 /* Three codes below are protected by CAP_SYS_ADMIN above. */
899 case NCP_IOC_SETCHARSETS:
900 case NCP_IOC_CONN_LOGGED_IN:
901 case NCP_IOC_SETROOT:
902 break;
903 }
904 }
905 ret = __ncp_ioctl(inode, cmd, arg);
906outDropWrite:
907 if (need_drop_write)
Al Viro2a79f172011-12-09 08:06:57 -0500908 mnt_drop_write_file(filp);
John Kacur93d84b62010-05-05 15:15:37 +0200909out:
Dave Hansena761a1c2008-02-15 14:37:39 -0800910 return ret;
911}
912
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700913#ifdef CONFIG_COMPAT
914long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
915{
John Kacur93d84b62010-05-05 15:15:37 +0200916 long ret;
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700917
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700918 arg = (unsigned long) compat_ptr(arg);
John Kacur93d84b62010-05-05 15:15:37 +0200919 ret = ncp_ioctl(file, cmd, arg);
Petr Vandrovec54f67f62006-09-30 23:27:55 -0700920 return ret;
921}
922#endif