asmlinkage long sys_oabi_socketcall(int call, unsigned long __user *args) { unsigned long r = -EFAULT, a[6]; switch (call) { case SYS_BIND: if (copy_from_user(a, args, 3 * sizeof(long)) == 0) r = sys_oabi_bind(a[0], (struct sockaddr __user *)a[1], a[2]); break; case SYS_CONNECT: if (copy_from_user(a, args, 3 * sizeof(long)) == 0) r = sys_oabi_connect(a[0], (struct sockaddr __user *)a[1], a[2]); break; case SYS_SENDTO: if (copy_from_user(a, args, 6 * sizeof(long)) == 0) r = sys_oabi_sendto(a[0], (void __user *)a[1], a[2], a[3], (struct sockaddr __user *)a[4], a[5]); break; case SYS_SENDMSG: if (copy_from_user(a, args, 3 * sizeof(long)) == 0) r = sys_oabi_sendmsg(a[0], (struct user_msghdr __user *)a[1], a[2]); break; default: r = sys_socketcall(call, args); } return r; }
int abi_do_setsockopt(unsigned long *sp) { int error; int level, optname; error = verify_area(VERIFY_READ, ((unsigned long *)sp), 5*sizeof(long)); if (error) return error; get_user(level, ((unsigned long *)sp)+1); get_user(optname, ((unsigned long *)sp)+2); if (abi_traced(ABI_TRACE_STREAMS|ABI_TRACE_SOCKSYS)) { u_long optval, optlen; get_user(optval, ((u_long *)sp) + 3); get_user(optlen, ((u_long *)sp) + 4); __abi_trace("setsockopt level=%d, optname=%d, " "optval=0x%08lx, optlen=0x%08lx\n", level, optname, optval, optlen); } switch (level) { case 0: /* IPPROTO_IP aka SOL_IP */ /* This is correct for the SCO family. Hopefully * it is correct for other SYSV... */ optname--; if (optname == 0) optname = 4; if (optname > 4) { optname += 24; if (optname <= 33) optname--; if (optname < 32 || optname > 36) return -EINVAL; } put_user(optname, ((unsigned long *)sp)+2); break; case 0xffff: put_user(SOL_SOCKET, ((unsigned long *)sp)+1); optname = map_value(current->exec_domain->sockopt_map, optname, 0); put_user(optname, ((unsigned long *)sp)+2); switch (optname) { case SO_LINGER: { unsigned long optlen; /* SO_LINGER takes a struct linger * as the argument but some code * uses an int and expects to get * away without an error. Sigh... */ get_user(optlen, ((unsigned long *)sp)+4); if (optlen == sizeof(int)) return 0; break; } /* The following are not currently implemented * under Linux so we must fake them in * reasonable ways. (Only SO_PROTOTYPE is * documented in SCO's man page). */ case SO_PROTOTYPE: case SO_ORDREL: case SO_SNDTIMEO: case SO_RCVTIMEO: return -ENOPROTOOPT; case SO_USELOOPBACK: case SO_SNDLOWAT: case SO_RCVLOWAT: return 0; /* The following are not currenty implemented * under Linux and probably aren't settable * anyway. */ case SO_IMASOCKET: return -ENOPROTOOPT; } default: /* FIXME: We assume everything else uses the * same level and option numbers. This is true * for IPPROTO_TCP(/SOL_TCP) and TCP_NDELAY * but is known to be incorrect for other * potential options :-(. */ break; } return sys_socketcall(SYS_SETSOCKOPT, sp); }
static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg) { switch (cmd & 0xff) { case 12: /* SIOCSIFADDR */ return compat_sys_ioctl(fd, SIOCSIFADDR, arg); case 13: /* SIOCGIFADDR */ return compat_sys_ioctl(fd, SIOCGIFADDR, arg); case 14: /* SIOCSIFDSTADDR */ return compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg); case 15: /* SIOCGIFDSTADDR */ return compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg); case 16: /* SIOCSIFFLAGS */ return compat_sys_ioctl(fd, SIOCSIFFLAGS, arg); case 17: /* SIOCGIFFLAGS */ return compat_sys_ioctl(fd, SIOCGIFFLAGS, arg); case 18: /* SIOCSIFMEM */ return compat_sys_ioctl(fd, SIOCSIFMEM, arg); case 19: /* SIOCGIFMEM */ return compat_sys_ioctl(fd, SIOCGIFMEM, arg); case 20: /* SIOCGIFCONF */ return compat_sys_ioctl(fd, SIOCGIFCONF, arg); case 21: /* SIOCSIFMTU */ return compat_sys_ioctl(fd, SIOCSIFMTU, arg); case 22: /* SIOCGIFMTU */ return compat_sys_ioctl(fd, SIOCGIFMTU, arg); case 23: /* SIOCGIFBRDADDR */ return compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg); case 24: /* SIOCSIFBRDADDR */ return compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg); case 25: /* SIOCGIFNETMASK */ return compat_sys_ioctl(fd, SIOCGIFNETMASK, arg); case 26: /* SIOCSIFNETMASK */ return compat_sys_ioctl(fd, SIOCSIFNETMASK, arg); case 27: /* SIOCGIFMETRIC */ return compat_sys_ioctl(fd, SIOCGIFMETRIC, arg); case 28: /* SIOCSIFMETRIC */ return compat_sys_ioctl(fd, SIOCSIFMETRIC, arg); case 30: /* SIOCSARP */ return compat_sys_ioctl(fd, SIOCSARP, arg); case 31: /* SIOCGARP */ return compat_sys_ioctl(fd, SIOCGARP, arg); case 32: /* SIOCDARP */ return compat_sys_ioctl(fd, SIOCDARP, arg); case 52: /* SIOCGETNAME */ case 53: /* SIOCGETPEER */ { struct sockaddr uaddr; int uaddr_len = sizeof(struct sockaddr), ret; long args[3]; mm_segment_t old_fs = get_fs(); int (*sys_socketcall)(int, unsigned long *) = (int (*)(int, unsigned long *))SYS(socketcall); args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len; set_fs(KERNEL_DS); ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME, args); set_fs(old_fs); if (ret >= 0) { if (copy_to_user((char *)A(arg), &uaddr, uaddr_len)) return -EFAULT; } return ret; } #if 0 case 86: /* SIOCSOCKSYS */ return socksys_syscall(fd, arg); #endif case 87: /* SIOCGIFNUM */ { struct net_device *d; int i = 0; read_lock_bh(&dev_base_lock); for (d = dev_base; d; d = d->next) i++; read_unlock_bh(&dev_base_lock); if (put_user (i, (int *)A(arg))) return -EFAULT; return 0; } } return -ENOSYS; }
int 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) { int error; int oldflags; struct file *filp; struct inode *ino; struct sol_socket_struct *sock; struct T_unitdata_ind udi; mm_segment_t old_fs = get_fs(); long args[6]; char *tmpbuf; int tmplen; int (*sys_socketcall)(int, unsigned long *) = (int (*)(int, unsigned long *))SYS(socketcall); int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *); SOLD("entry"); 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)); filp = current->files->fd[fd]; ino = filp->f_dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL)); if ( ctl_maxlen > 0 && !sock->pfirst && ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) { SOLD("calling LISTEN"); args[0] = fd; args[1] = -1; set_fs(KERNEL_DS); sys_socketcall(SYS_LISTEN, args); set_fs(old_fs); SOLD("LISTEN done"); } if (!(filp->f_flags & O_NONBLOCK)) { poll_table wait_table, *wait; poll_initwait(&wait_table); wait = &wait_table; for(;;) { SOLD("loop"); set_current_state(TASK_INTERRUPTIBLE); /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */ /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */ /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */ if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI)) break; SOLD("cond 1 passed"); if ( #if 1 *flags_p != MSG_HIPRI && #endif ((filp->f_op->poll(filp, wait) & POLLIN) || (filp->f_op->poll(filp, NULL) & POLLIN) || signal_pending(current)) ) { break; } if( *flags_p == MSG_HIPRI ) { SOLD("avoiding lockup"); break ; } if(wait_table.error) { SOLD("wait-table error"); poll_freewait(&wait_table); return wait_table.error; } SOLD("scheduling"); schedule(); } SOLD("loop done"); current->state = TASK_RUNNING; poll_freewait(&wait_table); if (signal_pending(current)) { SOLD("signal pending"); return -EINTR; } } if (ctl_maxlen >= 0 && sock->pfirst) { struct T_primsg *it = sock->pfirst; int l = min_t(int, ctl_maxlen, it->length); SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC); SOLD("purting ctl data"); if(copy_to_user(ctl_buf, (char*)&it->type + sock->offset, l)) return -EFAULT; SOLD("pur it"); if(put_user(l, ctl_len)) return -EFAULT; SOLD("set ctl_len"); *flags_p = it->pri; it->length -= l; if (it->length) { SOLD("more ctl"); sock->offset += l; return MORECTL; } else { SOLD("removing message"); sock->pfirst = it->next; if (!sock->pfirst) sock->plast = NULL; SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst)); mykfree(it); sock->offset = 0; SOLD("ctl done"); return 0; } } *flags_p = 0; if (ctl_maxlen >= 0) { SOLD("ACCEPT perhaps?"); if (ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) { struct T_conn_ind ind; char *buf = getpage(); int len = BUF_SIZE; SOLD("trying ACCEPT"); if (put_user(ctl_maxlen - sizeof(ind), ctl_len)) return -EFAULT; args[0] = fd; args[1] = (long)buf; args[2] = (long)&len; oldflags = filp->f_flags; filp->f_flags |= O_NONBLOCK; SOLD("calling ACCEPT"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_ACCEPT, args); set_fs(old_fs); filp->f_flags = oldflags; if (error < 0) { SOLD("some error"); putpage(buf); return error; } if (error) { SOLD("connect"); putpage(buf); if (sizeof(ind) > ctl_maxlen) { SOLD("generating CONN_IND"); ind.PRIM_type = T_CONN_IND; ind.SRC_length = len; ind.SRC_offset = sizeof(ind); ind.OPT_length = ind.OPT_offset = 0; ind.SEQ_number = error; if(copy_to_user(ctl_buf, &ind, sizeof(ind))|| put_user(sizeof(ind)+ind.SRC_length,ctl_len)) return -EFAULT; SOLD("CONN_IND created"); } if (data_maxlen >= 0) put_user(0, data_len); SOLD("CONN_IND done"); return 0; } if (len>ctl_maxlen) { SOLD("data don't fit"); putpage(buf); return -EFAULT; /* XXX - is this ok ? */ } if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){ SOLD("can't copy data"); putpage(buf); return -EFAULT; } SOLD("ACCEPT done"); putpage(buf); } } SOLD("checking data req"); if (data_maxlen <= 0) { if (data_maxlen == 0) put_user(0, data_len); if (ctl_maxlen >= 0) put_user(0, ctl_len); return -EAGAIN; } SOLD("wants data"); if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) { SOLD("udi fits"); tmpbuf = ctl_buf + sizeof(udi); tmplen = ctl_maxlen - sizeof(udi); } else { SOLD("udi does not fit"); tmpbuf = NULL; tmplen = 0; } if (put_user(tmplen, ctl_len)) return -EFAULT; SOLD("set ctl_len"); oldflags = filp->f_flags; filp->f_flags |= O_NONBLOCK; SOLD("calling recvfrom"); sys_recvfrom = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom); error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr*)tmpbuf, ctl_len); filp->f_flags = oldflags; if (error < 0) return error; SOLD("error >= 0" ) ; if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) { SOLD("generating udi"); udi.PRIM_type = T_UNITDATA_IND; get_user(udi.SRC_length, ctl_len); udi.SRC_offset = sizeof(udi); udi.OPT_length = udi.OPT_offset = 0; copy_to_user(ctl_buf, &udi, sizeof(udi)); put_user(sizeof(udi)+udi.SRC_length, ctl_len); SOLD("udi done"); } else put_user(0, ctl_len); put_user(error, data_len); SOLD("done"); return 0; }
static int timod_optmgmt(unsigned int fd, int flag, char *opt_buf, int opt_len, int do_ret) { int error, failed; int ret_space, ret_len; long args[5]; char *ret_pos,*ret_buf; int (*sys_socketcall)(int, unsigned long *) = (int (*)(int, unsigned long *))SYS(socketcall); mm_segment_t old_fs = get_fs(); SOLD("entry"); SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret)); if (!do_ret && (!opt_buf || opt_len <= 0)) return 0; SOLD("getting page"); ret_pos = ret_buf = getpage(); ret_space = BUF_SIZE; ret_len = 0; error = failed = 0; SOLD("looping"); while(opt_len >= sizeof(struct opthdr)) { struct opthdr *opt; int orig_opt_len; SOLD("loop start"); opt = (struct opthdr *)ret_pos; if (ret_space < sizeof(struct opthdr)) { failed = TSYSERR; break; } SOLD("getting opthdr"); if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) || opt->len > opt_len) { failed = TBADOPT; break; } SOLD("got opthdr"); if (flag == T_NEGOTIATE) { char *buf; SOLD("handling T_NEGOTIATE"); buf = ret_pos + sizeof(struct opthdr); if (ret_space < opt->len + sizeof(struct opthdr) || copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) { failed = TSYSERR; break; } SOLD("got optdata"); args[0] = fd; args[1] = opt->level; args[2] = opt->name; args[3] = (long)buf; args[4] = opt->len; SOLD("calling SETSOCKOPT"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_SETSOCKOPT, args); set_fs(old_fs); if (error) { failed = TBADOPT; break; } SOLD("SETSOCKOPT ok"); } orig_opt_len = opt->len; opt->len = ret_space - sizeof(struct opthdr); if (opt->len < 0) { failed = TSYSERR; break; } args[0] = fd; args[1] = opt->level; args[2] = opt->name; args[3] = (long)(ret_pos+sizeof(struct opthdr)); args[4] = (long)&opt->len; SOLD("calling GETSOCKOPT"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_GETSOCKOPT, args); set_fs(old_fs);; if (error) { failed = TBADOPT; break; } SOLD("GETSOCKOPT ok"); ret_space -= sizeof(struct opthdr) + opt->len; ret_len += sizeof(struct opthdr) + opt->len; ret_pos += sizeof(struct opthdr) + opt->len; opt_len -= sizeof(struct opthdr) + orig_opt_len; opt_buf += sizeof(struct opthdr) + orig_opt_len; SOLD("loop end"); } SOLD("loop done"); if (do_ret) { SOLD("generating ret msg"); if (failed) timod_error(fd, T_OPTMGMT_REQ, failed, -error); else { struct T_primsg *it; it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len); if (it) { struct T_optmgmt_ack *ack = (struct T_optmgmt_ack *)&it->type; SOLD("got primsg"); ack->PRIM_type = T_OPTMGMT_ACK; ack->OPT_length = ret_len; ack->OPT_offset = sizeof(struct T_optmgmt_ack); ack->MGMT_flags = (failed ? T_FAILURE : flag); memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack), ret_buf, ret_len); timod_queue(fd, it); } } } SOLDD(("put_page %p\n", ret_buf)); putpage(ret_buf); SOLD("done"); return 0; }
int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len, char *data_buf, int data_len, int flags) { int ret, error, terror; char *buf; struct file *filp; struct inode *ino; struct sol_socket_struct *sock; mm_segment_t old_fs = get_fs(); long args[6]; int (*sys_socketcall)(int, unsigned long *) = (int (*)(int, unsigned long *))SYS(socketcall); int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int) = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int))SYS(sendto); filp = current->files->fd[fd]; ino = filp->f_dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLD("entry"); if (get_user(ret, (int *)A(ctl_buf))) return -EFAULT; switch (ret) { case T_BIND_REQ: { struct T_bind_req req; SOLDD(("bind %016lx(%016lx)\n", sock, filp)); SOLD("T_BIND_REQ"); if (sock->state != TS_UNBND) { timod_error(fd, T_BIND_REQ, TOUTSTATE, 0); return 0; } SOLD("state ok"); if (copy_from_user(&req, ctl_buf, sizeof(req))) { timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); return 0; } SOLD("got ctl req"); if (req.ADDR_offset && req.ADDR_length) { if (req.ADDR_length > BUF_SIZE) { timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); return 0; } SOLD("req size ok"); buf = getpage(); if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) { timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); putpage(buf); return 0; } SOLD("got ctl data"); args[0] = fd; args[1] = (long)buf; args[2] = req.ADDR_length; SOLD("calling BIND"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_BIND, args); set_fs(old_fs); putpage(buf); SOLD("BIND returned"); } else error = 0; if (!error) { struct T_primsg *it; if (req.CONIND_number) { args[0] = fd; args[1] = req.CONIND_number; SOLD("calling LISTEN"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_LISTEN, args); set_fs(old_fs); SOLD("LISTEN done"); } it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr)); if (it) { struct T_bind_ack *ack; ack = (struct T_bind_ack *)&it->type; ack->PRIM_type = T_BIND_ACK; ack->ADDR_offset = sizeof(*ack); ack->ADDR_length = sizeof(struct sockaddr); ack->CONIND_number = req.CONIND_number; args[0] = fd; args[1] = (long)(ack+sizeof(*ack)); args[2] = (long)&ack->ADDR_length; set_fs(KERNEL_DS); sys_socketcall(SYS_GETSOCKNAME,args); set_fs(old_fs); sock->state = TS_IDLE; timod_ok(fd, T_BIND_REQ); timod_queue_end(fd, it); SOLD("BIND done"); return 0; } } SOLD("some error"); switch (error) { case -EINVAL: terror = TOUTSTATE; error = 0; break; case -EACCES: terror = TACCES; error = 0; break; case -EADDRNOTAVAIL: case -EADDRINUSE: terror = TNOADDR; error = 0; break; default: terror = TSYSERR; break; } timod_error(fd, T_BIND_REQ, terror, -error); SOLD("BIND done"); return 0; } case T_CONN_REQ: { struct T_conn_req req; unsigned short oldflags; struct T_primsg *it; SOLD("T_CONN_REQ"); if (sock->state != TS_UNBND && sock->state != TS_IDLE) { timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); return 0; } SOLD("state ok"); if (copy_from_user(&req, ctl_buf, sizeof(req))) { timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); return 0; } SOLD("got ctl req"); if (ctl_len > BUF_SIZE) { timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); return 0; } SOLD("req size ok"); buf = getpage(); if (copy_from_user(buf, ctl_buf, ctl_len)) { timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); putpage(buf); return 0; } #ifdef DEBUG_SOLARIS { char * ptr = buf; int len = ctl_len; printk("returned data (%d bytes): ",len); while( len-- ) { if (!(len & 7)) printk(" "); printk("%02x",(unsigned char)*ptr++); } printk("\n"); } #endif SOLD("got ctl data"); args[0] = fd; args[1] = (long)buf+req.DEST_offset; args[2] = req.DEST_length; oldflags = filp->f_flags; filp->f_flags &= ~O_NONBLOCK; SOLD("calling CONNECT"); set_fs(KERNEL_DS); error = sys_socketcall(SYS_CONNECT, args); set_fs(old_fs); filp->f_flags = oldflags; SOLD("CONNECT done"); if (!error) { struct T_conn_con *con; SOLD("no error"); it = timod_mkctl(ctl_len); if (!it) { putpage(buf); return -ENOMEM; } con = (struct T_conn_con *)&it->type; #ifdef DEBUG_SOLARIS { char * ptr = buf; int len = ctl_len; printk("returned data (%d bytes): ",len); while( len-- ) { if (!(len & 7)) printk(" "); printk("%02x",(unsigned char)*ptr++); } printk("\n"); } #endif memcpy(con, buf, ctl_len); SOLD("copied ctl_buf"); con->PRIM_type = T_CONN_CON; sock->state = TS_DATA_XFER; } else { struct T_discon_ind *dis; SOLD("some error"); it = timod_mkctl(sizeof(*dis)); if (!it) { putpage(buf); return -ENOMEM; } SOLD("got primsg"); dis = (struct T_discon_ind *)&it->type; dis->PRIM_type = T_DISCON_IND; dis->DISCON_reason = -error; /* FIXME: convert this as in iABI_errors() */ dis->SEQ_number = 0; } putpage(buf); timod_ok(fd, T_CONN_REQ); it->pri = 0; timod_queue_end(fd, it); SOLD("CONNECT done"); return 0; } case T_OPTMGMT_REQ: { struct T_optmgmt_req req; SOLD("OPTMGMT_REQ"); if (copy_from_user(&req, ctl_buf, sizeof(req))) return -EFAULT; SOLD("got req"); return timod_optmgmt(fd, req.MGMT_flags, req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL, req.OPT_length, 1); } case T_UNITDATA_REQ: { struct T_unitdata_req req; int err; SOLD("T_UNITDATA_REQ"); if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) { timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); return 0; } SOLD("state ok"); if (copy_from_user(&req, ctl_buf, sizeof(req))) { timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); return 0; } SOLD("got ctl req"); #ifdef DEBUG_SOLARIS { char * ptr = ctl_buf+req.DEST_offset; int len = req.DEST_length; printk("socket address (%d bytes): ",len); while( len-- ) { char c; if (get_user(c,ptr)) printk("??"); else printk("%02x",(unsigned char)c); ptr++; } printk("\n"); } #endif err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr*)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length); if (err == data_len) return 0; if(err >= 0) { printk("timod: sendto failed to send all the data\n"); return 0; } timod_error(fd, T_CONN_REQ, TSYSERR, -err); return 0; } default: printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret); break; } return -EINVAL; }
long sys_bind(int sockfd, const struct sockaddr *addr, int addrlen) { uint32_t a[] = {(uint32_t)sockfd, (uint32_t)addr, (uint32_t)addrlen}; return sys_socketcall(SYS_BIND, (unsigned long *)a); }
long sys_getsockopt(int sockfd, int level, int optname, const void *optval, unsigned int *optlen) { uint32_t a[] = {(uint32_t)sockfd, (uint32_t)level, (uint32_t)optname, (uint32_t)optval, (uint32_t)optlen}; return sys_socketcall(SYS_GETSOCKOPT, (unsigned long *)a); }
long sys_recvmsg(int sockfd, struct msghdr *msg, int flags) { uint32_t a[] = {(uint32_t)sockfd, (uint32_t)msg, (uint32_t)flags}; return sys_socketcall(SYS_RECVMSG, (unsigned long *)a); }
long sys_shutdown(int sockfd, int how) { uint32_t a[] = {(uint32_t)sockfd, (uint32_t)how}; return sys_socketcall(SYS_SHUTDOWN, (unsigned long *)a); }
long sys_sendmsg(int sockfd, const struct msghdr *msg, int flags) { uint32_t a[] = {(uint32_t)sockfd, (uint32_t)msg, (uint32_t)flags}; return sys_socketcall(SYS_SENDMSG, (unsigned long *)a); }
long sys_recvfrom(int sockfd, void *ubuf, size_t size, unsigned int flags, struct sockaddr *addr, int *addr_len) { uint32_t a[] = {(uint32_t)sockfd, (uint32_t)ubuf, (uint32_t)size, (uint32_t)flags, (uint32_t)addr, (uint32_t)addr_len}; return sys_socketcall(SYS_RECVFROM, (unsigned long *)a); }
long sys_sendto(int sockfd, void *buff, size_t len, unsigned int flags, struct sockaddr *addr, int addr_len) { uint32_t a[] = {(uint32_t)sockfd, (uint32_t)buff, (uint32_t)len, (uint32_t)flags, (uint32_t)addr, (uint32_t)addr_len}; return sys_socketcall(SYS_SENDTO, (unsigned long *)a); }
long sys_connect(int sockfd, struct sockaddr *addr, int addrlen) { uint32_t a[] = {(uint32_t)sockfd, (uint32_t)addr, (uint32_t)addrlen}; return sys_socketcall(SYS_CONNECT, (unsigned long *)a); }
long sys_socket(int domain, int type, int protocol) { uint32_t a[] = { (uint32_t)domain, (uint32_t)type, (uint32_t)protocol }; return sys_socketcall(SYS_SOCKET, (unsigned long *)a); }