1 /* $Id: timod.c,v 1.19 2002/02/08 03:57:14 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 asmlinkage
int solaris_ioctl(unsigned int fd
, unsigned int cmd
, u32 arg
);
32 static DEFINE_SPINLOCK(timod_pagelock
);
33 static char * page
= NULL
;
35 #ifndef DEBUG_SOLARIS_KMALLOC
37 #define mykmalloc kmalloc
42 void * mykmalloc(size_t s
, gfp_t gfp
)
49 SOLD("too big size, calling real kmalloc");
50 return kmalloc(s
, gfp
);
53 /* we are wasting memory, but we don't care */
54 page
= (char *)__get_free_page(gfp
);
71 #define BUF_SIZE PAGE_SIZE
72 #define PUT_MAGIC(a,m)
73 #define SCHECK_MAGIC(a,m)
75 #define MKCTL_TRAILER 0
79 #define BUF_SIZE (PAGE_SIZE-2*sizeof(u64))
80 #define BUFPAGE_MAGIC 0xBADC0DEDDEADBABEL
81 #define MKCTL_MAGIC 0xDEADBABEBADC0DEDL
82 #define PUT_MAGIC(a,m) do{(*(u64*)(a))=(m);}while(0)
83 #define SCHECK_MAGIC(a,m) do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
84 __FILE__,__LINE__,__FUNCTION__,(m),(a));}while(0)
85 #define BUF_OFFSET sizeof(u64)
86 #define MKCTL_TRAILER sizeof(u64)
90 static char *getpage( void )
94 spin_lock(&timod_pagelock
);
98 spin_unlock(&timod_pagelock
);
100 return r
+ BUF_OFFSET
;
102 spin_unlock(&timod_pagelock
);
104 r
= (char *)__get_free_page(GFP_KERNEL
);
105 PUT_MAGIC(r
,BUFPAGE_MAGIC
);
106 PUT_MAGIC(r
+PAGE_SIZE
-sizeof(u64
),BUFPAGE_MAGIC
);
107 return r
+ BUF_OFFSET
;
110 static void putpage(char *p
)
112 SOLD("putting page");
114 SCHECK_MAGIC(p
,BUFPAGE_MAGIC
);
115 SCHECK_MAGIC(p
+PAGE_SIZE
-sizeof(u64
),BUFPAGE_MAGIC
);
116 spin_lock(&timod_pagelock
);
118 spin_unlock(&timod_pagelock
);
119 free_page((unsigned long)p
);
123 spin_unlock(&timod_pagelock
);
128 static struct T_primsg
*timod_mkctl(int size
)
132 SOLD("creating primsg");
133 it
= (struct T_primsg
*)mykmalloc(size
+sizeof(*it
)-sizeof(s32
)+2*MKCTL_TRAILER
, GFP_KERNEL
);
138 PUT_MAGIC((char*)((u64
)(((char *)&it
->type
)+size
+7)&~7),MKCTL_MAGIC
);
143 static void timod_wake_socket(unsigned int fd
)
148 SOLD("wakeing socket");
149 fdt
= files_fdtable(current
->files
);
150 sock
= SOCKET_I(fdt
->fd
[fd
]->f_path
.dentry
->d_inode
);
151 wake_up_interruptible(&sock
->wait
);
152 read_lock(&sock
->sk
->sk_callback_lock
);
153 if (sock
->fasync_list
&& !test_bit(SOCK_ASYNC_WAITDATA
, &sock
->flags
))
154 __kill_fasync(sock
->fasync_list
, SIGIO
, POLL_IN
);
155 read_unlock(&sock
->sk
->sk_callback_lock
);
159 static void timod_queue(unsigned int fd
, struct T_primsg
*it
)
161 struct sol_socket_struct
*sock
;
164 SOLD("queuing primsg");
165 fdt
= files_fdtable(current
->files
);
166 sock
= (struct sol_socket_struct
*)fdt
->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
;
180 SOLD("queuing primsg at end");
181 fdt
= files_fdtable(current
->files
);
182 sock
= (struct sol_socket_struct
*)fdt
->fd
[fd
]->private_data
;
185 sock
->plast
->next
= it
;
192 static void timod_error(unsigned int fd
, int prim
, int terr
, int uerr
)
196 SOLD("making error");
197 it
= timod_mkctl(sizeof(struct T_error_ack
));
199 struct T_error_ack
*err
= (struct T_error_ack
*)&it
->type
;
202 err
->PRIM_type
= T_ERROR_ACK
;
203 err
->ERROR_prim
= prim
;
204 err
->TLI_error
= terr
;
205 err
->UNIX_error
= uerr
; /* FIXME: convert this */
211 static void timod_ok(unsigned int fd
, int prim
)
216 SOLD("creating ok ack");
217 it
= timod_mkctl(sizeof(*ok
));
220 ok
= (struct T_ok_ack
*)&it
->type
;
221 ok
->PRIM_type
= T_OK_ACK
;
222 ok
->CORRECT_prim
= prim
;
228 static int timod_optmgmt(unsigned int fd
, int flag
, char __user
*opt_buf
, int opt_len
, int do_ret
)
231 int ret_space
, ret_len
;
233 char *ret_pos
,*ret_buf
;
234 int (*sys_socketcall
)(int, unsigned long *) =
235 (int (*)(int, unsigned long *))SYS(socketcall
);
236 mm_segment_t old_fs
= get_fs();
239 SOLDD(("fd %u flg %u buf %p len %u doret %u",fd
,flag
,opt_buf
,opt_len
,do_ret
));
240 if (!do_ret
&& (!opt_buf
|| opt_len
<= 0))
242 SOLD("getting page");
243 ret_pos
= ret_buf
= getpage();
244 ret_space
= BUF_SIZE
;
249 while(opt_len
>= sizeof(struct opthdr
)) {
253 opt
= (struct opthdr
*)ret_pos
;
254 if (ret_space
< sizeof(struct opthdr
)) {
258 SOLD("getting opthdr");
259 if (copy_from_user(opt
, opt_buf
, sizeof(struct opthdr
)) ||
260 opt
->len
> opt_len
) {
265 if (flag
== T_NEGOTIATE
) {
268 SOLD("handling T_NEGOTIATE");
269 buf
= ret_pos
+ sizeof(struct opthdr
);
270 if (ret_space
< opt
->len
+ sizeof(struct opthdr
) ||
271 copy_from_user(buf
, opt_buf
+sizeof(struct opthdr
), opt
->len
)) {
277 args
[1] = opt
->level
;
281 SOLD("calling SETSOCKOPT");
283 error
= sys_socketcall(SYS_SETSOCKOPT
, args
);
289 SOLD("SETSOCKOPT ok");
291 orig_opt_len
= opt
->len
;
292 opt
->len
= ret_space
- sizeof(struct opthdr
);
298 args
[1] = opt
->level
;
300 args
[3] = (long)(ret_pos
+sizeof(struct opthdr
));
301 args
[4] = (long)&opt
->len
;
302 SOLD("calling GETSOCKOPT");
304 error
= sys_socketcall(SYS_GETSOCKOPT
, args
);
310 SOLD("GETSOCKOPT ok");
311 ret_space
-= sizeof(struct opthdr
) + opt
->len
;
312 ret_len
+= sizeof(struct opthdr
) + opt
->len
;
313 ret_pos
+= sizeof(struct opthdr
) + opt
->len
;
314 opt_len
-= sizeof(struct opthdr
) + orig_opt_len
;
315 opt_buf
+= sizeof(struct opthdr
) + orig_opt_len
;
320 SOLD("generating ret msg");
322 timod_error(fd
, T_OPTMGMT_REQ
, failed
, -error
);
325 it
= timod_mkctl(sizeof(struct T_optmgmt_ack
) + ret_len
);
327 struct T_optmgmt_ack
*ack
=
328 (struct T_optmgmt_ack
*)&it
->type
;
330 ack
->PRIM_type
= T_OPTMGMT_ACK
;
331 ack
->OPT_length
= ret_len
;
332 ack
->OPT_offset
= sizeof(struct T_optmgmt_ack
);
333 ack
->MGMT_flags
= (failed
? T_FAILURE
: flag
);
334 memcpy(((char*)ack
)+sizeof(struct T_optmgmt_ack
),
340 SOLDD(("put_page %p\n", ret_buf
));
346 int timod_putmsg(unsigned int fd
, char __user
*ctl_buf
, int ctl_len
,
347 char __user
*data_buf
, int data_len
, int flags
)
349 int ret
, error
, terror
;
354 struct sol_socket_struct
*sock
;
355 mm_segment_t old_fs
= get_fs();
357 int (*sys_socketcall
)(int, unsigned long __user
*) =
358 (int (*)(int, unsigned long __user
*))SYS(socketcall
);
359 int (*sys_sendto
)(int, void __user
*, size_t, unsigned, struct sockaddr __user
*, int) =
360 (int (*)(int, void __user
*, size_t, unsigned, struct sockaddr __user
*, int))SYS(sendto
);
362 fdt
= files_fdtable(current
->files
);
364 ino
= filp
->f_path
.dentry
->d_inode
;
365 sock
= (struct sol_socket_struct
*)filp
->private_data
;
367 if (get_user(ret
, (int __user
*)A(ctl_buf
)))
372 struct T_bind_req req
;
374 SOLDD(("bind %016lx(%016lx)\n", sock
, filp
));
376 if (sock
->state
!= TS_UNBND
) {
377 timod_error(fd
, T_BIND_REQ
, TOUTSTATE
, 0);
381 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
382 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
386 if (req
.ADDR_offset
&& req
.ADDR_length
) {
387 if (req
.ADDR_length
> BUF_SIZE
) {
388 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
393 if (copy_from_user(buf
, ctl_buf
+ req
.ADDR_offset
, req
.ADDR_length
)) {
394 timod_error(fd
, T_BIND_REQ
, TSYSERR
, EFAULT
);
398 SOLD("got ctl data");
401 args
[2] = req
.ADDR_length
;
402 SOLD("calling BIND");
404 error
= sys_socketcall(SYS_BIND
, args
);
407 SOLD("BIND returned");
412 if (req
.CONIND_number
) {
414 args
[1] = req
.CONIND_number
;
415 SOLD("calling LISTEN");
417 error
= sys_socketcall(SYS_LISTEN
, args
);
421 it
= timod_mkctl(sizeof(struct T_bind_ack
)+sizeof(struct sockaddr
));
423 struct T_bind_ack
*ack
;
425 ack
= (struct T_bind_ack
*)&it
->type
;
426 ack
->PRIM_type
= T_BIND_ACK
;
427 ack
->ADDR_offset
= sizeof(*ack
);
428 ack
->ADDR_length
= sizeof(struct sockaddr
);
429 ack
->CONIND_number
= req
.CONIND_number
;
431 args
[1] = (long)(ack
+sizeof(*ack
));
432 args
[2] = (long)&ack
->ADDR_length
;
434 sys_socketcall(SYS_GETSOCKNAME
,args
);
436 sock
->state
= TS_IDLE
;
437 timod_ok(fd
, T_BIND_REQ
);
438 timod_queue_end(fd
, it
);
462 timod_error(fd
, T_BIND_REQ
, terror
, -error
);
468 struct T_conn_req req
;
469 unsigned short oldflags
;
472 if (sock
->state
!= TS_UNBND
&& sock
->state
!= TS_IDLE
) {
473 timod_error(fd
, T_CONN_REQ
, TOUTSTATE
, 0);
477 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
478 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
482 if (ctl_len
> BUF_SIZE
) {
483 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
488 if (copy_from_user(buf
, ctl_buf
, ctl_len
)) {
489 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
497 printk("returned data (%d bytes): ",len
);
501 printk("%02x",(unsigned char)*ptr
++);
506 SOLD("got ctl data");
508 args
[1] = (long)buf
+req
.DEST_offset
;
509 args
[2] = req
.DEST_length
;
510 oldflags
= filp
->f_flags
;
511 filp
->f_flags
&= ~O_NONBLOCK
;
512 SOLD("calling CONNECT");
514 error
= sys_socketcall(SYS_CONNECT
, args
);
516 filp
->f_flags
= oldflags
;
517 SOLD("CONNECT done");
519 struct T_conn_con
*con
;
521 it
= timod_mkctl(ctl_len
);
526 con
= (struct T_conn_con
*)&it
->type
;
531 printk("returned data (%d bytes): ",len
);
535 printk("%02x",(unsigned char)*ptr
++);
540 memcpy(con
, buf
, ctl_len
);
541 SOLD("copied ctl_buf");
542 con
->PRIM_type
= T_CONN_CON
;
543 sock
->state
= TS_DATA_XFER
;
545 struct T_discon_ind
*dis
;
547 it
= timod_mkctl(sizeof(*dis
));
553 dis
= (struct T_discon_ind
*)&it
->type
;
554 dis
->PRIM_type
= T_DISCON_IND
;
555 dis
->DISCON_reason
= -error
; /* FIXME: convert this as in iABI_errors() */
559 timod_ok(fd
, T_CONN_REQ
);
561 timod_queue_end(fd
, it
);
562 SOLD("CONNECT done");
567 struct T_optmgmt_req req
;
569 if (copy_from_user(&req
, ctl_buf
, sizeof(req
)))
572 return timod_optmgmt(fd
, req
.MGMT_flags
,
573 req
.OPT_offset
> 0 ? ctl_buf
+ req
.OPT_offset
: NULL
,
578 struct T_unitdata_req req
;
581 SOLD("T_UNITDATA_REQ");
582 if (sock
->state
!= TS_IDLE
&& sock
->state
!= TS_DATA_XFER
) {
583 timod_error(fd
, T_CONN_REQ
, TOUTSTATE
, 0);
587 if (copy_from_user(&req
, ctl_buf
, sizeof(req
))) {
588 timod_error(fd
, T_CONN_REQ
, TSYSERR
, EFAULT
);
594 char * ptr
= ctl_buf
+req
.DEST_offset
;
595 int len
= req
.DEST_length
;
596 printk("socket address (%d bytes): ",len
);
602 printk("%02x",(unsigned char)c
);
608 err
= sys_sendto(fd
, data_buf
, data_len
, 0, req
.DEST_length
> 0 ? (struct sockaddr __user
*)(ctl_buf
+req
.DEST_offset
) : NULL
, req
.DEST_length
);
612 printk("timod: sendto failed to send all the data\n");
615 timod_error(fd
, T_CONN_REQ
, TSYSERR
, -err
);
619 printk(KERN_INFO
"timod_putmsg: unsupported command %u.\n", ret
);
625 int timod_getmsg(unsigned int fd
, char __user
*ctl_buf
, int ctl_maxlen
, s32 __user
*ctl_len
,
626 char __user
*data_buf
, int data_maxlen
, s32 __user
*data_len
, int *flags_p
)
633 struct sol_socket_struct
*sock
;
634 struct T_unitdata_ind udi
;
635 mm_segment_t old_fs
= get_fs();
639 int (*sys_socketcall
)(int, unsigned long __user
*) =
640 (int (*)(int, unsigned long __user
*))SYS(socketcall
);
641 int (*sys_recvfrom
)(int, void __user
*, size_t, unsigned, struct sockaddr __user
*, int __user
*);
644 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
));
645 fdt
= files_fdtable(current
->files
);
647 ino
= filp
->f_path
.dentry
->d_inode
;
648 sock
= (struct sol_socket_struct
*)filp
->private_data
;
649 SOLDD(("%p %p\n", sock
->pfirst
, sock
->pfirst
? sock
->pfirst
->next
: NULL
));
650 if ( ctl_maxlen
> 0 && !sock
->pfirst
&& SOCKET_I(ino
)->type
== SOCK_STREAM
651 && sock
->state
== TS_IDLE
) {
652 SOLD("calling LISTEN");
656 sys_socketcall(SYS_LISTEN
, args
);
660 if (!(filp
->f_flags
& O_NONBLOCK
)) {
661 struct poll_wqueues wait_table
;
664 poll_initwait(&wait_table
);
665 wait
= &wait_table
.pt
;
668 set_current_state(TASK_INTERRUPTIBLE
);
669 /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
670 /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
671 /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */
672 /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */
673 /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */
674 /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */
675 if (ctl_maxlen
>= 0 && sock
->pfirst
&& (*flags_p
!= MSG_HIPRI
|| sock
->pfirst
->pri
== MSG_HIPRI
))
677 SOLD("cond 1 passed");
680 *flags_p
!= MSG_HIPRI
&&
682 ((filp
->f_op
->poll(filp
, wait
) & POLLIN
) ||
683 (filp
->f_op
->poll(filp
, NULL
) & POLLIN
) ||
684 signal_pending(current
))
688 if( *flags_p
== MSG_HIPRI
) {
689 SOLD("avoiding lockup");
692 if(wait_table
.error
) {
693 SOLD("wait-table error");
694 poll_freewait(&wait_table
);
695 return wait_table
.error
;
701 current
->state
= TASK_RUNNING
;
702 poll_freewait(&wait_table
);
703 if (signal_pending(current
)) {
704 SOLD("signal pending");
708 if (ctl_maxlen
>= 0 && sock
->pfirst
) {
709 struct T_primsg
*it
= sock
->pfirst
;
710 int l
= min_t(int, ctl_maxlen
, it
->length
);
711 SCHECK_MAGIC((char*)((u64
)(((char *)&it
->type
)+sock
->offset
+it
->length
+7)&~7),MKCTL_MAGIC
);
712 SOLD("purting ctl data");
713 if(copy_to_user(ctl_buf
,
714 (char*)&it
->type
+ sock
->offset
, l
))
717 if(put_user(l
, ctl_len
))
727 SOLD("removing message");
728 sock
->pfirst
= it
->next
;
731 SOLDD(("getmsg kfree %016lx->%016lx\n", it
, sock
->pfirst
));
739 if (ctl_maxlen
>= 0) {
740 SOLD("ACCEPT perhaps?");
741 if (SOCKET_I(ino
)->type
== SOCK_STREAM
&& sock
->state
== TS_IDLE
) {
742 struct T_conn_ind ind
;
743 char *buf
= getpage();
746 SOLD("trying ACCEPT");
747 if (put_user(ctl_maxlen
- sizeof(ind
), ctl_len
))
751 args
[2] = (long)&len
;
752 oldflags
= filp
->f_flags
;
753 filp
->f_flags
|= O_NONBLOCK
;
754 SOLD("calling ACCEPT");
756 error
= sys_socketcall(SYS_ACCEPT
, args
);
758 filp
->f_flags
= oldflags
;
767 if (sizeof(ind
) > ctl_maxlen
) {
768 SOLD("generating CONN_IND");
769 ind
.PRIM_type
= T_CONN_IND
;
770 ind
.SRC_length
= len
;
771 ind
.SRC_offset
= sizeof(ind
);
772 ind
.OPT_length
= ind
.OPT_offset
= 0;
773 ind
.SEQ_number
= error
;
774 if(copy_to_user(ctl_buf
, &ind
, sizeof(ind
))||
775 put_user(sizeof(ind
)+ind
.SRC_length
,ctl_len
))
777 SOLD("CONN_IND created");
779 if (data_maxlen
>= 0)
780 put_user(0, data_len
);
781 SOLD("CONN_IND done");
784 if (len
>ctl_maxlen
) {
785 SOLD("data don't fit");
787 return -EFAULT
; /* XXX - is this ok ? */
789 if(copy_to_user(ctl_buf
,buf
,len
) || put_user(len
,ctl_len
)){
790 SOLD("can't copy data");
798 SOLD("checking data req");
799 if (data_maxlen
<= 0) {
800 if (data_maxlen
== 0)
801 put_user(0, data_len
);
803 put_user(0, ctl_len
);
807 if (ctl_maxlen
> sizeof(udi
) && sock
->state
== TS_IDLE
) {
809 tmpbuf
= ctl_buf
+ sizeof(udi
);
810 tmplen
= ctl_maxlen
- sizeof(udi
);
812 SOLD("udi does not fit");
816 if (put_user(tmplen
, ctl_len
))
819 oldflags
= filp
->f_flags
;
820 filp
->f_flags
|= O_NONBLOCK
;
821 SOLD("calling recvfrom");
822 sys_recvfrom
= (int (*)(int, void __user
*, size_t, unsigned, struct sockaddr __user
*, int __user
*))SYS(recvfrom
);
823 error
= sys_recvfrom(fd
, data_buf
, data_maxlen
, 0, (struct sockaddr __user
*)tmpbuf
, ctl_len
);
824 filp
->f_flags
= oldflags
;
827 SOLD("error >= 0" ) ;
828 if (error
&& ctl_maxlen
> sizeof(udi
) && sock
->state
== TS_IDLE
) {
829 SOLD("generating udi");
830 udi
.PRIM_type
= T_UNITDATA_IND
;
831 if (get_user(udi
.SRC_length
, ctl_len
))
833 udi
.SRC_offset
= sizeof(udi
);
834 udi
.OPT_length
= udi
.OPT_offset
= 0;
835 if (copy_to_user(ctl_buf
, &udi
, sizeof(udi
)) ||
836 put_user(sizeof(udi
)+udi
.SRC_length
, ctl_len
))
840 if (put_user(0, ctl_len
))
843 put_user(error
, data_len
);
848 asmlinkage
int solaris_getmsg(unsigned int fd
, u32 arg1
, u32 arg2
, u32 arg3
)
852 struct strbuf __user
*ctlptr
;
853 struct strbuf __user
*datptr
;
854 struct strbuf ctl
, dat
;
862 if(fd
>= NR_OPEN
) goto out
;
864 fdt
= files_fdtable(current
->files
);
868 ino
= filp
->f_path
.dentry
->d_inode
;
869 if (!ino
|| !S_ISSOCK(ino
->i_mode
))
872 ctlptr
= (struct strbuf __user
*)A(arg1
);
873 datptr
= (struct strbuf __user
*)A(arg2
);
874 flgptr
= (int __user
*)A(arg3
);
879 if (copy_from_user(&ctl
,ctlptr
,sizeof(struct strbuf
)) ||
880 put_user(-1,&ctlptr
->len
))
886 if (copy_from_user(&dat
,datptr
,sizeof(struct strbuf
)) ||
887 put_user(-1,&datptr
->len
))
892 if (get_user(flags
,flgptr
))
906 error
= timod_getmsg(fd
,A(ctl
.buf
),ctl
.maxlen
,&ctlptr
->len
,
907 A(dat
.buf
),dat
.maxlen
,&datptr
->len
,&flags
);
909 if (!error
&& put_user(flags
,flgptr
))
917 asmlinkage
int solaris_putmsg(unsigned int fd
, u32 arg1
, u32 arg2
, u32 arg3
)
921 struct strbuf __user
*ctlptr
;
922 struct strbuf __user
*datptr
;
923 struct strbuf ctl
, dat
;
924 int flags
= (int) arg3
;
930 if(fd
>= NR_OPEN
) goto out
;
932 fdt
= files_fdtable(current
->files
);
936 ino
= filp
->f_path
.dentry
->d_inode
;
939 if (!S_ISSOCK(ino
->i_mode
) &&
940 (imajor(ino
) != 30 || iminor(ino
) != 1))
949 if (copy_from_user(&ctl
,ctlptr
,sizeof(ctl
)))
951 if (ctl
.len
< 0 && flags
) {
961 if (copy_from_user(&dat
,datptr
,sizeof(dat
)))
968 error
= timod_putmsg(fd
,A(ctl
.buf
),ctl
.len
,
969 A(dat
.buf
),dat
.len
,flags
);