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 = ¤t->files->fd[fd]->f_dentry->d_inode->u.socket_i; 153 wake_up_interruptible(&sock->wait); 154 read_lock(&sock->sk->callback_lock); 155 if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) 156 __kill_fasync(sock->fasync_list, SIGIO, POLL_IN); 157 read_unlock(&sock->sk->callback_lock); 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