1/* $Id: timod.c,v 1.1.1.1 2008/10/15 03:26:19 james26_jang Exp $
2 * timod.c: timod emulation.
3 *
4 * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
5 *
6 * Streams & timod emulation based on code
7 * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
8 *
9 */
10
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>
17#include <linux/fs.h>
18#include <linux/file.h>
19#include <linux/netdevice.h>
20#include <linux/poll.h>
21
22#include <net/sock.h>
23
24#include <asm/uaccess.h>
25#include <asm/termios.h>
26
27#include "conv.h"
28#include "socksys.h"
29
30extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
31	unsigned long arg);
32extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd,
33	u32 arg);
34asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
35
36static spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED;
37static char * page = NULL ;
38
39#ifndef DEBUG_SOLARIS_KMALLOC
40
41#define mykmalloc kmalloc
42#define mykfree kfree
43
44#else
45
46void * mykmalloc(size_t s, int gfp)
47{
48	static char * page;
49	static size_t free;
50	void * r;
51	s = ((s + 63) & ~63);
52	if( s > PAGE_SIZE ) {
53		SOLD("too big size, calling real kmalloc");
54		return kmalloc(s, gfp);
55	}
56	if( s > free ) {
57		/* we are wasting memory, but we don't care */
58		page = (char *)__get_free_page(gfp);
59		free = PAGE_SIZE;
60	}
61	r = page;
62	page += s;
63	free -= s;
64	return r;
65}
66
67void mykfree(void *p)
68{
69}
70
71#endif
72
73#ifndef DEBUG_SOLARIS
74
75#define BUF_SIZE	PAGE_SIZE
76#define PUT_MAGIC(a,m)
77#define SCHECK_MAGIC(a,m)
78#define BUF_OFFSET	0
79#define MKCTL_TRAILER	0
80
81#else
82
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)
91
92#endif
93
94static char *getpage( void )
95{
96	char *r;
97	SOLD("getting page");
98	spin_lock(&timod_pagelock);
99	if (page) {
100		r = page;
101		page = NULL;
102		spin_unlock(&timod_pagelock);
103		SOLD("got cached");
104		return r + BUF_OFFSET;
105	}
106	spin_unlock(&timod_pagelock);
107	SOLD("getting new");
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;
112}
113
114static void putpage(char *p)
115{
116	SOLD("putting page");
117	p = p - BUF_OFFSET;
118	SCHECK_MAGIC(p,BUFPAGE_MAGIC);
119	SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
120	spin_lock(&timod_pagelock);
121	if (page) {
122		spin_unlock(&timod_pagelock);
123		free_page((unsigned long)p);
124		SOLD("freed it");
125	} else {
126		page = p;
127		spin_unlock(&timod_pagelock);
128		SOLD("cached it");
129	}
130}
131
132static struct T_primsg *timod_mkctl(int size)
133{
134	struct T_primsg *it;
135
136	SOLD("creating primsg");
137	it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL);
138	if (it) {
139		SOLD("got it");
140		it->pri = MSG_HIPRI;
141		it->length = size;
142		PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC);
143	}
144	return it;
145}
146
147static void timod_wake_socket(unsigned int fd)
148{
149	struct socket *sock;
150
151	SOLD("wakeing socket");
152	sock = &current->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);
158	SOLD("done");
159}
160
161static void timod_queue(unsigned int fd, struct T_primsg *it)
162{
163	struct sol_socket_struct *sock;
164
165	SOLD("queuing primsg");
166	sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
167	it->next = sock->pfirst;
168	sock->pfirst = it;
169	if (!sock->plast)
170		sock->plast = it;
171	timod_wake_socket(fd);
172	SOLD("done");
173}
174
175static void timod_queue_end(unsigned int fd, struct T_primsg *it)
176{
177	struct sol_socket_struct *sock;
178
179	SOLD("queuing primsg at end");
180	sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
181	it->next = NULL;
182	if (sock->plast)
183		sock->plast->next = it;
184	else
185		sock->pfirst = it;
186	sock->plast = it;
187	SOLD("done");
188}
189
190static void timod_error(unsigned int fd, int prim, int terr, int uerr)
191{
192	struct T_primsg *it;
193
194	SOLD("making error");
195	it = timod_mkctl(sizeof(struct T_error_ack));
196	if (it) {
197		struct T_error_ack *err = (struct T_error_ack *)&it->type;
198
199		SOLD("got it");
200		err->PRIM_type = T_ERROR_ACK;
201		err->ERROR_prim = prim;
202		err->TLI_error = terr;
203		err->UNIX_error = uerr;
204		timod_queue(fd, it);
205	}
206	SOLD("done");
207}
208
209static void timod_ok(unsigned int fd, int prim)
210{
211	struct T_primsg *it;
212	struct T_ok_ack *ok;
213
214	SOLD("creating ok ack");
215	it = timod_mkctl(sizeof(*ok));
216	if (it) {
217		SOLD("got it");
218		ok = (struct T_ok_ack *)&it->type;
219		ok->PRIM_type = T_OK_ACK;
220		ok->CORRECT_prim = prim;
221		timod_queue(fd, it);
222	}
223	SOLD("done");
224}
225
226static int timod_optmgmt(unsigned int fd, int flag, char *opt_buf, int opt_len, int do_ret)
227{
228	int error, failed;
229	int ret_space, ret_len;
230	long args[5];
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();
235
236	SOLD("entry");
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))
239		return 0;
240	SOLD("getting page");
241	ret_pos = ret_buf = getpage();
242	ret_space = BUF_SIZE;
243	ret_len = 0;
244
245	error = failed = 0;
246	SOLD("looping");
247	while(opt_len >= sizeof(struct opthdr)) {
248		struct opthdr *opt;
249		int orig_opt_len;
250		SOLD("loop start");
251		opt = (struct opthdr *)ret_pos;
252		if (ret_space < sizeof(struct opthdr)) {
253			failed = TSYSERR;
254			break;
255		}
256		SOLD("getting opthdr");
257		if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) ||
258			opt->len > opt_len) {
259			failed = TBADOPT;
260			break;
261		}
262		SOLD("got opthdr");
263		if (flag == T_NEGOTIATE) {
264			char *buf;
265
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)) {
270				failed = TSYSERR;
271				break;
272			}
273			SOLD("got optdata");
274			args[0] = fd;
275			args[1] = opt->level;
276			args[2] = opt->name;
277			args[3] = (long)buf;
278			args[4] = opt->len;
279			SOLD("calling SETSOCKOPT");
280			set_fs(KERNEL_DS);
281			error = sys_socketcall(SYS_SETSOCKOPT, args);
282			set_fs(old_fs);
283			if (error) {
284				failed = TBADOPT;
285				break;
286			}
287			SOLD("SETSOCKOPT ok");
288		}
289		orig_opt_len = opt->len;
290		opt->len = ret_space - sizeof(struct opthdr);
291		if (opt->len < 0) {
292			failed = TSYSERR;
293			break;
294		}
295		args[0] = fd;
296		args[1] = opt->level;
297		args[2] = opt->name;
298		args[3] = (long)(ret_pos+sizeof(struct opthdr));
299		args[4] = (long)&opt->len;
300		SOLD("calling GETSOCKOPT");
301		set_fs(KERNEL_DS);
302		error = sys_socketcall(SYS_GETSOCKOPT, args);
303		set_fs(old_fs);;
304		if (error) {
305			failed = TBADOPT;
306			break;
307		}
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;
314		SOLD("loop end");
315	}
316	SOLD("loop done");
317	if (do_ret) {
318		SOLD("generating ret msg");
319		if (failed)
320			timod_error(fd, T_OPTMGMT_REQ, failed, -error);
321		else {
322			struct T_primsg *it;
323			it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len);
324			if (it) {
325				struct T_optmgmt_ack *ack =
326					(struct T_optmgmt_ack *)&it->type;
327				SOLD("got primsg");
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),
333					ret_buf, ret_len);
334				timod_queue(fd, it);
335			}
336		}
337	}
338	SOLDD(("put_page %p\n", ret_buf));
339	putpage(ret_buf);
340	SOLD("done");
341	return 0;
342}
343
344int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len,
345			char *data_buf, int data_len, int flags)
346{
347	int ret, error, terror;
348	char *buf;
349	struct file *filp;
350	struct inode *ino;
351	struct sol_socket_struct *sock;
352	mm_segment_t old_fs = get_fs();
353	long args[6];
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;
361	SOLD("entry");
362	if (get_user(ret, (int *)A(ctl_buf)))
363		return -EFAULT;
364	switch (ret) {
365	case T_BIND_REQ:
366	{
367		struct T_bind_req req;
368
369		SOLDD(("bind %016lx(%016lx)\n", sock, filp));
370		SOLD("T_BIND_REQ");
371		if (sock->state != TS_UNBND) {
372			timod_error(fd, T_BIND_REQ, TOUTSTATE, 0);
373			return 0;
374		}
375		SOLD("state ok");
376		if (copy_from_user(&req, ctl_buf, sizeof(req))) {
377			timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
378			return 0;
379		}
380		SOLD("got ctl req");
381		if (req.ADDR_offset && req.ADDR_length) {
382			if (req.ADDR_length > BUF_SIZE) {
383				timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
384				return 0;
385			}
386			SOLD("req size ok");
387			buf = getpage();
388			if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) {
389				timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
390				putpage(buf);
391				return 0;
392			}
393			SOLD("got ctl data");
394			args[0] = fd;
395			args[1] = (long)buf;
396			args[2] = req.ADDR_length;
397			SOLD("calling BIND");
398			set_fs(KERNEL_DS);
399			error = sys_socketcall(SYS_BIND, args);
400			set_fs(old_fs);
401			putpage(buf);
402			SOLD("BIND returned");
403		} else
404			error = 0;
405		if (!error) {
406			struct T_primsg *it;
407			if (req.CONIND_number) {
408	  			args[0] = fd;
409  				args[1] = req.CONIND_number;
410  				SOLD("calling LISTEN");
411  				set_fs(KERNEL_DS);
412	  			error = sys_socketcall(SYS_LISTEN, args);
413  				set_fs(old_fs);
414  				SOLD("LISTEN done");
415  			}
416			it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr));
417			if (it) {
418				struct T_bind_ack *ack;
419
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;
425				args[0] = fd;
426				args[1] = (long)(ack+sizeof(*ack));
427				args[2] = (long)&ack->ADDR_length;
428				set_fs(KERNEL_DS);
429				sys_socketcall(SYS_GETSOCKNAME,args);
430				set_fs(old_fs);
431				sock->state = TS_IDLE;
432				timod_ok(fd, T_BIND_REQ);
433				timod_queue_end(fd, it);
434				SOLD("BIND done");
435				return 0;
436			}
437		}
438		SOLD("some error");
439		switch (error) {
440			case -EINVAL:
441				terror = TOUTSTATE;
442				error = 0;
443				break;
444			case -EACCES:
445				terror = TACCES;
446				error = 0;
447				break;
448			case -EADDRNOTAVAIL:
449			case -EADDRINUSE:
450				terror = TNOADDR;
451				error = 0;
452				break;
453			default:
454				terror = TSYSERR;
455				break;
456		}
457		timod_error(fd, T_BIND_REQ, terror, -error);
458		SOLD("BIND done");
459		return 0;
460	}
461	case T_CONN_REQ:
462	{
463		struct T_conn_req req;
464		unsigned short oldflags;
465		struct T_primsg *it;
466		SOLD("T_CONN_REQ");
467		if (sock->state != TS_UNBND && sock->state != TS_IDLE) {
468			timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
469			return 0;
470		}
471		SOLD("state ok");
472		if (copy_from_user(&req, ctl_buf, sizeof(req))) {
473			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
474			return 0;
475		}
476		SOLD("got ctl req");
477		if (ctl_len > BUF_SIZE) {
478			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
479			return 0;
480		}
481		SOLD("req size ok");
482		buf = getpage();
483		if (copy_from_user(buf, ctl_buf, ctl_len)) {
484			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
485			putpage(buf);
486			return 0;
487		}
488#ifdef DEBUG_SOLARIS
489		{
490			char * ptr = buf;
491			int len = ctl_len;
492			printk("returned data (%d bytes): ",len);
493			while( len-- ) {
494				if (!(len & 7))
495					printk(" ");
496				printk("%02x",(unsigned char)*ptr++);
497			}
498			printk("\n");
499		}
500#endif
501		SOLD("got ctl data");
502		args[0] = fd;
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");
508		set_fs(KERNEL_DS);
509		error = sys_socketcall(SYS_CONNECT, args);
510		set_fs(old_fs);
511		filp->f_flags = oldflags;
512		SOLD("CONNECT done");
513		if (!error) {
514			struct T_conn_con *con;
515			SOLD("no error");
516			it = timod_mkctl(ctl_len);
517			if (!it) {
518				putpage(buf);
519				return -ENOMEM;
520			}
521			con = (struct T_conn_con *)&it->type;
522#ifdef DEBUG_SOLARIS
523			{
524				char * ptr = buf;
525				int len = ctl_len;
526				printk("returned data (%d bytes): ",len);
527				while( len-- ) {
528					if (!(len & 7))
529						printk(" ");
530					printk("%02x",(unsigned char)*ptr++);
531				}
532				printk("\n");
533			}
534#endif
535			memcpy(con, buf, ctl_len);
536			SOLD("copied ctl_buf");
537			con->PRIM_type = T_CONN_CON;
538			sock->state = TS_DATA_XFER;
539		} else {
540			struct T_discon_ind *dis;
541			SOLD("some error");
542			it = timod_mkctl(sizeof(*dis));
543			if (!it) {
544				putpage(buf);
545				return -ENOMEM;
546			}
547			SOLD("got primsg");
548			dis = (struct T_discon_ind *)&it->type;
549			dis->PRIM_type = T_DISCON_IND;
550			dis->DISCON_reason = -error;
551			dis->SEQ_number = 0;
552		}
553		putpage(buf);
554		timod_ok(fd, T_CONN_REQ);
555		it->pri = 0;
556		timod_queue_end(fd, it);
557		SOLD("CONNECT done");
558		return 0;
559	}
560	case T_OPTMGMT_REQ:
561	{
562		struct T_optmgmt_req req;
563		SOLD("OPTMGMT_REQ");
564		if (copy_from_user(&req, ctl_buf, sizeof(req)))
565			return -EFAULT;
566		SOLD("got req");
567		return timod_optmgmt(fd, req.MGMT_flags,
568				req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL,
569				req.OPT_length, 1);
570	}
571	case T_UNITDATA_REQ:
572	{
573		struct T_unitdata_req req;
574
575		int err;
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);
579			return 0;
580		}
581		SOLD("state ok");
582		if (copy_from_user(&req, ctl_buf, sizeof(req))) {
583			timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
584			return 0;
585		}
586		SOLD("got ctl req");
587#ifdef DEBUG_SOLARIS
588		{
589			char * ptr = ctl_buf+req.DEST_offset;
590			int len = req.DEST_length;
591			printk("socket address (%d bytes): ",len);
592			while( len-- ) {
593				char c;
594				if (get_user(c,ptr))
595					printk("??");
596				else
597					printk("%02x",(unsigned char)c);
598				ptr++;
599			}
600			printk("\n");
601		}
602#endif
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);
604		if (err == data_len)
605			return 0;
606		if(err >= 0) {
607			printk("timod: sendto failed to send all the data\n");
608			return 0;
609		}
610		timod_error(fd, T_CONN_REQ, TSYSERR, -err);
611		return 0;
612	}
613	default:
614		printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret);
615		break;
616	}
617	return -EINVAL;
618}
619
620int 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)
622{
623	int error;
624	int oldflags;
625	struct file *filp;
626	struct inode *ino;
627	struct sol_socket_struct *sock;
628	struct T_unitdata_ind udi;
629	mm_segment_t old_fs = get_fs();
630	long args[6];
631	char *tmpbuf;
632	int tmplen;
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 *);
636
637	SOLD("entry");
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");
646		args[0] = fd;
647		args[1] = -1;
648		set_fs(KERNEL_DS);
649		sys_socketcall(SYS_LISTEN, args);
650		set_fs(old_fs);
651		SOLD("LISTEN done");
652	}
653	if (!(filp->f_flags & O_NONBLOCK)) {
654		poll_table wait_table, *wait;
655
656		poll_initwait(&wait_table);
657		wait = &wait_table;
658		for(;;) {
659			SOLD("loop");
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))
668				break;
669			SOLD("cond 1 passed");
670			if (
671			#if 1
672				*flags_p != MSG_HIPRI &&
673			#endif
674				((filp->f_op->poll(filp, wait) & POLLIN) ||
675				(filp->f_op->poll(filp, NULL) & POLLIN) ||
676				signal_pending(current))
677			) {
678				break;
679			}
680			if( *flags_p == MSG_HIPRI ) {
681				SOLD("avoiding lockup");
682				break ;
683			}
684			if(wait_table.error) {
685				SOLD("wait-table error");
686				poll_freewait(&wait_table);
687				return wait_table.error;
688			}
689			SOLD("scheduling");
690			schedule();
691		}
692		SOLD("loop done");
693		current->state = TASK_RUNNING;
694		poll_freewait(&wait_table);
695		if (signal_pending(current)) {
696			SOLD("signal pending");
697			return -EINTR;
698		}
699	}
700	if (ctl_maxlen >= 0 && sock->pfirst) {
701		struct T_primsg *it = sock->pfirst;
702		int l = min_t(int, ctl_maxlen, it->length);
703		SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);
704		SOLD("purting ctl data");
705		if(copy_to_user(ctl_buf,
706			(char*)&it->type + sock->offset, l))
707			return -EFAULT;
708		SOLD("pur it");
709		if(put_user(l, ctl_len))
710			return -EFAULT;
711		SOLD("set ctl_len");
712		*flags_p = it->pri;
713		it->length -= l;
714		if (it->length) {
715			SOLD("more ctl");
716			sock->offset += l;
717			return MORECTL;
718		} else {
719			SOLD("removing message");
720			sock->pfirst = it->next;
721			if (!sock->pfirst)
722				sock->plast = NULL;
723			SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst));
724			mykfree(it);
725			sock->offset = 0;
726			SOLD("ctl done");
727			return 0;
728		}
729	}
730	*flags_p = 0;
731	if (ctl_maxlen >= 0) {
732		SOLD("ACCEPT perhaps?");
733		if (ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) {
734			struct T_conn_ind ind;
735			char *buf = getpage();
736			int len = BUF_SIZE;
737
738			SOLD("trying ACCEPT");
739			if (put_user(ctl_maxlen - sizeof(ind), ctl_len))
740				return -EFAULT;
741			args[0] = fd;
742			args[1] = (long)buf;
743			args[2] = (long)&len;
744			oldflags = filp->f_flags;
745			filp->f_flags |= O_NONBLOCK;
746			SOLD("calling ACCEPT");
747			set_fs(KERNEL_DS);
748			error = sys_socketcall(SYS_ACCEPT, args);
749			set_fs(old_fs);
750			filp->f_flags = oldflags;
751			if (error < 0) {
752				SOLD("some error");
753				putpage(buf);
754				return error;
755			}
756			if (error) {
757				SOLD("connect");
758				putpage(buf);
759				if (sizeof(ind) > ctl_maxlen) {
760					SOLD("generating CONN_IND");
761					ind.PRIM_type = T_CONN_IND;
762					ind.SRC_length = len;
763					ind.SRC_offset = sizeof(ind);
764					ind.OPT_length = ind.OPT_offset = 0;
765					ind.SEQ_number = error;
766					if(copy_to_user(ctl_buf, &ind, sizeof(ind))||
767					   put_user(sizeof(ind)+ind.SRC_length,ctl_len))
768						return -EFAULT;
769					SOLD("CONN_IND created");
770				}
771				if (data_maxlen >= 0)
772					put_user(0, data_len);
773				SOLD("CONN_IND done");
774				return 0;
775			}
776			if (len>ctl_maxlen) {
777				SOLD("data don't fit");
778				putpage(buf);
779				return -EFAULT;
780			}
781			if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){
782				SOLD("can't copy data");
783				putpage(buf);
784				return -EFAULT;
785			}
786			SOLD("ACCEPT done");
787			putpage(buf);
788		}
789	}
790	SOLD("checking data req");
791	if (data_maxlen <= 0) {
792		if (data_maxlen == 0)
793			put_user(0, data_len);
794		if (ctl_maxlen >= 0)
795			put_user(0, ctl_len);
796		return -EAGAIN;
797	}
798	SOLD("wants data");
799	if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
800		SOLD("udi fits");
801		tmpbuf = ctl_buf + sizeof(udi);
802		tmplen = ctl_maxlen - sizeof(udi);
803	} else {
804		SOLD("udi does not fit");
805		tmpbuf = NULL;
806		tmplen = 0;
807	}
808	if (put_user(tmplen, ctl_len))
809		return -EFAULT;
810	SOLD("set ctl_len");
811	oldflags = filp->f_flags;
812	filp->f_flags |= O_NONBLOCK;
813	SOLD("calling recvfrom");
814	sys_recvfrom = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom);
815	error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr*)tmpbuf, ctl_len);
816	filp->f_flags = oldflags;
817	if (error < 0)
818		return error;
819	SOLD("error >= 0" ) ;
820	if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
821		SOLD("generating udi");
822		udi.PRIM_type = T_UNITDATA_IND;
823		get_user(udi.SRC_length, ctl_len);
824		udi.SRC_offset = sizeof(udi);
825		udi.OPT_length = udi.OPT_offset = 0;
826		copy_to_user(ctl_buf, &udi, sizeof(udi));
827		put_user(sizeof(udi)+udi.SRC_length, ctl_len);
828		SOLD("udi done");
829	} else
830		put_user(0, ctl_len);
831	put_user(error, data_len);
832	SOLD("done");
833	return 0;
834}
835
836asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
837{
838	struct file *filp;
839	struct inode *ino;
840	struct strbuf *ctlptr, *datptr;
841	struct strbuf ctl, dat;
842	int *flgptr;
843	int flags;
844	int error = -EBADF;
845
846	SOLD("entry");
847	lock_kernel();
848	if(fd >= NR_OPEN) goto out;
849
850	filp = current->files->fd[fd];
851	if(!filp) goto out;
852
853	ino = filp->f_dentry->d_inode;
854	if (!ino) goto out;
855
856	if (!ino->i_sock)
857		goto out;
858
859	ctlptr = (struct strbuf *)A(arg1);
860	datptr = (struct strbuf *)A(arg2);
861	flgptr = (int *)A(arg3);
862
863	error = -EFAULT;
864
865	if (ctlptr) {
866		if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) ||
867		    put_user(-1,&ctlptr->len))
868			goto out;
869	} else
870		ctl.maxlen = -1;
871
872	if (datptr) {
873		if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) ||
874		    put_user(-1,&datptr->len))
875			goto out;
876	} else
877		dat.maxlen = -1;
878
879	if (get_user(flags,flgptr))
880		goto out;
881
882	switch (flags) {
883	case 0:
884	case MSG_HIPRI:
885	case MSG_ANY:
886	case MSG_BAND:
887		break;
888	default:
889		error = -EINVAL;
890		goto out;
891	}
892
893	error = timod_getmsg(fd,(char*)A(ctl.buf),ctl.maxlen,&ctlptr->len,
894				(char*)A(dat.buf),dat.maxlen,&datptr->len,&flags);
895
896	if (!error && put_user(flags,flgptr))
897		error = -EFAULT;
898out:
899	unlock_kernel();
900	SOLD("done");
901	return error;
902}
903
904asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
905{
906	struct file *filp;
907	struct inode *ino;
908	struct strbuf *ctlptr, *datptr;
909	struct strbuf ctl, dat;
910	int flags = (int) arg3;
911	int error = -EBADF;
912
913	SOLD("entry");
914	lock_kernel();
915	if(fd >= NR_OPEN) goto out;
916
917	filp = current->files->fd[fd];
918	if(!filp) goto out;
919
920	ino = filp->f_dentry->d_inode;
921	if (!ino) goto out;
922
923	if (!ino->i_sock &&
924		(MAJOR(ino->i_rdev) != 30 || MINOR(ino->i_rdev) != 1))
925		goto out;
926
927	ctlptr = (struct strbuf *)A(arg1);
928	datptr = (struct strbuf *)A(arg2);
929
930	error = -EFAULT;
931
932	if (ctlptr) {
933		if (copy_from_user(&ctl,ctlptr,sizeof(ctl)))
934			goto out;
935		if (ctl.len < 0 && flags) {
936			error = -EINVAL;
937			goto out;
938		}
939	} else {
940		ctl.len = 0;
941		ctl.buf = 0;
942	}
943
944	if (datptr) {
945		if (copy_from_user(&dat,datptr,sizeof(dat)))
946			goto out;
947	} else {
948		dat.len = 0;
949		dat.buf = 0;
950	}
951
952	error = timod_putmsg(fd,(char*)A(ctl.buf),ctl.len,
953				(char*)A(dat.buf),dat.len,flags);
954out:
955	unlock_kernel();
956	SOLD("done");
957	return error;
958}
959