1 /* $Id: timod.c,v 1.16.2.1 2001/12/18 22:15:25 davem 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 
30 extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
31 	unsigned long arg);
32 extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd,
33 	u32 arg);
34 asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
35 
36 static spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED;
37 static char * page = NULL ;
38 
39 #ifndef DEBUG_SOLARIS_KMALLOC
40 
41 #define mykmalloc kmalloc
42 #define mykfree kfree
43 
44 #else
45 
mykmalloc(size_t s,int gfp)46 void * 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 
mykfree(void * p)67 void 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 
getpage(void)94 static 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 
putpage(char * p)114 static 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 
timod_mkctl(int size)132 static 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 
timod_wake_socket(unsigned int fd)147 static 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 
timod_queue(unsigned int fd,struct T_primsg * it)161 static 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 
timod_queue_end(unsigned int fd,struct T_primsg * it)175 static 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 
timod_error(unsigned int fd,int prim,int terr,int uerr)190 static 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; /* FIXME: convert this */
204 		timod_queue(fd, it);
205 	}
206 	SOLD("done");
207 }
208 
timod_ok(unsigned int fd,int prim)209 static 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 
timod_optmgmt(unsigned int fd,int flag,char * opt_buf,int opt_len,int do_ret)226 static 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 
timod_putmsg(unsigned int fd,char * ctl_buf,int ctl_len,char * data_buf,int data_len,int flags)344 int 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;	/* FIXME: convert this as in iABI_errors() */
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 
timod_getmsg(unsigned int fd,char * ctl_buf,int ctl_maxlen,s32 * ctl_len,char * data_buf,int data_maxlen,s32 * data_len,int * flags_p)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)
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;		/* XXX - is this ok ? */
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 
solaris_getmsg(unsigned int fd,u32 arg1,u32 arg2,u32 arg3)836 asmlinkage 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;
898 out:
899 	unlock_kernel();
900 	SOLD("done");
901 	return error;
902 }
903 
solaris_putmsg(unsigned int fd,u32 arg1,u32 arg2,u32 arg3)904 asmlinkage 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);
954 out:
955 	unlock_kernel();
956 	SOLD("done");
957 	return error;
958 }
959