1 /* $Id: timod.c,v 1.10 2000/07/28 12:15:02 davem Exp $
2 * timod.c: timod emulation.
4 * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
6 * Streams & timod emulation based on code
7 * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/smp.h>
15 #include <linux/smp_lock.h>
16 #include <linux/ioctl.h>
18 #include <linux/file.h>
19 #include <linux/netdevice.h>
20 #include <linux/poll.h>
24 #include <asm/uaccess.h>
25 #include <asm/termios.h>
30 extern asmlinkage
int sys_ioctl(unsigned int fd
, unsigned int cmd
,
32 extern asmlinkage
int sys32_ioctl(unsigned int fd
, unsigned int cmd
,
34 asmlinkage
int solaris_ioctl(unsigned int fd
, unsigned int cmd
, u32 arg
);
36 spinlock_t timod_pagelock
= SPIN_LOCK_UNLOCKED
;
37 static char * page
= NULL
;
39 #ifndef DEBUG_SOLARIS_KMALLOC
41 #define mykmalloc kmalloc
46 void * mykmalloc(size_t s
, int gfp
)
49 static size_t free
= 0;
53 SOLD("too big size, calling real kmalloc");
54 return kmalloc(s
, gfp
);
57 /* we are wasting memory, but we don't care */
58 page
= (char *)__get_free_page(gfp
);
75 #define BUF_SIZE PAGE_SIZE
76 #define PUT_MAGIC(a,m)
77 #define SCHECK_MAGIC(a,m)
79 #define MKCTL_TRAILER 0
83 #define BUF_SIZE (PAGE_SIZE-2*sizeof(u64))
84 #define BUFPAGE_MAGIC 0xBADC0DEDDEADBABEL
85 #define MKCTL_MAGIC 0xDEADBABEBADC0DEDL
86 #define PUT_MAGIC(a,m) do{(*(u64*)(a))=(m);}while(0)
87 #define SCHECK_MAGIC(a,m) do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
88 __FILE__,__LINE__,__FUNCTION__,(m),(a));}while(0)
89 #define BUF_OFFSET sizeof(u64)
90 #define MKCTL_TRAILER sizeof(u64)
94 static char *getpage( void )
98 spin_lock(&timod_pagelock
);
102 spin_unlock(&timod_pagelock
);
104 return r
+ BUF_OFFSET
;
106 spin_unlock(&timod_pagelock
);
108 r
= (char *)__get_free_page(GFP_KERNEL
);
109 PUT_MAGIC(r
,BUFPAGE_MAGIC
);
110 PUT_MAGIC(r
+PAGE_SIZE
-sizeof(u64
),BUFPAGE_MAGIC
);
111 return r
+ BUF_OFFSET
;
114 static void putpage(char *p
)
116 SOLD("putting page");
118 SCHECK_MAGIC(p
,BUFPAGE_MAGIC
);
119 SCHECK_MAGIC(p
+PAGE_SIZE
-sizeof(u64
),BUFPAGE_MAGIC
);
120 spin_lock(&timod_pagelock
);
122 spin_unlock(&timod_pagelock
);
123 free_page((unsigned long)p
);
127 spin_unlock(&timod_pagelock
);
132 static struct T_primsg
*timod_mkctl(int size
)
136 SOLD("creating primsg");
137 it
= (struct T_primsg
*)mykmalloc(size
+sizeof(*it
)-sizeof(s32
)+2*MKCTL_TRAILER
, GFP_KERNEL
);
142 PUT_MAGIC((char*)((u64
)(((char *)&it
->type
)+size
+7)&~7),MKCTL_MAGIC
);
147 static void timod_wake_socket(unsigned int fd
)
151 SOLD("wakeing socket");
152 sock
= ¤t
->files
->fd
[fd
]->f_dentry
->d_inode
->u
.socket_i
;
153 wake_up_interruptible(&sock
->wait
);
154 read_lock(&sock
->sk
->callback_lock
);
155 if (sock
->fasync_list
&& !test_bit(SOCK_ASYNC_WAITDATA
, &sock
->flags
))
156 __kill_fasync(sock
->fasync_list
, SIGIO
, POLL_IN
);
157 read_unlock(&sock
->sk
->callback_lock
);
161 static void timod_queue(unsigned int fd
, struct T_primsg
*it
)
163 struct sol_socket_struct
*sock
;
165 SOLD("queuing primsg");
166 sock
= (struct sol_socket_struct
*)current
->files
->fd
[fd
]->private_data
;
167 it
->next
= sock
->pfirst
;
171 timod_wake_socket(fd
);
175 static void timod_queue_end(unsigned int fd
, struct T_primsg
*it
)
177 struct sol_socket_struct
*sock
;
179 SOLD("queuing primsg at end");
180 sock
= (struct sol_socket_struct
*)current
->files
->fd
[fd
]->private_data
;
183 sock
->plast
->next
= it
;
190 static void timod_error(unsigned int fd
, int prim
, int terr
, int uerr
)
194 SOLD("making error");
195 it
= timod_mkctl(sizeof(struct T_error_ack
));
197 struct T_error_ack
*err
= (struct T_error_ack
*)&it
->type
;
200 err
->PRIM_type
= T_ERROR_ACK
;
201 err
->ERROR_prim
= prim
;
202 err
->TLI_error
= terr
;
203 err
->UNIX_error
= uerr
; /* FIXME: convert this */
209 static void timod_ok(unsigned int fd
, int prim
)
214 SOLD("creating ok ack");
215 it
= timod_mkctl(sizeof(*ok
));
218 ok
= (struct T_ok_ack
*)&it
->type
;
219 ok
->PRIM_type
= T_OK_ACK
;
220 ok
->CORRECT_prim
= prim
;
226 static int timod_optmgmt(unsigned int fd
, int flag
, char *opt_buf
, int opt_len
, int do_ret
)
229 int ret_space
, ret_len
;
231 char *ret_pos
,*ret_buf
;
232 int (*sys_socketcall
)(int, unsigned long *) =
233 (int (*)(int, unsigned long *))SYS(socketcall
);
234 mm_segment_t old_fs
= get_fs();
237 SOLDD(("fd %u flg %u buf %p len %u doret %u",fd
,flag
,opt_buf
,opt_len
,do_ret
));
238 if (!do_ret
&& (!opt_buf
|| opt_len
<= 0))
240 SOLD("getting page");
241 ret_pos
= ret_buf
= getpage();
242 ret_space
= BUF_SIZE
;
247 while(opt_len
>= sizeof(struct opthdr
)) {
251 opt
= (struct opthdr
*)ret_pos
;
252 if (ret_space
< sizeof(struct opthdr
)) {
256 SOLD("getting opthdr");
257 if (copy_from_user(opt
, opt_buf
, sizeof(struct opthdr
)) ||
258 opt
->len
> opt_len
) {
263 if (flag
== T_NEGOTIATE
) {
266 SOLD("handling T_NEGOTIATE");
267 buf
= ret_pos
+ sizeof(struct opthdr
);
268 if (ret_space
< opt
->len
+ sizeof(struct opthdr
) ||
269 copy_from_user(buf
, opt_buf
+sizeof(struct opthdr
), opt
->len
)) {
275 args
[1] = opt
->level
;
279 SOLD("calling SETSOCKOPT");
281 error
= sys_socketcall(SYS_SETSOCKOPT
, args
);
287 SOLD("SETSOCKOPT ok");
289 orig_opt_len
= opt
->len
;
290 opt
->len
= ret_space
- sizeof(struct opthdr
);
296 args
[1] = opt
->level
;
298 args
[3] = (long)(ret_pos
+sizeof(struct opthdr
));
299 args
[4] = (long)&opt
->len
;
300 SOLD("calling GETSOCKOPT");
302 error
= sys_socketcall(SYS_GETSOCKOPT
, args
);
308 SOLD("GETSOCKOPT ok");
309 ret_space
-= sizeof(struct opthdr
) + opt
->len
;
310 ret_len
+= sizeof(struct opthdr
) + opt
->len
;
311 ret_pos
+= sizeof(struct opthdr
) + opt
->len
;
312 opt_len
-= sizeof(struct opthdr
) + orig_opt_len
;
313 opt_buf
+= sizeof(struct opthdr
) + orig_opt_len
;
318 SOLD("generating ret msg");
320 timod_error(fd
, T_OPTMGMT_REQ
, failed
, -error
);
323 it
= timod_mkctl(sizeof(struct T_optmgmt_ack
) + ret_len
);
325 struct T_optmgmt_ack
*ack
=
326 (struct T_optmgmt_ack
*)&it
->type
;
328 ack
->PRIM_type
= T_OPTMGMT_ACK
;
329 ack
->OPT_length
= ret_len
;
330 ack
->OPT_offset
= sizeof(struct T_optmgmt_ack
);
331 ack
->MGMT_flags
= (failed
? T_FAILURE
: flag
);
332 memcpy(((char*)ack
)+sizeof(struct T_optmgmt_ack
),
338 SOLDD(("put_page %p\n", ret_buf
));
344 int timod_putmsg(unsigned int fd
, char *ctl_buf
, int ctl_len
,
345 char *data_buf
, int data_len
, int flags
)
347 int ret
, error
, terror
;
351 struct sol_socket_struct
*sock
;
352 mm_segment_t old_fs
= get_fs();
354 int (*sys_socketcall
)(int, unsigned long *) =
355 (int (*)(int, unsigned long *))SYS(socketcall
);
356 int (*sys_sendto
)(int, void *, size_t, unsigned, struct sockaddr
*, int) =
357 (int (*)(int, void *, size_t, unsigned, struct sockaddr
*, int))SYS(sendto
);
358 filp
= current
->files
->fd
[fd
];
359 ino
= filp
->f_dentry
->d_inode
;
360 sock
= (struct sol_socket_struct
*)filp
->private_data
;
362 if (get_user(ret
, (int *)A(ctl_buf
)))
367 struct T_bind_req req
;
369 SOLDD(("bind %016lx(%016lx)\n", sock
, filp
));
371 if (sock
->state
!= TS_UNBND
) {
372 timod_error(fd
, T_BIND_REQ
, TOUTSTATE
, 0);
376 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
377 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
381 if (req
.ADDR_offset
&& req
.ADDR_length
) {
382 if (req
.ADDR_length
> BUF_SIZE
) {
383 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
388 if (copy_from_user(buf
, ctl_buf
+ req
.ADDR_offset
, req
.ADDR_length
)) {
389 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
393 SOLD("got ctl data");
396 args
[2] = req
.ADDR_length
;
397 SOLD("calling BIND");
399 error
= sys_socketcall(SYS_BIND
, args
);
402 SOLD("BIND returned");
407 if (req
.CONIND_number
) {
409 args
[1] = req
.CONIND_number
;
410 SOLD("calling LISTEN");
412 error
= sys_socketcall(SYS_LISTEN
, args
);
416 it
= timod_mkctl(sizeof(struct T_bind_ack
)+sizeof(struct sockaddr
));
418 struct T_bind_ack
*ack
;
420 ack
= (struct T_bind_ack
*)&it
->type
;
421 ack
->PRIM_type
= T_BIND_ACK
;
422 ack
->ADDR_offset
= sizeof(*ack
);
423 ack
->ADDR_length
= sizeof(struct sockaddr
);
424 ack
->CONIND_number
= req
.CONIND_number
;
426 args
[1] = (long)(ack
+sizeof(*ack
));
427 args
[2] = (long)&ack
->ADDR_length
;
429 sys_socketcall(SYS_GETSOCKNAME
,args
);
431 sock
->state
= TS_IDLE
;
432 timod_ok(fd
, T_BIND_REQ
);
433 timod_queue_end(fd
, it
);
457 timod_error(fd
, T_BIND_REQ
, terror
, -error
);
463 struct T_conn_req req
;
464 unsigned short oldflags
;
467 if (sock
->state
!= TS_UNBND
&& sock
->state
!= TS_IDLE
) {
468 timod_error(fd
, T_CONN_REQ
, TOUTSTATE
, 0);
472 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
473 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
477 if (ctl_len
> BUF_SIZE
) {
478 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
483 if (copy_from_user(buf
, ctl_buf
, ctl_len
)) {
484 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
492 printk("returned data (%d bytes): ",len
);
496 printk("%02x",(unsigned char)*ptr
++);
501 SOLD("got ctl data");
503 args
[1] = (long)buf
+req
.DEST_offset
;
504 args
[2] = req
.DEST_length
;
505 oldflags
= filp
->f_flags
;
506 filp
->f_flags
&= ~O_NONBLOCK
;
507 SOLD("calling CONNECT");
509 error
= sys_socketcall(SYS_CONNECT
, args
);
511 filp
->f_flags
= oldflags
;
512 SOLD("CONNECT done");
514 struct T_conn_con
*con
;
516 it
= timod_mkctl(ctl_len
);
521 con
= (struct T_conn_con
*)&it
->type
;
526 printk("returned data (%d bytes): ",len
);
530 printk("%02x",(unsigned char)*ptr
++);
535 memcpy(con
, buf
, ctl_len
);
536 SOLD("copied ctl_buf");
537 con
->PRIM_type
= T_CONN_CON
;
538 sock
->state
= TS_DATA_XFER
;
540 struct T_discon_ind
*dis
;
542 it
= timod_mkctl(sizeof(*dis
));
548 dis
= (struct T_discon_ind
*)&it
->type
;
549 dis
->PRIM_type
= T_DISCON_IND
;
550 dis
->DISCON_reason
= -error
; /* FIXME: convert this as in iABI_errors() */
554 timod_ok(fd
, T_CONN_REQ
);
556 timod_queue_end(fd
, it
);
557 SOLD("CONNECT done");
562 struct T_optmgmt_req req
;
564 if (copy_from_user(&req
, ctl_buf
, sizeof(req
)))
567 return timod_optmgmt(fd
, req
.MGMT_flags
,
568 req
.OPT_offset
> 0 ? ctl_buf
+ req
.OPT_offset
: NULL
,
573 struct T_unitdata_req req
;
576 SOLD("T_UNITDATA_REQ");
577 if (sock
->state
!= TS_IDLE
&& sock
->state
!= TS_DATA_XFER
) {
578 timod_error(fd
, T_CONN_REQ
, TOUTSTATE
, 0);
582 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
583 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
589 char * ptr
= ctl_buf
+req
.DEST_offset
;
590 int len
= req
.DEST_length
;
591 printk("socket address (%d bytes): ",len
);
597 printk("%02x",(unsigned char)c
);
603 err
= sys_sendto(fd
, data_buf
, data_len
, 0, req
.DEST_length
> 0 ? (struct sockaddr
*)(ctl_buf
+req
.DEST_offset
) : NULL
, req
.DEST_length
);
607 printk("timod: sendto failed to send all the data\n");
610 timod_error(fd
, T_CONN_REQ
, TSYSERR
, -err
);
614 printk("timod_putmsg: unsuported command %u.\n", ret
);
620 int timod_getmsg(unsigned int fd
, char *ctl_buf
, int ctl_maxlen
, s32
*ctl_len
,
621 char *data_buf
, int data_maxlen
, s32
*data_len
, int *flags_p
)
627 struct sol_socket_struct
*sock
;
628 struct T_unitdata_ind udi
;
629 mm_segment_t old_fs
= get_fs();
633 int (*sys_socketcall
)(int, unsigned long *) =
634 (int (*)(int, unsigned long *))SYS(socketcall
);
635 int (*sys_recvfrom
)(int, void *, size_t, unsigned, struct sockaddr
*, int *);
638 SOLDD(("%u %p %d %p %p %d %p %d\n", fd
, ctl_buf
, ctl_maxlen
, ctl_len
, data_buf
, data_maxlen
, data_len
, *flags_p
));
639 filp
= current
->files
->fd
[fd
];
640 ino
= filp
->f_dentry
->d_inode
;
641 sock
= (struct sol_socket_struct
*)filp
->private_data
;
642 SOLDD(("%p %p\n", sock
->pfirst
, sock
->pfirst
? sock
->pfirst
->next
: NULL
));
643 if ( ctl_maxlen
> 0 && !sock
->pfirst
&& ino
->u
.socket_i
.type
== SOCK_STREAM
644 && sock
->state
== TS_IDLE
) {
645 SOLD("calling LISTEN");
649 sys_socketcall(SYS_LISTEN
, args
);
653 if (!(filp
->f_flags
& O_NONBLOCK
)) {
654 poll_table wait_table
, *wait
;
656 poll_initwait(&wait_table
);
660 set_current_state(TASK_INTERRUPTIBLE
);
661 /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
662 /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
663 /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
664 /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */
665 /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */
666 /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */
667 if (ctl_maxlen
>= 0 && sock
->pfirst
&& (*flags_p
!= MSG_HIPRI
|| sock
->pfirst
->pri
== MSG_HIPRI
))
669 SOLD("cond 1 passed");
672 *flags_p
!= MSG_HIPRI
&&
674 ((filp
->f_op
->poll(filp
, wait
) & POLLIN
) ||
675 (filp
->f_op
->poll(filp
, NULL
) & POLLIN
) ||
676 signal_pending(current
))
680 if( *flags_p
== MSG_HIPRI
) {
681 SOLD("avoiding lockup");
684 if(wait_table
.error
) {
685 SOLD("wait-table error");
686 poll_freewait(&wait_table
);
687 return wait_table
.error
;
693 current
->state
= TASK_RUNNING
;
694 poll_freewait(&wait_table
);
695 if (signal_pending(current
)) {
696 SOLD("signal pending");
700 if (ctl_maxlen
>= 0 && sock
->pfirst
) {
701 struct T_primsg
*it
= sock
->pfirst
;
703 #define min(a,b) ((a)<(b)?(a):(b))
705 int l
= min(ctl_maxlen
, it
->length
);
706 SCHECK_MAGIC((char*)((u64
)(((char *)&it
->type
)+sock
->offset
+it
->length
+7)&~7),MKCTL_MAGIC
);
707 SOLD("purting ctl data");
708 if(copy_to_user(ctl_buf
,
709 (char*)&it
->type
+ sock
->offset
, l
))
712 if(put_user(l
, ctl_len
))
722 SOLD("removing message");
723 sock
->pfirst
= it
->next
;
726 SOLDD(("getmsg kfree %016lx->%016lx\n", it
, sock
->pfirst
));
734 if (ctl_maxlen
>= 0) {
735 SOLD("ACCEPT perhaps?");
736 if (ino
->u
.socket_i
.type
== SOCK_STREAM
&& sock
->state
== TS_IDLE
) {
737 struct T_conn_ind ind
;
738 char *buf
= getpage();
741 SOLD("trying ACCEPT");
742 if (put_user(ctl_maxlen
- sizeof(ind
), ctl_len
))
746 args
[2] = (long)&len
;
747 oldflags
= filp
->f_flags
;
748 filp
->f_flags
|= O_NONBLOCK
;
749 SOLD("calling ACCEPT");
751 error
= sys_socketcall(SYS_ACCEPT
, args
);
753 filp
->f_flags
= oldflags
;
762 if (sizeof(ind
) > ctl_maxlen
) {
763 SOLD("generating CONN_IND");
764 ind
.PRIM_type
= T_CONN_IND
;
765 ind
.SRC_length
= len
;
766 ind
.SRC_offset
= sizeof(ind
);
767 ind
.OPT_length
= ind
.OPT_offset
= 0;
768 ind
.SEQ_number
= error
;
769 if(copy_to_user(ctl_buf
, &ind
, sizeof(ind
))||
770 put_user(sizeof(ind
)+ind
.SRC_length
,ctl_len
))
772 SOLD("CONN_IND created");
774 if (data_maxlen
>= 0)
775 put_user(0, data_len
);
776 SOLD("CONN_IND done");
779 if (len
>ctl_maxlen
) {
780 SOLD("data don't fit");
782 return -EFAULT
; /* XXX - is this ok ? */
784 if(copy_to_user(ctl_buf
,buf
,len
) || put_user(len
,ctl_len
)){
785 SOLD("can't copy data");
793 SOLD("checking data req");
794 if (data_maxlen
<= 0) {
795 if (data_maxlen
== 0)
796 put_user(0, data_len
);
798 put_user(0, ctl_len
);
802 if (ctl_maxlen
> sizeof(udi
) && sock
->state
== TS_IDLE
) {
804 tmpbuf
= ctl_buf
+ sizeof(udi
);
805 tmplen
= ctl_maxlen
- sizeof(udi
);
807 SOLD("udi does not fit");
811 if (put_user(tmplen
, ctl_len
))
814 oldflags
= filp
->f_flags
;
815 filp
->f_flags
|= O_NONBLOCK
;
816 SOLD("calling recvfrom");
817 sys_recvfrom
= (int (*)(int, void *, size_t, unsigned, struct sockaddr
*, int *))SYS(recvfrom
);
818 error
= sys_recvfrom(fd
, data_buf
, min(0,data_maxlen
), 0, (struct sockaddr
*)tmpbuf
, ctl_len
);
819 filp
->f_flags
= oldflags
;
822 SOLD("error >= 0" ) ;
823 if (error
&& ctl_maxlen
> sizeof(udi
) && sock
->state
== TS_IDLE
) {
824 SOLD("generating udi");
825 udi
.PRIM_type
= T_UNITDATA_IND
;
826 get_user(udi
.SRC_length
, ctl_len
);
827 udi
.SRC_offset
= sizeof(udi
);
828 udi
.OPT_length
= udi
.OPT_offset
= 0;
829 copy_to_user(ctl_buf
, &udi
, sizeof(udi
));
830 put_user(sizeof(udi
)+udi
.SRC_length
, ctl_len
);
833 put_user(0, ctl_len
);
834 put_user(error
, data_len
);
839 asmlinkage
int solaris_getmsg(unsigned int fd
, u32 arg1
, u32 arg2
, u32 arg3
)
843 struct strbuf
*ctlptr
, *datptr
;
844 struct strbuf ctl
, dat
;
851 if(fd
>= NR_OPEN
) goto out
;
853 filp
= current
->files
->fd
[fd
];
856 ino
= filp
->f_dentry
->d_inode
;
862 ctlptr
= (struct strbuf
*)A(arg1
);
863 datptr
= (struct strbuf
*)A(arg2
);
864 flgptr
= (int *)A(arg3
);
869 if (copy_from_user(&ctl
,ctlptr
,sizeof(struct strbuf
)) ||
870 put_user(-1,&ctlptr
->len
))
876 if (copy_from_user(&dat
,datptr
,sizeof(struct strbuf
)) ||
877 put_user(-1,&datptr
->len
))
882 if (get_user(flags
,flgptr
))
896 error
= timod_getmsg(fd
,(char*)A(ctl
.buf
),ctl
.maxlen
,&ctlptr
->len
,
897 (char*)A(dat
.buf
),dat
.maxlen
,&datptr
->len
,&flags
);
899 if (!error
&& put_user(flags
,flgptr
))
907 asmlinkage
int solaris_putmsg(unsigned int fd
, u32 arg1
, u32 arg2
, u32 arg3
)
911 struct strbuf
*ctlptr
, *datptr
;
912 struct strbuf ctl
, dat
;
913 int flags
= (int) arg3
;
918 if(fd
>= NR_OPEN
) goto out
;
920 filp
= current
->files
->fd
[fd
];
923 ino
= filp
->f_dentry
->d_inode
;
927 (MAJOR(ino
->i_rdev
) != 30 || MINOR(ino
->i_rdev
) != 1))
930 ctlptr
= (struct strbuf
*)A(arg1
);
931 datptr
= (struct strbuf
*)A(arg2
);
936 if (copy_from_user(&ctl
,ctlptr
,sizeof(ctl
)))
938 if (ctl
.len
< 0 && flags
) {
948 if (copy_from_user(&dat
,datptr
,sizeof(dat
)))
955 error
= timod_putmsg(fd
,(char*)A(ctl
.buf
),ctl
.len
,
956 (char*)A(dat
.buf
),dat
.len
,flags
);