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