OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [ncpfs/] [ioctl.c] - Blame information for rev 82

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
 
10
#include <linux/capability.h>
11
#include <linux/compat.h>
12
#include <linux/errno.h>
13
#include <linux/fs.h>
14
#include <linux/ioctl.h>
15
#include <linux/time.h>
16
#include <linux/mm.h>
17
#include <linux/highuid.h>
18
#include <linux/smp_lock.h>
19
#include <linux/vmalloc.h>
20
#include <linux/sched.h>
21
 
22
#include <linux/ncp_fs.h>
23
 
24
#include <asm/uaccess.h>
25
 
26
#include "ncplib_kernel.h"
27
 
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
 
35
static int
36
ncp_get_fs_info(struct ncp_server * server, struct file *file,
37
                struct ncp_fs_info __user *arg)
38
{
39
        struct inode *inode = file->f_path.dentry->d_inode;
40
        struct ncp_fs_info info;
41
 
42
        if ((file_permission(file, MAY_WRITE) != 0)
43
            && (current->uid != server->m.mounted_uid)) {
44
                return -EACCES;
45
        }
46
        if (copy_from_user(&info, arg, sizeof(info)))
47
                return -EFAULT;
48
 
49
        if (info.version != NCP_GET_FS_INFO_VERSION) {
50
                DPRINTK("info.version invalid: %d\n", info.version);
51
                return -EINVAL;
52
        }
53
        /* TODO: info.addr = server->m.serv_addr; */
54
        SET_UID(info.mounted_uid, server->m.mounted_uid);
55
        info.connection         = server->connection;
56
        info.buffer_size        = server->buffer_size;
57
        info.volume_number      = NCP_FINFO(inode)->volNumber;
58
        info.directory_id       = NCP_FINFO(inode)->DosDirNum;
59
 
60
        if (copy_to_user(arg, &info, sizeof(info)))
61
                return -EFAULT;
62
        return 0;
63
}
64
 
65
static int
66
ncp_get_fs_info_v2(struct ncp_server * server, struct file *file,
67
                   struct ncp_fs_info_v2 __user * arg)
68
{
69
        struct inode *inode = file->f_path.dentry->d_inode;
70
        struct ncp_fs_info_v2 info2;
71
 
72
        if ((file_permission(file, MAY_WRITE) != 0)
73
            && (current->uid != server->m.mounted_uid)) {
74
                return -EACCES;
75
        }
76
        if (copy_from_user(&info2, arg, sizeof(info2)))
77
                return -EFAULT;
78
 
79
        if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
80
                DPRINTK("info.version invalid: %d\n", info2.version);
81
                return -EINVAL;
82
        }
83
        info2.mounted_uid   = server->m.mounted_uid;
84
        info2.connection    = server->connection;
85
        info2.buffer_size   = server->buffer_size;
86
        info2.volume_number = NCP_FINFO(inode)->volNumber;
87
        info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
88
        info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
89
 
90
        if (copy_to_user(arg, &info2, sizeof(info2)))
91
                return -EFAULT;
92
        return 0;
93
}
94
 
95
#ifdef CONFIG_COMPAT
96
struct compat_ncp_objectname_ioctl
97
{
98
        s32             auth_type;
99
        u32             object_name_len;
100
        compat_caddr_t  object_name;    /* an userspace data, in most cases user name */
101
};
102
 
103
struct compat_ncp_fs_info_v2 {
104
        s32 version;
105
        u32 mounted_uid;
106
        u32 connection;
107
        u32 buffer_size;
108
 
109
        u32 volume_number;
110
        u32 directory_id;
111
 
112
        u32 dummy1;
113
        u32 dummy2;
114
        u32 dummy3;
115
};
116
 
117
struct compat_ncp_ioctl_request {
118
        u32 function;
119
        u32 size;
120
        compat_caddr_t data;
121
};
122
 
123
struct compat_ncp_privatedata_ioctl
124
{
125
        u32             len;
126
        compat_caddr_t  data;           /* ~1000 for NDS */
127
};
128
 
129
#define NCP_IOC_GET_FS_INFO_V2_32       _IOWR('n', 4, struct compat_ncp_fs_info_v2)
130
#define NCP_IOC_NCPREQUEST_32           _IOR('n', 1, struct compat_ncp_ioctl_request)
131
#define NCP_IOC_GETOBJECTNAME_32        _IOWR('n', 9, struct compat_ncp_objectname_ioctl)
132
#define NCP_IOC_SETOBJECTNAME_32        _IOR('n', 9, struct compat_ncp_objectname_ioctl)
133
#define NCP_IOC_GETPRIVATEDATA_32       _IOWR('n', 10, struct compat_ncp_privatedata_ioctl)
134
#define NCP_IOC_SETPRIVATEDATA_32       _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
135
 
136
static int
137
ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file,
138
                   struct compat_ncp_fs_info_v2 __user * arg)
139
{
140
        struct inode *inode = file->f_path.dentry->d_inode;
141
        struct compat_ncp_fs_info_v2 info2;
142
 
143
        if ((file_permission(file, MAY_WRITE) != 0)
144
            && (current->uid != server->m.mounted_uid)) {
145
                return -EACCES;
146
        }
147
        if (copy_from_user(&info2, arg, sizeof(info2)))
148
                return -EFAULT;
149
 
150
        if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
151
                DPRINTK("info.version invalid: %d\n", info2.version);
152
                return -EINVAL;
153
        }
154
        info2.mounted_uid   = server->m.mounted_uid;
155
        info2.connection    = server->connection;
156
        info2.buffer_size   = server->buffer_size;
157
        info2.volume_number = NCP_FINFO(inode)->volNumber;
158
        info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
159
        info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
160
 
161
        if (copy_to_user(arg, &info2, sizeof(info2)))
162
                return -EFAULT;
163
        return 0;
164
}
165
#endif
166
 
167
#define NCP_IOC_GETMOUNTUID16           _IOW('n', 2, u16)
168
#define NCP_IOC_GETMOUNTUID32           _IOW('n', 2, u32)
169
#define NCP_IOC_GETMOUNTUID64           _IOW('n', 2, u64)
170
 
171
#ifdef CONFIG_NCPFS_NLS
172
/* Here we are select the iocharset and the codepage for NLS.
173
 * Thanks Petr Vandrovec for idea and many hints.
174
 */
175
static int
176
ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
177
{
178
        struct ncp_nls_ioctl user;
179
        struct nls_table *codepage;
180
        struct nls_table *iocharset;
181
        struct nls_table *oldset_io;
182
        struct nls_table *oldset_cp;
183
 
184
        if (!capable(CAP_SYS_ADMIN))
185
                return -EACCES;
186
        if (server->root_setuped)
187
                return -EBUSY;
188
 
189
        if (copy_from_user(&user, arg, sizeof(user)))
190
                return -EFAULT;
191
 
192
        codepage = NULL;
193
        user.codepage[NCP_IOCSNAME_LEN] = 0;
194
        if (!user.codepage[0] || !strcmp(user.codepage, "default"))
195
                codepage = load_nls_default();
196
        else {
197
                codepage = load_nls(user.codepage);
198
                if (!codepage) {
199
                        return -EBADRQC;
200
                }
201
        }
202
 
203
        iocharset = NULL;
204
        user.iocharset[NCP_IOCSNAME_LEN] = 0;
205
        if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
206
                iocharset = load_nls_default();
207
                NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
208
        } else if (!strcmp(user.iocharset, "utf8")) {
209
                iocharset = load_nls_default();
210
                NCP_SET_FLAG(server, NCP_FLAG_UTF8);
211
        } else {
212
                iocharset = load_nls(user.iocharset);
213
                if (!iocharset) {
214
                        unload_nls(codepage);
215
                        return -EBADRQC;
216
                }
217
                NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
218
        }
219
 
220
        oldset_cp = server->nls_vol;
221
        server->nls_vol = codepage;
222
        oldset_io = server->nls_io;
223
        server->nls_io = iocharset;
224
 
225
        if (oldset_cp)
226
                unload_nls(oldset_cp);
227
        if (oldset_io)
228
                unload_nls(oldset_io);
229
 
230
        return 0;
231
}
232
 
233
static int
234
ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
235
{
236
        struct ncp_nls_ioctl user;
237
        int len;
238
 
239
        memset(&user, 0, sizeof(user));
240
        if (server->nls_vol && server->nls_vol->charset) {
241
                len = strlen(server->nls_vol->charset);
242
                if (len > NCP_IOCSNAME_LEN)
243
                        len = NCP_IOCSNAME_LEN;
244
                strncpy(user.codepage, server->nls_vol->charset, len);
245
                user.codepage[len] = 0;
246
        }
247
 
248
        if (NCP_IS_FLAG(server, NCP_FLAG_UTF8))
249
                strcpy(user.iocharset, "utf8");
250
        else if (server->nls_io && server->nls_io->charset) {
251
                len = strlen(server->nls_io->charset);
252
                if (len > NCP_IOCSNAME_LEN)
253
                        len = NCP_IOCSNAME_LEN;
254
                strncpy(user.iocharset, server->nls_io->charset, len);
255
                user.iocharset[len] = 0;
256
        }
257
 
258
        if (copy_to_user(arg, &user, sizeof(user)))
259
                return -EFAULT;
260
        return 0;
261
}
262
#endif /* CONFIG_NCPFS_NLS */
263
 
264
int ncp_ioctl(struct inode *inode, struct file *filp,
265
              unsigned int cmd, unsigned long arg)
266
{
267
        struct ncp_server *server = NCP_SERVER(inode);
268
        int result;
269
        struct ncp_ioctl_request request;
270
        char* bouncebuffer;
271
        void __user *argp = (void __user *)arg;
272
 
273
        switch (cmd) {
274
#ifdef CONFIG_COMPAT
275
        case NCP_IOC_NCPREQUEST_32:
276
#endif
277
        case NCP_IOC_NCPREQUEST:
278
                if ((file_permission(filp, MAY_WRITE) != 0)
279
                    && (current->uid != server->m.mounted_uid)) {
280
                        return -EACCES;
281
                }
282
#ifdef CONFIG_COMPAT
283
                if (cmd == NCP_IOC_NCPREQUEST_32) {
284
                        struct compat_ncp_ioctl_request request32;
285
                        if (copy_from_user(&request32, argp, sizeof(request32)))
286
                                return -EFAULT;
287
                        request.function = request32.function;
288
                        request.size = request32.size;
289
                        request.data = compat_ptr(request32.data);
290
                } else
291
#endif
292
                if (copy_from_user(&request, argp, sizeof(request)))
293
                        return -EFAULT;
294
 
295
                if ((request.function > 255)
296
                    || (request.size >
297
                  NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
298
                        return -EINVAL;
299
                }
300
                bouncebuffer = vmalloc(NCP_PACKET_SIZE_INTERNAL);
301
                if (!bouncebuffer)
302
                        return -ENOMEM;
303
                if (copy_from_user(bouncebuffer, request.data, request.size)) {
304
                        vfree(bouncebuffer);
305
                        return -EFAULT;
306
                }
307
                ncp_lock_server(server);
308
 
309
                /* FIXME: We hack around in the server's structures
310
                   here to be able to use ncp_request */
311
 
312
                server->has_subfunction = 0;
313
                server->current_size = request.size;
314
                memcpy(server->packet, bouncebuffer, request.size);
315
 
316
                result = ncp_request2(server, request.function,
317
                        bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
318
                if (result < 0)
319
                        result = -EIO;
320
                else
321
                        result = server->reply_size;
322
                ncp_unlock_server(server);
323
                DPRINTK("ncp_ioctl: copy %d bytes\n",
324
                        result);
325
                if (result >= 0)
326
                        if (copy_to_user(request.data, bouncebuffer, result))
327
                                result = -EFAULT;
328
                vfree(bouncebuffer);
329
                return result;
330
 
331
        case NCP_IOC_CONN_LOGGED_IN:
332
 
333
                if (!capable(CAP_SYS_ADMIN))
334
                        return -EACCES;
335
                if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
336
                        return -EINVAL;
337
                if (server->root_setuped)
338
                        return -EBUSY;
339
                server->root_setuped = 1;
340
                return ncp_conn_logged_in(inode->i_sb);
341
 
342
        case NCP_IOC_GET_FS_INFO:
343
                return ncp_get_fs_info(server, filp, argp);
344
 
345
        case NCP_IOC_GET_FS_INFO_V2:
346
                return ncp_get_fs_info_v2(server, filp, argp);
347
 
348
#ifdef CONFIG_COMPAT
349
        case NCP_IOC_GET_FS_INFO_V2_32:
350
                return ncp_get_compat_fs_info_v2(server, filp, argp);
351
#endif
352
        /* we have too many combinations of CONFIG_COMPAT,
353
         * CONFIG_64BIT and CONFIG_UID16, so just handle
354
         * any of the possible ioctls */
355
        case NCP_IOC_GETMOUNTUID16:
356
        case NCP_IOC_GETMOUNTUID32:
357
        case NCP_IOC_GETMOUNTUID64:
358
                if ((file_permission(filp, MAY_READ) != 0)
359
                        && (current->uid != server->m.mounted_uid)) {
360
                        return -EACCES;
361
                }
362
                if (cmd == NCP_IOC_GETMOUNTUID16) {
363
                        u16 uid;
364
                        SET_UID(uid, server->m.mounted_uid);
365
                        if (put_user(uid, (u16 __user *)argp))
366
                                return -EFAULT;
367
                } else if (cmd == NCP_IOC_GETMOUNTUID32) {
368
                        if (put_user(server->m.mounted_uid,
369
                                                (u32 __user *)argp))
370
                                return -EFAULT;
371
                } else {
372
                        if (put_user(server->m.mounted_uid,
373
                                                (u64 __user *)argp))
374
                                return -EFAULT;
375
                }
376
                return 0;
377
 
378
        case NCP_IOC_GETROOT:
379
                {
380
                        struct ncp_setroot_ioctl sr;
381
 
382
                        if ((file_permission(filp, MAY_READ) != 0)
383
                            && (current->uid != server->m.mounted_uid))
384
                        {
385
                                return -EACCES;
386
                        }
387
                        if (server->m.mounted_vol[0]) {
388
                                struct dentry* dentry = inode->i_sb->s_root;
389
 
390
                                if (dentry) {
391
                                        struct inode* inode = dentry->d_inode;
392
 
393
                                        if (inode) {
394
                                                sr.volNumber = NCP_FINFO(inode)->volNumber;
395
                                                sr.dirEntNum = NCP_FINFO(inode)->dirEntNum;
396
                                                sr.namespace = server->name_space[sr.volNumber];
397
                                        } else
398
                                                DPRINTK("ncpfs: s_root->d_inode==NULL\n");
399
                                } else
400
                                        DPRINTK("ncpfs: s_root==NULL\n");
401
                        } else {
402
                                sr.volNumber = -1;
403
                                sr.namespace = 0;
404
                                sr.dirEntNum = 0;
405
                        }
406
                        if (copy_to_user(argp, &sr, sizeof(sr)))
407
                                return -EFAULT;
408
                        return 0;
409
                }
410
        case NCP_IOC_SETROOT:
411
                {
412
                        struct ncp_setroot_ioctl sr;
413
                        __u32 vnum;
414
                        __le32 de;
415
                        __le32 dosde;
416
                        struct dentry* dentry;
417
 
418
                        if (!capable(CAP_SYS_ADMIN))
419
                        {
420
                                return -EACCES;
421
                        }
422
                        if (server->root_setuped) return -EBUSY;
423
                        if (copy_from_user(&sr, argp, sizeof(sr)))
424
                                return -EFAULT;
425
                        if (sr.volNumber < 0) {
426
                                server->m.mounted_vol[0] = 0;
427
                                vnum = NCP_NUMBER_OF_VOLUMES;
428
                                de = 0;
429
                                dosde = 0;
430
                        } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
431
                                return -EINVAL;
432
                        } else if (ncp_mount_subdir(server, sr.volNumber,
433
                                                sr.namespace, sr.dirEntNum,
434
                                                &vnum, &de, &dosde)) {
435
                                return -ENOENT;
436
                        }
437
 
438
                        dentry = inode->i_sb->s_root;
439
                        server->root_setuped = 1;
440
                        if (dentry) {
441
                                struct inode* inode = dentry->d_inode;
442
 
443
                                if (inode) {
444
                                        NCP_FINFO(inode)->volNumber = vnum;
445
                                        NCP_FINFO(inode)->dirEntNum = de;
446
                                        NCP_FINFO(inode)->DosDirNum = dosde;
447
                                } else
448
                                        DPRINTK("ncpfs: s_root->d_inode==NULL\n");
449
                        } else
450
                                DPRINTK("ncpfs: s_root==NULL\n");
451
 
452
                        return 0;
453
                }
454
 
455
#ifdef CONFIG_NCPFS_PACKET_SIGNING      
456
        case NCP_IOC_SIGN_INIT:
457
                if ((file_permission(filp, MAY_WRITE) != 0)
458
                    && (current->uid != server->m.mounted_uid))
459
                {
460
                        return -EACCES;
461
                }
462
                if (argp) {
463
                        if (server->sign_wanted)
464
                        {
465
                                struct ncp_sign_init sign;
466
 
467
                                if (copy_from_user(&sign, argp, sizeof(sign)))
468
                                        return -EFAULT;
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
                return 0;
478
 
479
        case NCP_IOC_SIGN_WANTED:
480
                if ((file_permission(filp, MAY_READ) != 0)
481
                    && (current->uid != server->m.mounted_uid))
482
                {
483
                        return -EACCES;
484
                }
485
 
486
                if (put_user(server->sign_wanted, (int __user *)argp))
487
                        return -EFAULT;
488
                return 0;
489
        case NCP_IOC_SET_SIGN_WANTED:
490
                {
491
                        int newstate;
492
 
493
                        if ((file_permission(filp, MAY_WRITE) != 0)
494
                            && (current->uid != server->m.mounted_uid))
495
                        {
496
                                return -EACCES;
497
                        }
498
                        /* get only low 8 bits... */
499
                        if (get_user(newstate, (unsigned char __user *)argp))
500
                                return -EFAULT;
501
                        if (server->sign_active) {
502
                                /* cannot turn signatures OFF when active */
503
                                if (!newstate) return -EINVAL;
504
                        } else {
505
                                server->sign_wanted = newstate != 0;
506
                        }
507
                        return 0;
508
                }
509
 
510
#endif /* CONFIG_NCPFS_PACKET_SIGNING */
511
 
512
#ifdef CONFIG_NCPFS_IOCTL_LOCKING
513
        case NCP_IOC_LOCKUNLOCK:
514
                if ((file_permission(filp, MAY_WRITE) != 0)
515
                    && (current->uid != server->m.mounted_uid))
516
                {
517
                        return -EACCES;
518
                }
519
                {
520
                        struct ncp_lock_ioctl    rqdata;
521
                        int result;
522
 
523
                        if (copy_from_user(&rqdata, argp, sizeof(rqdata)))
524
                                return -EFAULT;
525
                        if (rqdata.origin != 0)
526
                                return -EINVAL;
527
                        /* check for cmd */
528
                        switch (rqdata.cmd) {
529
                                case NCP_LOCK_EX:
530
                                case NCP_LOCK_SH:
531
                                                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
                        }
548
                        result = -EIO;
549
                        if (!ncp_conn_valid(server))
550
                                goto outrel;
551
                        result = -EISDIR;
552
                        if (!S_ISREG(inode->i_mode))
553
                                goto outrel;
554
                        if (rqdata.cmd == NCP_LOCK_CLEAR)
555
                        {
556
                                result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
557
                                                        NCP_FINFO(inode)->file_handle,
558
                                                        rqdata.offset,
559
                                                        rqdata.length);
560
                                if (result > 0) result = 0;       /* no such lock */
561
                        }
562
                        else
563
                        {
564
                                int lockcmd;
565
 
566
                                switch (rqdata.cmd)
567
                                {
568
                                        case NCP_LOCK_EX:  lockcmd=1; break;
569
                                        case NCP_LOCK_SH:  lockcmd=3; break;
570
                                        default:           lockcmd=0; break;
571
                                }
572
                                result = ncp_LogPhysicalRecord(NCP_SERVER(inode),
573
                                                        NCP_FINFO(inode)->file_handle,
574
                                                        lockcmd,
575
                                                        rqdata.offset,
576
                                                        rqdata.length,
577
                                                        rqdata.timeout);
578
                                if (result > 0) result = -EAGAIN;
579
                        }
580
outrel:
581
                        ncp_inode_close(inode);
582
                        return result;
583
                }
584
#endif  /* CONFIG_NCPFS_IOCTL_LOCKING */
585
 
586
#ifdef CONFIG_COMPAT
587
        case NCP_IOC_GETOBJECTNAME_32:
588
                if (current->uid != server->m.mounted_uid) {
589
                        return -EACCES;
590
                }
591
                {
592
                        struct compat_ncp_objectname_ioctl user;
593
                        size_t outl;
594
 
595
                        if (copy_from_user(&user, argp, sizeof(user)))
596
                                return -EFAULT;
597
                        user.auth_type = server->auth.auth_type;
598
                        outl = user.object_name_len;
599
                        user.object_name_len = server->auth.object_name_len;
600
                        if (outl > user.object_name_len)
601
                                outl = user.object_name_len;
602
                        if (outl) {
603
                                if (copy_to_user(compat_ptr(user.object_name),
604
                                                 server->auth.object_name,
605
                                                 outl)) return -EFAULT;
606
                        }
607
                        if (copy_to_user(argp, &user, sizeof(user)))
608
                                return -EFAULT;
609
                        return 0;
610
                }
611
#endif
612
        case NCP_IOC_GETOBJECTNAME:
613
                if (current->uid != server->m.mounted_uid) {
614
                        return -EACCES;
615
                }
616
                {
617
                        struct ncp_objectname_ioctl user;
618
                        size_t outl;
619
 
620
                        if (copy_from_user(&user, argp, sizeof(user)))
621
                                return -EFAULT;
622
                        user.auth_type = server->auth.auth_type;
623
                        outl = user.object_name_len;
624
                        user.object_name_len = server->auth.object_name_len;
625
                        if (outl > user.object_name_len)
626
                                outl = user.object_name_len;
627
                        if (outl) {
628
                                if (copy_to_user(user.object_name,
629
                                                 server->auth.object_name,
630
                                                 outl)) return -EFAULT;
631
                        }
632
                        if (copy_to_user(argp, &user, sizeof(user)))
633
                                return -EFAULT;
634
                        return 0;
635
                }
636
#ifdef CONFIG_COMPAT
637
        case NCP_IOC_SETOBJECTNAME_32:
638
#endif
639
        case NCP_IOC_SETOBJECTNAME:
640
                if (current->uid != server->m.mounted_uid) {
641
                        return -EACCES;
642
                }
643
                {
644
                        struct ncp_objectname_ioctl user;
645
                        void* newname;
646
                        void* oldname;
647
                        size_t oldnamelen;
648
                        void* oldprivate;
649
                        size_t oldprivatelen;
650
 
651
#ifdef CONFIG_COMPAT
652
                        if (cmd == NCP_IOC_SETOBJECTNAME_32) {
653
                                struct compat_ncp_objectname_ioctl user32;
654
                                if (copy_from_user(&user32, argp, sizeof(user32)))
655
                                        return -EFAULT;
656
                                user.auth_type = user32.auth_type;
657
                                user.object_name_len = user32.object_name_len;
658
                                user.object_name = compat_ptr(user32.object_name);
659
                        } else
660
#endif
661
                        if (copy_from_user(&user, argp, sizeof(user)))
662
                                return -EFAULT;
663
 
664
                        if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
665
                                return -ENOMEM;
666
                        if (user.object_name_len) {
667
                                newname = kmalloc(user.object_name_len, GFP_USER);
668
                                if (!newname)
669
                                        return -ENOMEM;
670
                                if (copy_from_user(newname, user.object_name, user.object_name_len)) {
671
                                        kfree(newname);
672
                                        return -EFAULT;
673
                                }
674
                        } else {
675
                                newname = NULL;
676
                        }
677
                        /* enter critical section */
678
                        /* maybe that kfree can sleep so do that this way */
679
                        /* it is at least more SMP friendly (in future...) */
680
                        oldname = server->auth.object_name;
681
                        oldnamelen = server->auth.object_name_len;
682
                        oldprivate = server->priv.data;
683
                        oldprivatelen = server->priv.len;
684
                        server->auth.auth_type = user.auth_type;
685
                        server->auth.object_name_len = user.object_name_len;
686
                        server->auth.object_name = newname;
687
                        server->priv.len = 0;
688
                        server->priv.data = NULL;
689
                        /* leave critical section */
690
                        kfree(oldprivate);
691
                        kfree(oldname);
692
                        return 0;
693
                }
694
#ifdef CONFIG_COMPAT
695
        case NCP_IOC_GETPRIVATEDATA_32:
696
#endif
697
        case NCP_IOC_GETPRIVATEDATA:
698
                if (current->uid != server->m.mounted_uid) {
699
                        return -EACCES;
700
                }
701
                {
702
                        struct ncp_privatedata_ioctl user;
703
                        size_t outl;
704
 
705
#ifdef CONFIG_COMPAT
706
                        if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
707
                                struct compat_ncp_privatedata_ioctl user32;
708
                                if (copy_from_user(&user32, argp, sizeof(user32)))
709
                                        return -EFAULT;
710
                                user.len = user32.len;
711
                                user.data = compat_ptr(user32.data);
712
                        } else
713
#endif
714
                        if (copy_from_user(&user, argp, sizeof(user)))
715
                                return -EFAULT;
716
 
717
                        outl = user.len;
718
                        user.len = server->priv.len;
719
                        if (outl > user.len) outl = user.len;
720
                        if (outl) {
721
                                if (copy_to_user(user.data,
722
                                                 server->priv.data,
723
                                                 outl)) return -EFAULT;
724
                        }
725
#ifdef CONFIG_COMPAT
726
                        if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
727
                                struct compat_ncp_privatedata_ioctl user32;
728
                                user32.len = user.len;
729
                                user32.data = (unsigned long) user.data;
730
                                if (copy_to_user(argp, &user32, sizeof(user32)))
731
                                        return -EFAULT;
732
                        } else
733
#endif
734
                        if (copy_to_user(argp, &user, sizeof(user)))
735
                                return -EFAULT;
736
 
737
                        return 0;
738
                }
739
#ifdef CONFIG_COMPAT
740
        case NCP_IOC_SETPRIVATEDATA_32:
741
#endif
742
        case NCP_IOC_SETPRIVATEDATA:
743
                if (current->uid != server->m.mounted_uid) {
744
                        return -EACCES;
745
                }
746
                {
747
                        struct ncp_privatedata_ioctl user;
748
                        void* new;
749
                        void* old;
750
                        size_t oldlen;
751
 
752
#ifdef CONFIG_COMPAT
753
                        if (cmd == NCP_IOC_SETPRIVATEDATA_32) {
754
                                struct compat_ncp_privatedata_ioctl user32;
755
                                if (copy_from_user(&user32, argp, sizeof(user32)))
756
                                        return -EFAULT;
757
                                user.len = user32.len;
758
                                user.data = compat_ptr(user32.data);
759
                        } else
760
#endif
761
                        if (copy_from_user(&user, argp, sizeof(user)))
762
                                return -EFAULT;
763
 
764
                        if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
765
                                return -ENOMEM;
766
                        if (user.len) {
767
                                new = kmalloc(user.len, GFP_USER);
768
                                if (!new)
769
                                        return -ENOMEM;
770
                                if (copy_from_user(new, user.data, user.len)) {
771
                                        kfree(new);
772
                                        return -EFAULT;
773
                                }
774
                        } else {
775
                                new = NULL;
776
                        }
777
                        /* enter critical section */
778
                        old = server->priv.data;
779
                        oldlen = server->priv.len;
780
                        server->priv.len = user.len;
781
                        server->priv.data = new;
782
                        /* leave critical section */
783
                        kfree(old);
784
                        return 0;
785
                }
786
 
787
#ifdef CONFIG_NCPFS_NLS
788
        case NCP_IOC_SETCHARSETS:
789
                return ncp_set_charsets(server, argp);
790
 
791
        case NCP_IOC_GETCHARSETS:
792
                return ncp_get_charsets(server, argp);
793
 
794
#endif /* CONFIG_NCPFS_NLS */
795
 
796
        case NCP_IOC_SETDENTRYTTL:
797
                if ((file_permission(filp, MAY_WRITE) != 0) &&
798
                                 (current->uid != server->m.mounted_uid))
799
                        return -EACCES;
800
                {
801
                        u_int32_t user;
802
 
803
                        if (copy_from_user(&user, argp, sizeof(user)))
804
                                return -EFAULT;
805
                        /* 20 secs at most... */
806
                        if (user > 20000)
807
                                return -EINVAL;
808
                        user = (user * HZ) / 1000;
809
                        server->dentry_ttl = user;
810
                        return 0;
811
                }
812
 
813
        case NCP_IOC_GETDENTRYTTL:
814
                {
815
                        u_int32_t user = (server->dentry_ttl * 1000) / HZ;
816
                        if (copy_to_user(argp, &user, sizeof(user)))
817
                                return -EFAULT;
818
                        return 0;
819
                }
820
 
821
        }
822
        return -EINVAL;
823
}
824
 
825
#ifdef CONFIG_COMPAT
826
long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
827
{
828
        struct inode *inode = file->f_path.dentry->d_inode;
829
        int ret;
830
 
831
        lock_kernel();
832
        arg = (unsigned long) compat_ptr(arg);
833
        ret = ncp_ioctl(inode, file, cmd, arg);
834
        unlock_kernel();
835
        return ret;
836
}
837
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.