00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <linux/types.h>
00012 #include <linux/kernel.h>
00013 #include <linux/sched.h>
00014 #include <linux/smp.h>
00015 #include <linux/smp_lock.h>
00016 #include <linux/ioctl.h>
00017 #include <linux/fs.h>
00018 #include <linux/netdevice.h>
00019 #include <linux/poll.h>
00020
00021 #include <asm/uaccess.h>
00022 #include <asm/termios.h>
00023
00024 #include "conv.h"
00025 #include "socksys.h"
00026
00027 extern char *getname32(u32 filename);
00028 #define putname32 putname
00029
00030 extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
00031 unsigned long arg);
00032 extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd,
00033 u32 arg);
00034 asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
00035
00036 #ifdef __SMP__
00037 spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED;
00038 #endif
00039 static char * page = NULL ;
00040
00041 #ifndef DEBUG_SOLARIS_KMALLOC
00042
00043 #define mykmalloc kmalloc
00044 #define mykfree kfree
00045
00046 #else
00047
00048 void * mykmalloc(size_t s, int gfp)
00049 {
00050 static char * page;
00051 static size_t free = 0;
00052 void * r;
00053 s = ((s + 63) & ~63);
00054 if( s > PAGE_SIZE ) {
00055 SOLD("too big size, calling real kmalloc");
00056 return kmalloc(s, gfp);
00057 }
00058 if( s > free ) {
00059
00060 page = (char *)__get_free_page(gfp);
00061 free = PAGE_SIZE;
00062 }
00063 r = page;
00064 page += s;
00065 free -= s;
00066 return r;
00067 }
00068
00069 void mykfree(void *p)
00070 {
00071 }
00072
00073 #endif
00074
00075 #ifndef DEBUG_SOLARIS
00076
00077 #define BUF_SIZE PAGE_SIZE
00078 #define PUT_MAGIC(a,m)
00079 #define CHECK_MAGIC(a,m)
00080 #define BUF_OFFSET 0
00081 #define MKCTL_TRAILER 0
00082
00083 #else
00084
00085 #define BUF_SIZE (PAGE_SIZE-2*sizeof(u64))
00086 #define BUFPAGE_MAGIC 0xBADC0DEDDEADBABEL
00087 #define MKCTL_MAGIC 0xDEADBABEBADC0DEDL
00088 #define PUT_MAGIC(a,m) do{(*(u64*)(a))=(m);}while(0)
00089 #define CHECK_MAGIC(a,m) do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
00090 __FILE__,__LINE__,__FUNCTION__,(m),(a));}while(0)
00091 #define BUF_OFFSET sizeof(u64)
00092 #define MKCTL_TRAILER sizeof(u64)
00093
00094 #endif
00095
00096 static char *getpage( void )
00097 {
00098 char *r;
00099 SOLD("getting page");
00100 spin_lock(&timod_pagelock);
00101 if (page) {
00102 r = page;
00103 page = NULL;
00104 spin_unlock(&timod_pagelock);
00105 SOLD("got cached");
00106 return r + BUF_OFFSET;
00107 }
00108 spin_unlock(&timod_pagelock);
00109 SOLD("getting new");
00110 r = (char *)__get_free_page(GFP_KERNEL);
00111 PUT_MAGIC(r,BUFPAGE_MAGIC);
00112 PUT_MAGIC(r+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
00113 return r + BUF_OFFSET;
00114 }
00115
00116 static void putpage(char *p)
00117 {
00118 SOLD("putting page");
00119 p = p - BUF_OFFSET;
00120 CHECK_MAGIC(p,BUFPAGE_MAGIC);
00121 CHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
00122 spin_lock(&timod_pagelock);
00123 if (page) {
00124 spin_unlock(&timod_pagelock);
00125 free_page((unsigned long)p);
00126 SOLD("freed it");
00127 } else {
00128 page = p;
00129 spin_unlock(&timod_pagelock);
00130 SOLD("cached it");
00131 }
00132 }
00133
00134 static struct T_primsg *timod_mkctl(int size)
00135 {
00136 struct T_primsg *it;
00137
00138 SOLD("creating primsg");
00139 it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL);
00140 if (it) {
00141 SOLD("got it");
00142 it->pri = MSG_HIPRI;
00143 it->length = size;
00144 PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC);
00145 }
00146 return it;
00147 }
00148
00149 static void timod_wake_socket(unsigned int fd)
00150 {
00151 struct socket *sock;
00152
00153 SOLD("wakeing socket");
00154 sock = ¤t->files->fd[fd]->f_dentry->d_inode->u.socket_i;
00155 wake_up_interruptible(&sock->wait);
00156 if (sock->fasync_list && !(sock->flags & SO_WAITDATA))
00157 kill_fasync(sock->fasync_list, SIGIO);
00158 SOLD("done");
00159 }
00160
00161 static void timod_queue(unsigned int fd, struct T_primsg *it)
00162 {
00163 struct sol_socket_struct *sock;
00164
00165 SOLD("queuing primsg");
00166 sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
00167 it->next = sock->pfirst;
00168 sock->pfirst = it;
00169 if (!sock->plast)
00170 sock->plast = it;
00171 timod_wake_socket(fd);
00172 SOLD("done");
00173 }
00174
00175 static void timod_queue_end(unsigned int fd, struct T_primsg *it)
00176 {
00177 struct sol_socket_struct *sock;
00178
00179 SOLD("queuing primsg at end");
00180 sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
00181 it->next = NULL;
00182 if (sock->plast)
00183 sock->plast->next = it;
00184 else
00185 sock->pfirst = it;
00186 sock->plast = it;
00187 SOLD("done");
00188 }
00189
00190 static void timod_error(unsigned int fd, int prim, int terr, int uerr)
00191 {
00192 struct T_primsg *it;
00193
00194 SOLD("making error");
00195 it = timod_mkctl(sizeof(struct T_error_ack));
00196 if (it) {
00197 struct T_error_ack *err = (struct T_error_ack *)&it->type;
00198
00199 SOLD("got it");
00200 err->PRIM_type = T_ERROR_ACK;
00201 err->ERROR_prim = prim;
00202 err->TLI_error = terr;
00203 err->UNIX_error = uerr;
00204 timod_queue(fd, it);
00205 }
00206 SOLD("done");
00207 }
00208
00209 static void timod_ok(unsigned int fd, int prim)
00210 {
00211 struct T_primsg *it;
00212 struct T_ok_ack *ok;
00213
00214 SOLD("creating ok ack");
00215 it = timod_mkctl(sizeof(*ok));
00216 if (it) {
00217 SOLD("got it");
00218 ok = (struct T_ok_ack *)&it->type;
00219 ok->PRIM_type = T_OK_ACK;
00220 ok->CORRECT_prim = prim;
00221 timod_queue(fd, it);
00222 }
00223 SOLD("done");
00224 }
00225
00226 static int timod_optmgmt(unsigned int fd, int flag, char *opt_buf, int opt_len, int do_ret)
00227 {
00228 int error, failed;
00229 int ret_space, ret_len;
00230 long args[5];
00231 char *ret_pos,*ret_buf;
00232 int (*sys_socketcall)(int, unsigned long *) =
00233 (int (*)(int, unsigned long *))SYS(socketcall);
00234 mm_segment_t old_fs = get_fs();
00235
00236 SOLD("entry");
00237 SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret));
00238 if (!do_ret && (!opt_buf || opt_len <= 0))
00239 return 0;
00240 SOLD("getting page");
00241 ret_pos = ret_buf = getpage();
00242 ret_space = BUF_SIZE;
00243 ret_len = 0;
00244
00245 error = failed = 0;
00246 SOLD("looping");
00247 while(opt_len >= sizeof(struct opthdr)) {
00248 struct opthdr *opt;
00249 int orig_opt_len;
00250 SOLD("loop start");
00251 opt = (struct opthdr *)ret_pos;
00252 if (ret_space < sizeof(struct opthdr)) {
00253 failed = TSYSERR;
00254 break;
00255 }
00256 SOLD("getting opthdr");
00257 if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) ||
00258 opt->len > opt_len) {
00259 failed = TBADOPT;
00260 break;
00261 }
00262 SOLD("got opthdr");
00263 if (flag == T_NEGOTIATE) {
00264 char *buf;
00265
00266 SOLD("handling T_NEGOTIATE");
00267 buf = ret_pos + sizeof(struct opthdr);
00268 if (ret_space < opt->len + sizeof(struct opthdr) ||
00269 copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) {
00270 failed = TSYSERR;
00271 break;
00272 }
00273 SOLD("got optdata");
00274 args[0] = fd;
00275 args[1] = opt->level;
00276 args[2] = opt->name;
00277 args[3] = (long)buf;
00278 args[4] = opt->len;
00279 SOLD("calling SETSOCKOPT");
00280 set_fs(KERNEL_DS);
00281 error = sys_socketcall(SYS_SETSOCKOPT, args);
00282 set_fs(old_fs);
00283 if (error) {
00284 failed = TBADOPT;
00285 break;
00286 }
00287 SOLD("SETSOCKOPT ok");
00288 }
00289 orig_opt_len = opt->len;
00290 opt->len = ret_space - sizeof(struct opthdr);
00291 if (opt->len < 0) {
00292 failed = TSYSERR;
00293 break;
00294 }
00295 args[0] = fd;
00296 args[1] = opt->level;
00297 args[2] = opt->name;
00298 args[3] = (long)(ret_pos+sizeof(struct opthdr));
00299 args[4] = (long)&opt->len;
00300 SOLD("calling GETSOCKOPT");
00301 set_fs(KERNEL_DS);
00302 error = sys_socketcall(SYS_GETSOCKOPT, args);
00303 set_fs(old_fs);;
00304 if (error) {
00305 failed = TBADOPT;
00306 break;
00307 }
00308 SOLD("GETSOCKOPT ok");
00309 ret_space -= sizeof(struct opthdr) + opt->len;
00310 ret_len += sizeof(struct opthdr) + opt->len;
00311 ret_pos += sizeof(struct opthdr) + opt->len;
00312 opt_len -= sizeof(struct opthdr) + orig_opt_len;
00313 opt_buf += sizeof(struct opthdr) + orig_opt_len;
00314 SOLD("loop end");
00315 }
00316 SOLD("loop done");
00317 if (do_ret) {
00318 SOLD("generating ret msg");
00319 if (failed)
00320 timod_error(fd, T_OPTMGMT_REQ, failed, -error);
00321 else {
00322 struct T_primsg *it;
00323 it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len);
00324 if (it) {
00325 struct T_optmgmt_ack *ack =
00326 (struct T_optmgmt_ack *)&it->type;
00327 SOLD("got primsg");
00328 ack->PRIM_type = T_OPTMGMT_ACK;
00329 ack->OPT_length = ret_len;
00330 ack->OPT_offset = sizeof(struct T_optmgmt_ack);
00331 ack->MGMT_flags = (failed ? T_FAILURE : flag);
00332 memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack),
00333 ret_buf, ret_len);
00334 timod_queue(fd, it);
00335 }
00336 }
00337 }
00338 SOLDD(("put_page %p\n", ret_buf));
00339 putpage(ret_buf);
00340 SOLD("done");
00341 return 0;
00342 }
00343
00344 int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len,
00345 char *data_buf, int data_len, int flags)
00346 {
00347 int ret, error, terror;
00348 char *buf;
00349 struct file *filp;
00350 struct inode *ino;
00351 struct sol_socket_struct *sock;
00352 mm_segment_t old_fs = get_fs();
00353 long args[6];
00354 int (*sys_socketcall)(int, unsigned long *) =
00355 (int (*)(int, unsigned long *))SYS(socketcall);
00356 int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int) =
00357 (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int))SYS(sendto);
00358 filp = current->files->fd[fd];
00359 ino = filp->f_dentry->d_inode;
00360 sock = (struct sol_socket_struct *)filp->private_data;
00361 SOLD("entry");
00362 if (get_user(ret, (int *)A(ctl_buf)))
00363 return -EFAULT;
00364 switch (ret) {
00365 case T_BIND_REQ:
00366 {
00367 struct T_bind_req req;
00368
00369 SOLDD(("bind %016lx(%016lx)\n", sock, filp));
00370 SOLD("T_BIND_REQ");
00371 if (sock->state != TS_UNBND) {
00372 timod_error(fd, T_BIND_REQ, TOUTSTATE, 0);
00373 return 0;
00374 }
00375 SOLD("state ok");
00376 if (copy_from_user(&req, ctl_buf, sizeof(req))) {
00377 timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
00378 return 0;
00379 }
00380 SOLD("got ctl req");
00381 if (req.ADDR_offset && req.ADDR_length) {
00382 if (req.ADDR_length > BUF_SIZE) {
00383 timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
00384 return 0;
00385 }
00386 SOLD("req size ok");
00387 buf = getpage();
00388 if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) {
00389 timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT);
00390 putpage(buf);
00391 return 0;
00392 }
00393 SOLD("got ctl data");
00394 args[0] = fd;
00395 args[1] = (long)buf;
00396 args[2] = req.ADDR_length;
00397 SOLD("calling BIND");
00398 set_fs(KERNEL_DS);
00399 error = sys_socketcall(SYS_BIND, args);
00400 set_fs(old_fs);
00401 putpage(buf);
00402 SOLD("BIND returned");
00403 } else
00404 error = 0;
00405 if (!error) {
00406 struct T_primsg *it;
00407 if (req.CONIND_number) {
00408 args[0] = fd;
00409 args[1] = req.CONIND_number;
00410 SOLD("calling LISTEN");
00411 set_fs(KERNEL_DS);
00412 error = sys_socketcall(SYS_LISTEN, args);
00413 set_fs(old_fs);
00414 SOLD("LISTEN done");
00415 }
00416 it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr));
00417 if (it) {
00418 struct T_bind_ack *ack;
00419
00420 ack = (struct T_bind_ack *)&it->type;
00421 ack->PRIM_type = T_BIND_ACK;
00422 ack->ADDR_offset = sizeof(*ack);
00423 ack->ADDR_length = sizeof(struct sockaddr);
00424 ack->CONIND_number = req.CONIND_number;
00425 args[0] = fd;
00426 args[1] = (long)(ack+sizeof(*ack));
00427 args[2] = (long)&ack->ADDR_length;
00428 set_fs(KERNEL_DS);
00429 sys_socketcall(SYS_GETSOCKNAME,args);
00430 set_fs(old_fs);
00431 sock->state = TS_IDLE;
00432 timod_ok(fd, T_BIND_REQ);
00433 timod_queue_end(fd, it);
00434 SOLD("BIND done");
00435 return 0;
00436 }
00437 }
00438 SOLD("some error");
00439 switch (error) {
00440 case -EINVAL:
00441 terror = TOUTSTATE;
00442 error = 0;
00443 break;
00444 case -EACCES:
00445 terror = TACCES;
00446 error = 0;
00447 break;
00448 case -EADDRNOTAVAIL:
00449 case -EADDRINUSE:
00450 terror = TNOADDR;
00451 error = 0;
00452 break;
00453 default:
00454 terror = TSYSERR;
00455 break;
00456 }
00457 timod_error(fd, T_BIND_REQ, terror, -error);
00458 SOLD("BIND done");
00459 return 0;
00460 }
00461 case T_CONN_REQ:
00462 {
00463 struct T_conn_req req;
00464 unsigned short oldflags;
00465 struct T_primsg *it;
00466 SOLD("T_CONN_REQ");
00467 if (sock->state != TS_UNBND && sock->state != TS_IDLE) {
00468 timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
00469 return 0;
00470 }
00471 SOLD("state ok");
00472 if (copy_from_user(&req, ctl_buf, sizeof(req))) {
00473 timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
00474 return 0;
00475 }
00476 SOLD("got ctl req");
00477 if (ctl_len > BUF_SIZE) {
00478 timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
00479 return 0;
00480 }
00481 SOLD("req size ok");
00482 buf = getpage();
00483 if (copy_from_user(buf, ctl_buf, ctl_len)) {
00484 timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
00485 putpage(buf);
00486 return 0;
00487 }
00488 #ifdef DEBUG_SOLARIS
00489 {
00490 char * ptr = buf;
00491 int len = ctl_len;
00492 printk("returned data (%d bytes): ",len);
00493 while( len-- ) {
00494 if (!(len & 7))
00495 printk(" ");
00496 printk("%02x",(unsigned char)*ptr++);
00497 }
00498 printk("\n");
00499 }
00500 #endif
00501 SOLD("got ctl data");
00502 args[0] = fd;
00503 args[1] = (long)buf+req.DEST_offset;
00504 args[2] = req.DEST_length;
00505 oldflags = filp->f_flags;
00506 filp->f_flags &= ~O_NONBLOCK;
00507 SOLD("calling CONNECT");
00508 set_fs(KERNEL_DS);
00509 error = sys_socketcall(SYS_CONNECT, args);
00510 set_fs(old_fs);
00511 filp->f_flags = oldflags;
00512 SOLD("CONNECT done");
00513 if (!error) {
00514 struct T_conn_con *con;
00515 SOLD("no error");
00516 it = timod_mkctl(ctl_len);
00517 if (!it) {
00518 putpage(buf);
00519 return -ENOMEM;
00520 }
00521 con = (struct T_conn_con *)&it->type;
00522 #ifdef DEBUG_SOLARIS
00523 {
00524 char * ptr = buf;
00525 int len = ctl_len;
00526 printk("returned data (%d bytes): ",len);
00527 while( len-- ) {
00528 if (!(len & 7))
00529 printk(" ");
00530 printk("%02x",(unsigned char)*ptr++);
00531 }
00532 printk("\n");
00533 }
00534 #endif
00535 memcpy(con, buf, ctl_len);
00536 SOLD("copied ctl_buf");
00537 con->PRIM_type = T_CONN_CON;
00538 sock->state = TS_DATA_XFER;
00539 } else {
00540 struct T_discon_ind *dis;
00541 SOLD("some error");
00542 it = timod_mkctl(sizeof(*dis));
00543 if (!it) {
00544 putpage(buf);
00545 return -ENOMEM;
00546 }
00547 SOLD("got primsg");
00548 dis = (struct T_discon_ind *)&it->type;
00549 dis->PRIM_type = T_DISCON_IND;
00550 dis->DISCON_reason = -error;
00551 dis->SEQ_number = 0;
00552 }
00553 putpage(buf);
00554 timod_ok(fd, T_CONN_REQ);
00555 it->pri = 0;
00556 timod_queue_end(fd, it);
00557 SOLD("CONNECT done");
00558 return 0;
00559 }
00560 case T_OPTMGMT_REQ:
00561 {
00562 struct T_optmgmt_req req;
00563 SOLD("OPTMGMT_REQ");
00564 if (copy_from_user(&req, ctl_buf, sizeof(req)))
00565 return -EFAULT;
00566 SOLD("got req");
00567 return timod_optmgmt(fd, req.MGMT_flags,
00568 req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL,
00569 req.OPT_length, 1);
00570 }
00571 case T_UNITDATA_REQ:
00572 {
00573 struct T_unitdata_req req;
00574
00575 int err;
00576 SOLD("T_UNITDATA_REQ");
00577 if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) {
00578 timod_error(fd, T_CONN_REQ, TOUTSTATE, 0);
00579 return 0;
00580 }
00581 SOLD("state ok");
00582 if (copy_from_user(&req, ctl_buf, sizeof(req))) {
00583 timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT);
00584 return 0;
00585 }
00586 SOLD("got ctl req");
00587 #ifdef DEBUG_SOLARIS
00588 {
00589 char * ptr = ctl_buf+req.DEST_offset;
00590 int len = req.DEST_length;
00591 printk("socket address (%d bytes): ",len);
00592 while( len-- ) {
00593 char c;
00594 if (get_user(c,ptr))
00595 printk("??");
00596 else
00597 printk("%02x",(unsigned char)c);
00598 ptr++;
00599 }
00600 printk("\n");
00601 }
00602 #endif
00603 err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr*)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length);
00604 if (err == data_len)
00605 return 0;
00606 if(err >= 0) {
00607 printk("timod: sendto failed to send all the data\n");
00608 return 0;
00609 }
00610 timod_error(fd, T_CONN_REQ, TSYSERR, -err);
00611 return 0;
00612 }
00613 default:
00614 printk("timod_putmsg: unsuported command %u.\n", ret);
00615 break;
00616 }
00617 return -EINVAL;
00618 }
00619
00620
00621
00622 static void free_wait(poll_table * p)
00623 {
00624 struct poll_table_entry * entry = p->entry + p->nr;
00625
00626 SOLD("entry");
00627 while (p->nr > 0) {
00628 p->nr--;
00629 entry--;
00630 remove_wait_queue(entry->wait_address,&entry->wait);
00631 }
00632 SOLD("done");
00633 }
00634
00635
00636 int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, s32 *ctl_len,
00637 char *data_buf, int data_maxlen, s32 *data_len, int *flags_p)
00638 {
00639 int error;
00640 int oldflags;
00641 struct file *filp;
00642 struct inode *ino;
00643 struct sol_socket_struct *sock;
00644 struct T_unitdata_ind udi;
00645 mm_segment_t old_fs = get_fs();
00646 long args[6];
00647 char *tmpbuf;
00648 int tmplen;
00649 int (*sys_socketcall)(int, unsigned long *) =
00650 (int (*)(int, unsigned long *))SYS(socketcall);
00651 int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *);
00652
00653 SOLD("entry");
00654 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));
00655 filp = current->files->fd[fd];
00656 ino = filp->f_dentry->d_inode;
00657 sock = (struct sol_socket_struct *)filp->private_data;
00658 SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
00659 if ( ctl_maxlen > 0 && !sock->pfirst && ino->u.socket_i.type == SOCK_STREAM
00660 && sock->state == TS_IDLE) {
00661 SOLD("calling LISTEN");
00662 args[0] = fd;
00663 args[1] = -1;
00664 set_fs(KERNEL_DS);
00665 sys_socketcall(SYS_LISTEN, args);
00666 set_fs(old_fs);
00667 SOLD("LISTEN done");
00668 }
00669 if (!(filp->f_flags & O_NONBLOCK)) {
00670 poll_table wait_table, *wait;
00671 struct poll_table_entry *entry;
00672 SOLD("getting poll_table");
00673 entry = (struct poll_table_entry *)__get_free_page(GFP_KERNEL);
00674 if (!entry)
00675 return -ENOMEM;
00676 SOLD("got one");
00677 wait_table.nr = 0;
00678 wait_table.entry = entry;
00679 wait = &wait_table;
00680 for(;;) {
00681 SOLD("loop");
00682 current->state = TASK_INTERRUPTIBLE;
00683
00684
00685
00686
00687
00688
00689 if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI))
00690 break;
00691 SOLD("cond 1 passed");
00692 if (
00693 #if 1
00694 *flags_p != MSG_HIPRI &&
00695 #endif
00696 ((filp->f_op->poll(filp, wait) & POLLIN) ||
00697 (filp->f_op->poll(filp, NULL) & POLLIN) ||
00698 signal_pending(current))
00699 ) {
00700 break;
00701 }
00702 if( *flags_p == MSG_HIPRI ) {
00703 SOLD("avoiding lockup");
00704 break ;
00705 }
00706 SOLD("scheduling");
00707 schedule();
00708 }
00709 SOLD("loop done");
00710 current->state = TASK_RUNNING;
00711 free_wait(&wait_table);
00712 free_page((unsigned long)entry);
00713 if (signal_pending(current)) {
00714 SOLD("signal pending");
00715 return -EINTR;
00716 }
00717 }
00718 if (ctl_maxlen >= 0 && sock->pfirst) {
00719 struct T_primsg *it = sock->pfirst;
00720 #ifndef min
00721 #define min(a,b) ((a)<(b)?(a):(b))
00722 #endif
00723 int l = min(ctl_maxlen, it->length);
00724 CHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);
00725 SOLD("purting ctl data");
00726 if(copy_to_user(ctl_buf,
00727 (char*)&it->type + sock->offset, l))
00728 return -EFAULT;
00729 SOLD("pur it");
00730 if(put_user(l, ctl_len))
00731 return -EFAULT;
00732 SOLD("set ctl_len");
00733 *flags_p = it->pri;
00734 it->length -= l;
00735 if (it->length) {
00736 SOLD("more ctl");
00737 sock->offset += l;
00738 return MORECTL;
00739 } else {
00740 SOLD("removing message");
00741 sock->pfirst = it->next;
00742 if (!sock->pfirst)
00743 sock->plast = NULL;
00744 SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst));
00745 mykfree(it);
00746 sock->offset = 0;
00747 SOLD("ctl done");
00748 return 0;
00749 }
00750 }
00751 *flags_p = 0;
00752 if (ctl_maxlen >= 0) {
00753 SOLD("ACCEPT perhaps?");
00754 if (ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) {
00755 struct T_conn_ind ind;
00756 char *buf = getpage();
00757 int len = BUF_SIZE;
00758
00759 SOLD("trying ACCEPT");
00760 if (put_user(ctl_maxlen - sizeof(ind), ctl_len))
00761 return -EFAULT;
00762 args[0] = fd;
00763 args[1] = (long)buf;
00764 args[2] = (long)&len;
00765 oldflags = filp->f_flags;
00766 filp->f_flags |= O_NONBLOCK;
00767 SOLD("calling ACCEPT");
00768 set_fs(KERNEL_DS);
00769 error = sys_socketcall(SYS_ACCEPT, args);
00770 set_fs(old_fs);
00771 filp->f_flags = oldflags;
00772 if (error < 0) {
00773 SOLD("some error");
00774 putpage(buf);
00775 return error;
00776 }
00777 if (error) {
00778 SOLD("connect");
00779 putpage(buf);
00780 if (sizeof(ind) > ctl_maxlen) {
00781 SOLD("generating CONN_IND");
00782 ind.PRIM_type = T_CONN_IND;
00783 ind.SRC_length = len;
00784 ind.SRC_offset = sizeof(ind);
00785 ind.OPT_length = ind.OPT_offset = 0;
00786 ind.SEQ_number = error;
00787 if(copy_to_user(ctl_buf, &ind, sizeof(ind))||
00788 put_user(sizeof(ind)+ind.SRC_length,ctl_len))
00789 return -EFAULT;
00790 SOLD("CONN_IND created");
00791 }
00792 if (data_maxlen >= 0)
00793 put_user(0, data_len);
00794 SOLD("CONN_IND done");
00795 return 0;
00796 }
00797 if (len>ctl_maxlen) {
00798 SOLD("data don't fit");
00799 putpage(buf);
00800 return -EFAULT;
00801 }
00802 if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){
00803 SOLD("can't copy data");
00804 putpage(buf);
00805 return -EFAULT;
00806 }
00807 SOLD("ACCEPT done");
00808 putpage(buf);
00809 }
00810 }
00811 SOLD("checking data req");
00812 if (data_maxlen <= 0) {
00813 if (data_maxlen == 0)
00814 put_user(0, data_len);
00815 if (ctl_maxlen >= 0)
00816 put_user(0, ctl_len);
00817 return -EAGAIN;
00818 }
00819 SOLD("wants data");
00820 if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
00821 SOLD("udi fits");
00822 tmpbuf = ctl_buf + sizeof(udi);
00823 tmplen = ctl_maxlen - sizeof(udi);
00824 } else {
00825 SOLD("udi does not fit");
00826 tmpbuf = NULL;
00827 tmplen = 0;
00828 }
00829 if (put_user(tmplen, ctl_len))
00830 return -EFAULT;
00831 SOLD("set ctl_len");
00832 oldflags = filp->f_flags;
00833 filp->f_flags |= O_NONBLOCK;
00834 SOLD("calling recvfrom");
00835 sys_recvfrom = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom);
00836 error = sys_recvfrom(fd, data_buf, min(0,data_maxlen), 0, (struct sockaddr*)tmpbuf, ctl_len);
00837 filp->f_flags = oldflags;
00838 if (error < 0)
00839 return error;
00840 SOLD("error >= 0" ) ;
00841 if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) {
00842 SOLD("generating udi");
00843 udi.PRIM_type = T_UNITDATA_IND;
00844 get_user(udi.SRC_length, ctl_len);
00845 udi.SRC_offset = sizeof(udi);
00846 udi.OPT_length = udi.OPT_offset = 0;
00847 copy_to_user(ctl_buf, &udi, sizeof(udi));
00848 put_user(sizeof(udi)+udi.SRC_length, ctl_len);
00849 SOLD("udi done");
00850 } else
00851 put_user(0, ctl_len);
00852 put_user(error, data_len);
00853 SOLD("done");
00854 return 0;
00855 }
00856
00857 asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
00858 {
00859 struct file *filp;
00860 struct inode *ino;
00861 struct strbuf *ctlptr, *datptr;
00862 struct strbuf ctl, dat;
00863 int *flgptr;
00864 int flags;
00865 int error = -EBADF;
00866
00867 SOLD("entry");
00868 lock_kernel();
00869 if(fd >= NR_OPEN) goto out;
00870
00871 filp = current->files->fd[fd];
00872 if(!filp) goto out;
00873
00874 ino = filp->f_dentry->d_inode;
00875 if (!ino) goto out;
00876
00877 if (!ino->i_sock)
00878 goto out;
00879
00880 ctlptr = (struct strbuf *)A(arg1);
00881 datptr = (struct strbuf *)A(arg2);
00882 flgptr = (int *)A(arg3);
00883
00884 error = -EFAULT;
00885
00886 if (ctlptr) {
00887 if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) ||
00888 put_user(-1,&ctlptr->len))
00889 goto out;
00890 } else
00891 ctl.maxlen = -1;
00892
00893 if (datptr) {
00894 if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) ||
00895 put_user(-1,&datptr->len))
00896 goto out;
00897 } else
00898 dat.maxlen = -1;
00899
00900 if (get_user(flags,flgptr))
00901 goto out;
00902
00903 switch (flags) {
00904 case 0:
00905 case MSG_HIPRI:
00906 case MSG_ANY:
00907 case MSG_BAND:
00908 break;
00909 default:
00910 error = -EINVAL;
00911 goto out;
00912 }
00913
00914 error = timod_getmsg(fd,(char*)A(ctl.buf),ctl.maxlen,&ctlptr->len,
00915 (char*)A(dat.buf),dat.maxlen,&datptr->len,&flags);
00916
00917 if (!error && put_user(flags,flgptr))
00918 error = -EFAULT;
00919 out:
00920 unlock_kernel();
00921 SOLD("done");
00922 return error;
00923 }
00924
00925 asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
00926 {
00927 struct file *filp;
00928 struct inode *ino;
00929 struct strbuf *ctlptr, *datptr;
00930 struct strbuf ctl, dat;
00931 int flags = (int) arg3;
00932 int error = -EBADF;
00933
00934 SOLD("entry");
00935 lock_kernel();
00936 if(fd >= NR_OPEN) goto out;
00937
00938 filp = current->files->fd[fd];
00939 if(!filp) goto out;
00940
00941 ino = filp->f_dentry->d_inode;
00942 if (!ino) goto out;
00943
00944 if (!ino->i_sock &&
00945 (MAJOR(ino->i_rdev) != 30 || MINOR(ino->i_rdev) != 1))
00946 goto out;
00947
00948 ctlptr = (struct strbuf *)A(arg1);
00949 datptr = (struct strbuf *)A(arg2);
00950
00951 error = -EFAULT;
00952
00953 if (ctlptr) {
00954 if (copy_from_user(&ctl,ctlptr,sizeof(ctl)))
00955 goto out;
00956 if (ctl.len < 0 && flags) {
00957 error = -EINVAL;
00958 goto out;
00959 }
00960 } else {
00961 ctl.len = 0;
00962 ctl.buf = 0;
00963 }
00964
00965 if (datptr) {
00966 if (copy_from_user(&dat,datptr,sizeof(dat)))
00967 goto out;
00968 } else {
00969 dat.len = 0;
00970 dat.buf = 0;
00971 }
00972
00973 error = timod_putmsg(fd,(char*)A(ctl.buf),ctl.len,
00974 (char*)A(dat.buf),dat.len,flags);
00975 out:
00976 unlock_kernel();
00977 SOLD("done");
00978 return error;
00979 }