ssize_t read_udp_socket(int fd,char *buf,size_t len) { ssize_t ret; struct sockaddr_in sock; socklen_t socklen = sizeof(sock); memset((char *)&sock,'\0',socklen); memset((char *)&lastip,'\0',sizeof(lastip)); ret = (ssize_t)sys_recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen); if (ret <= 0) { /* Don't print a low debug error for a non-blocking socket. */ if (errno == EAGAIN) { DEBUG(10,("read socket returned EAGAIN. ERRNO=%s\n",strerror(errno))); } else { DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno))); } return(0); } lastip = sock.sin_addr; lastport = ntohs(sock.sin_port); DEBUG(10,("read_udp_socket: lastip %s lastport %d read: %lu\n", inet_ntoa(lastip), lastport, (unsigned long)ret)); return(ret); }
/* * Receive data. */ PJ_DEF(pj_status_t) pj_sock_recvfrom( pj_sock_t sockfd, void *buff, pj_ssize_t *size, unsigned flags, pj_sockaddr_t *from, int *fromlen) { mm_segment_t oldfs; long err; PJ_CHECK_STACK(); oldfs = get_fs(); set_fs(KERNEL_DS); err = *size = sys_recvfrom( sockfd, buff, *size, flags, from, fromlen); set_fs(oldfs); if (err >= 0) { return PJ_SUCCESS; } else { return PJ_RETURN_OS_ERROR(-err); } }
asmlinkage int solaris_recv(int s, char *buf, int len, int flags) { int (*sys_recvfrom)(int, void *, size_t, unsigned, struct sockaddr *, int *) = (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(recvfrom); return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL); }
asmlinkage int solaris_recvfrom(int s, char __user *buf, int len, int flags, u32 from, u32 fromlen) { int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) = (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom); return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), A(from), A(fromlen)); }
static int ngctl_recvfrom(struct recvfrom_args *uap) { int error = sys_recvfrom(curthread, uap); if (error) { ff_os_errno(error); return (-1); } return curthread->td_retval[0]; }
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen){ static ssize_t (*sys_recvfrom)(int, void *, size_t, int, struct sockaddr *, socklen_t *) = NULL; if (!sys_recvfrom) { if (!(*(void **)(&sys_recvfrom) = dlsym(RTLD_NEXT,"recvfrom"))){ perror("cannot fetch system recvfrom\n"); exit(1); } } if (iniparser_getstring(ini, "recvfrom:allow", NULL)) return sys_recvfrom(sockfd, buf, len, flags, src_addr, addrlen); printf("Forbidden use of recvfrom\n"); return -1; }
int linux32_sys_recv(struct lwp *l, const struct linux32_sys_recv_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(netbsd32_voidp) buf; syscallarg(int) len; syscallarg(int) flags; } */ struct sys_recvfrom_args ua; NETBSD32TO64_UAP(s); NETBSD32TOP_UAP(buf, void); NETBSD32TO64_UAP(len); NETBSD32TO64_UAP(flags); SCARG(&ua, from) = NULL; SCARG(&ua, fromlenaddr) = NULL; return sys_recvfrom(l, &ua, retval); }
ssize_t read_udp_v4_socket(int fd, char *buf, size_t len, struct sockaddr_storage *psa) { ssize_t ret; socklen_t socklen = sizeof(*psa); struct sockaddr_in *si = (struct sockaddr_in *)psa; memset((char *)psa,'\0',socklen); ret = (ssize_t)sys_recvfrom(fd,buf,len,0, (struct sockaddr *)psa,&socklen); if (ret <= 0) { /* Don't print a low debug error for a non-blocking socket. */ if (errno == EAGAIN) { DEBUG(10,("read_udp_v4_socket: returned EAGAIN\n")); } else { DEBUG(2,("read_udp_v4_socket: failed. errno=%s\n", strerror(errno))); } return 0; } if (psa->ss_family != AF_INET) { DEBUG(2,("read_udp_v4_socket: invalid address family %d " "(not IPv4)\n", (int)psa->ss_family)); return 0; } DEBUG(10,("read_udp_v4_socket: ip %s port %d read: %lu\n", inet_ntoa(si->sin_addr), si->sin_port, (unsigned long)ret)); return ret; }
asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len, unsigned int flags, struct sockaddr __user *addr, int __user *addrlen) { return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen); }
asmlinkage long compat_sys_socketcall(int call, u32 __user *args) { int ret; u32 a[6]; u32 a0, a1; if (call < SYS_SOCKET || call > SYS_RECVMSG) return -EINVAL; if (copy_from_user(a, args, nas[call])) return -EFAULT; a0 = a[0]; a1 = a[1]; switch(call) { case SYS_SOCKET: ret = sys_socket(a0, a1, a[2]); break; case SYS_BIND: ret = sys_bind(a0, compat_ptr(a1), a[2]); break; case SYS_CONNECT: ret = sys_connect(a0, compat_ptr(a1), a[2]); break; case SYS_LISTEN: ret = sys_listen(a0, a1); break; case SYS_ACCEPT: ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2])); break; case SYS_GETSOCKNAME: ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2])); break; case SYS_GETPEERNAME: ret = sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2])); break; case SYS_SOCKETPAIR: ret = sys_socketpair(a0, a1, a[2], compat_ptr(a[3])); break; case SYS_SEND: ret = sys_send(a0, compat_ptr(a1), a[2], a[3]); break; case SYS_SENDTO: ret = sys_sendto(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), a[5]); break; case SYS_RECV: ret = sys_recv(a0, compat_ptr(a1), a[2], a[3]); break; case SYS_RECVFROM: ret = sys_recvfrom(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), compat_ptr(a[5])); break; case SYS_SHUTDOWN: ret = sys_shutdown(a0,a1); break; case SYS_SETSOCKOPT: ret = compat_sys_setsockopt(a0, a1, a[2], compat_ptr(a[3]), a[4]); break; case SYS_GETSOCKOPT: ret = compat_sys_getsockopt(a0, a1, a[2], compat_ptr(a[3]), compat_ptr(a[4])); break; case SYS_SENDMSG: ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]); break; case SYS_RECVMSG: ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); break; default: ret = -EINVAL; break; } return ret; }
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; }
DEFINE_SYSCALL(socketcall, int, call, uintptr_t *, args) { if (call < 1 || call > SYS_SENDMMSG) return -L_EINVAL; if (!mm_check_read(args, nargs[call])) return -L_EFAULT; switch (call) { case SYS_SOCKET: return sys_socket(args[0], args[1], args[2]); case SYS_BIND: return sys_bind(args[0], (const struct sockaddr *)args[1], args[2]); case SYS_CONNECT: return sys_connect(args[0], (const struct sockaddr *)args[1], args[2]); case SYS_LISTEN: return sys_listen(args[0], args[1]); case SYS_ACCEPT: return sys_accept(args[0], (struct sockaddr *)args[1], (int *)args[2]); case SYS_GETSOCKNAME: return sys_getsockname(args[0], (struct sockaddr *)args[1], (int *)args[2]); case SYS_GETPEERNAME: return sys_getpeername(args[0], (struct sockaddr *)args[1], (int *)args[2]); case SYS_SEND: return sys_send(args[0], (const void *)args[1], args[2], args[3]); case SYS_RECV: return sys_recv(args[0], (void *)args[1], args[2], args[3]); case SYS_SENDTO: return sys_sendto(args[0], (const void *)args[1], args[2], args[3], (const struct sockaddr *)args[4], args[5]); case SYS_RECVFROM: return sys_recvfrom(args[0], (void *)args[1], args[2], args[3], (struct sockaddr *)args[4], (int *)args[5]); case SYS_SHUTDOWN: return sys_shutdown(args[0], args[1]); case SYS_SETSOCKOPT: return sys_setsockopt(args[0], args[1], args[2], (const void *)args[3], args[4]); case SYS_GETSOCKOPT: return sys_getsockopt(args[0], args[1], args[2], (void *)args[3], (int *)args[4]); case SYS_SENDMSG: return sys_sendmsg(args[0], (const struct msghdr *)args[1], args[2]); case SYS_RECVMSG: return sys_recvmsg(args[0], (struct msghdr *)args[1], args[2]); case SYS_ACCEPT4: return sys_accept4(args[0], (struct sockaddr *)args[1], (int *)args[2], args[3]); case SYS_SENDMMSG: return sys_sendmmsg(args[0], (struct mmsghdr *)args[1], args[2], args[3]); default: { log_error("Unimplemented socketcall: %d", call); return -L_EINVAL; } } }
int so_socksys(struct socksysreq *req) { int err = -EINVAL; int cmd = req->args[0]; if ((1 << cmd) & ((1 << SO_ACCEPT) | (1 << SO_BIND) | (1 << SO_CONNECT) | (1 << SO_GETPEERNAME) | (1 << SO_GETSOCKNAME) | (1 << SO_GETSOCKOPT) | (1 << SO_LISTEN) | (1 << SO_RECV) | (1 << SO_RECVFROM) | (1 << SO_SEND) | (1 << SO_SENDTO) | (1 << SO_SETSOCKOPT) | (1 << SO_SHUTDOWN) | (1 << SO_RECVMSG) | (1 << SO_SENDMSG))) { int fd = req->args[1]; (void) fd; /* These are all socket related and accept a file (socket) descriptor as their first argument. In situations where we are incapable of providing back a real socket, we must here first distinguish if the file descriptor corresponds to a socket or a stream. */ #if 0 if (it_is_a_socket) { #endif /* In this case, we have a real socket from the operating system's perspective and we can simply pass the arguments to the appropriate system call. */ #if 0 switch (cmd) { case SO_ACCEPT: /* FIXME: 32/64 conversion */ err = sys_accept(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_BIND: /* FIXME: 32/64 conversion */ err = sys_bind(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_CONNECT: /* FIXME: 32/64 conversion */ err = sys_connect(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_GETPEERNAME: /* FIXME: 32/64 conversion */ err = sys_getpeername(fd, (struct sockaddr *) req->args[2], (int *) req->args[3]); break; case SO_GETSOCKNAME: /* FIXME: 32/64 conversion */ err = sys_getsockname(fd, (struct sockaddr *) req->args[2], (int *) req->args[3]); break; case SO_GETSOCKOPT: /* FIXME: 32/64 conversion */ err = sys_getsockopt(fd, req->args[2], req->args[3], (char *) req->args[4], (int *) req->args[5]); break; case SO_LISTEN: /* FIXME: 32/64 conversion */ err = sys_listen(fd, req->args[2]); break; case SO_RECV: /* FIXME: 32/64 conversion */ err = sys_recv(fd, (void *) req->args[2], req->args[3], req->args[4]); break; case SO_RECVFROM: /* FIXME: 32/64 conversion */ err = sys_recvfrom(fd, (void *) req->args[2], req->args[3], req->args[4], (struct sockaddr *) req->args[5], (int *) req->args[6]); break; case SO_SEND: /* FIXME: 32/64 conversion */ err = sys_send(fd, (void *) req->args[2], req->args[3], req->args[4]); break; case SO_SENDTO: /* FIXME: 32/64 conversion */ err = sys_sendto(fd, (void *) req->args[2], req->args[3], req->args[4], (struct sockaddr *) req->args[5], req->args[6]); break; case SO_SETSOCKOPT: /* FIXME: 32/64 conversion */ err = sys_setsockopt(fd, req->args[2], req->args[3], (char *) req->args[4], req->args[5]); break; case SO_SHUTDOWN: /* FIXME: 32/64 conversion */ err = sys_shutdown(fd, req->args[2]); break; case SO_RECVMSG: /* FIXME: 32/64 conversion */ err = sys_recvmsg(fd, (struct msghdr *) req->args[2], req->args[3]); break; case SO_SENDMSG: /* FIXME: 32/64 conversion */ err = sys_sendmsg(fd, (struct msghdr *) req->args[2], req->args[3]); break; } #endif #if 0 } else { /* In this case, we do not have a real socket, but have a TPI stream from the operating system's perspective, and we will directly call the associated TPI routine. */ switch (cmd) { case SO_ACCEPT: /* FIXME: 32/64 conversion */ err = tpi_accept(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_BIND: /* FIXME: 32/64 conversion */ err = tpi_bind(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_CONNECT: /* FIXME: 32/64 conversion */ err = tpi_connect(fd, (struct sockaddr *) req->args[2], req->args[3]); break; case SO_GETPEERNAME: /* FIXME: 32/64 conversion */ err = tpi_getpeername(fd, (struct sockaddr *) req->args[2], (int *) req->args[3]); break; case SO_GETSOCKNAME: /* FIXME: 32/64 conversion */ err = tpi_getsockname(fd, (struct sockaddr *) req->args[2], (int *) req->args[3]); break; case SO_GETSOCKOPT: /* FIXME: 32/64 conversion */ err = tpi_getsockopt(fd, req->args[2], req->args[3], (char *) req->args[4], (int *) req->args[5]); break; case SO_LISTEN: /* FIXME: 32/64 conversion */ err = tpi_listen(fd, req->args[2]); break; case SO_RECV: /* FIXME: 32/64 conversion */ err = tpi_recv(fd, (void *) req->args[2], req->args[3], req->args[4]); break; case SO_RECVFROM: /* FIXME: 32/64 conversion */ err = tpi_recvfrom(fd, (void *) req->args[2], req->args[3], req->args[4], (struct sockaddr *) req->args[5], (int *) req->args[6]); break; case SO_SEND: /* FIXME: 32/64 conversion */ err = tpi_send(fd, (void *) req->args[2], req->args[3], req->args[4]); break; case SO_SENDTO: /* FIXME: 32/64 conversion */ err = tpi_sendto(fd, (void *) req->args[2], req->args[3], req->args[4], (struct sockaddr *) req->args[5], req->args[6]); break; case SO_SETSOCKOPT: /* FIXME: 32/64 conversion */ err = tpi_setsockopt(fd, req->args[2], req->args[3], (char *) req->args[4], req->args[5]); break; case SO_SHUTDOWN: /* FIXME: 32/64 conversion */ err = tpi_shutdown(fd, req->args[2]); break; case SO_RECVMSG: /* FIXME: 32/64 conversion */ err = tpi_recvmsg(fd, (struct msghdr *) req->args[2], req->args[3]); break; case SO_SENDMSG: /* FIXME: 32/64 conversion */ err = tpi_sendmsg(fd, (struct msghdr *) req->args[2], req->args[3]); break; } } #endif } if ((1 << cmd) & ((1 << SO_SOCKET) | (1 << SO_SOCKPAIR) | (1 << SO_SELECT) | (1 << SO_GETIPDOMAIN) | (1 << SO_SETIPDOMAIN) | (1 << SO_ADJTIME) | (1 << SO_SETREUID) | (1 << SO_SETREGID) | (1 << SO_GETTIME) | (1 << SO_SETTIME) | (1 << SO_GETITIMER) | (1 << SO_SETITIMER))) { /* These are BSD compatibiltiy functions and are how we create sockets in the first place. The BSD compatibility functions all have system calls in Linux, but we provide them for backward compatibility (to what!?). */ #if 0 switch (cmd) { case SO_SOCKET: /* FIXME: 32/64 conversion */ /* XXX: don't think so..., after checking for a stream */ err = sys_socket(req->args[1], req->args[2], req->args[3]); break; case SO_SOCKPAIR: /* FIXME: 32/64 conversion */ /* XXX: don't think so..., after checking for a stream */ err = sys_socketpair(req->args[1], req->args[2], req->args[3], (int *) req->args[4]); err = -EOPNOTSUPP; break; case SO_SELECT: /* FIXME: 32/64 conversion */ err = sys_select(req->args[1], (fd_set *) req->args[2], (fd_set *) req->args[3], (fd_set *) req->args[4], (struct timeval *) req->args[5]); break; case SO_GETIPDOMAIN: /* FIXME: 32/64 conversion */ todo(("Process SO_GETIPDOMAIN for compatibility.\n")); /* does not exist in Linux, need to use sys_newuname and copy the domainname portion */ err = -ENOSYS; break; case SO_SETIPDOMAIN: /* FIXME: 32/64 conversion */ err = sys_setdomainname((char *) req->args[1], req->args[2]); break; case SO_ADJTIME: /* FIXME: 32/64 conversion */ err = sys_admtimex((struct timex *) req->args[1]); break; case SO_SETREUID: /* FIXME: 32/64 conversion */ err = sys_setreuid(req->args[1], req->args[2]); break; case SO_SETREGID: /* FIXME: 32/64 conversion */ err = sys_setregid(req->args[1], req->args[2]); break; case SO_GETTIME: /* FIXME: 32/64 conversion */ err = sys_gettimeofday((struct timeval *) req->args[1], (struct timezone *) req->args[2]); break; case SO_SETTIME: /* FIXME: 32/64 conversion */ err = sys_settimeofday((struct timeval *) req->args[1], (struct timezone *) req->args[2]); break; case SO_GETITIMER: /* FIXME: 32/64 conversion */ err = sys_getitimer(req->args[1], (struct itimerval *) req->args[2]); break; case SO_SETITIMER: /* FIXME: 32/64 conversion */ err = sys_getitimer(req->args[1], (struct itimerval *) req->args[2], (struct itimerval *) req->args[3]); break; } #endif } return (err); }
COMPAT_SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, buf, compat_size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int __user *, addrlen) { return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen); }
/* * system call vectors. since i want to rewrite sockets as streams, we have * this level of indirection. not a lot of overhead, since more of the work is * done via read/write/select directly */ int sys_socketcall(int call, unsigned long *args) { switch (call) { case SYS_SOCKET: verify_area(args, 3 * sizeof(long)); return sock_socket(get_fs_long(args+0), get_fs_long(args+1), get_fs_long(args+2)); case SYS_BIND: verify_area(args, 3 * sizeof(long)); return sock_bind(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), get_fs_long(args+2)); case SYS_CONNECT: verify_area(args, 3 * sizeof(long)); return sock_connect(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), get_fs_long(args+2)); case SYS_LISTEN: verify_area(args, 2 * sizeof(long)); return sock_listen(get_fs_long(args+0), get_fs_long(args+1)); case SYS_ACCEPT: verify_area(args, 3 * sizeof(long)); return sock_accept(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), (int *)get_fs_long(args+2)); case SYS_GETSOCKNAME: verify_area(args, 3 * sizeof(long)); return sock_getsockname(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), (int *)get_fs_long(args+2)); case SYS_GETPEERNAME: verify_area(args, 3 * sizeof(long)); return sock_getpeername(get_fs_long(args+0), (struct sockaddr *)get_fs_long(args+1), (int *)get_fs_long(args+2)); case SYS_SOCKETPAIR: verify_area(args, 4 * sizeof(long)); return sock_socketpair(get_fs_long(args+0), get_fs_long(args+1), get_fs_long(args+2), (int *)get_fs_long(args+3)); case SYS_SEND: verify_area(args, 4 * sizeof (unsigned long)); return ( sys_send (get_fs_long(args+0), (void *)get_fs_long(args+1), get_fs_long(args+2), get_fs_long(args+3))); case SYS_SENDTO: verify_area(args, 6 * sizeof (unsigned long)); return ( sys_sendto (get_fs_long(args+0), (void *)get_fs_long(args+1), get_fs_long(args+2), get_fs_long(args+3), (struct sockaddr *)get_fs_long(args+4), get_fs_long(args+5))); case SYS_RECV: verify_area(args, 4 * sizeof (unsigned long)); return ( sys_recv (get_fs_long(args+0), (void *)get_fs_long(args+1), get_fs_long(args+2), get_fs_long(args+3))); case SYS_RECVFROM: verify_area(args, 6 * sizeof (unsigned long)); return ( sys_recvfrom (get_fs_long(args+0), (void *)get_fs_long(args+1), get_fs_long(args+2), get_fs_long(args+3), (struct sockaddr *)get_fs_long(args+4), (int *)get_fs_long(args+5))); case SYS_SHUTDOWN: verify_area (args, 2* sizeof (unsigned long)); return ( sys_shutdown (get_fs_long (args+0), get_fs_long (args+1))); case SYS_SETSOCKOPT: verify_area (args, 5*sizeof (unsigned long)); return (sys_setsockopt (get_fs_long (args+0), get_fs_long (args+1), get_fs_long (args+2), (char *)get_fs_long (args+3), get_fs_long (args+4))); case SYS_GETSOCKOPT: verify_area (args, 5*sizeof (unsigned long)); return (sys_getsockopt (get_fs_long (args+0), get_fs_long (args+1), get_fs_long (args+2), (char *)get_fs_long (args+3), (int *)get_fs_long (args+4))); default: return -EINVAL; } }
BOOL receive_local_message( char *buffer, int buffer_len, int timeout) { struct sockaddr_in from; socklen_t fromlen = sizeof(from); int32 msg_len = 0; fd_set fds; int selrtn = -1; FD_ZERO(&fds); smb_read_error = 0; /* * We need to check for kernel oplocks before going into the select * here, as the EINTR generated by the linux kernel oplock may have * already been eaten. JRA. */ if (koplocks && koplocks->msg_waiting(&fds)) { return koplocks->receive_message(&fds, buffer, buffer_len); } while (timeout > 0 && selrtn == -1) { struct timeval to; int maxfd = oplock_sock; time_t starttime = time(NULL); FD_ZERO(&fds); maxfd = setup_oplock_select_set(&fds); to.tv_sec = timeout / 1000; to.tv_usec = (timeout % 1000) * 1000; DEBUG(5,("receive_local_message: doing select with timeout of %d ms\n", timeout)); selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); if (selrtn == -1 && errno == EINTR) { /* could be a kernel oplock interrupt */ if (koplocks && koplocks->msg_waiting(&fds)) { return koplocks->receive_message(&fds, buffer, buffer_len); } /* * Linux 2.0.x seems to have a bug in that * it can return -1, EINTR with a timeout of zero. * Make sure we bail out here with a read timeout * if we got EINTR on a timeout of 1 or less. */ if (timeout <= 1) { smb_read_error = READ_TIMEOUT; return False; } /* Not a kernel interrupt - could be a SIGUSR1 message. We must restart. */ /* We need to decrement the timeout here. */ timeout -= ((time(NULL) - starttime)*1000); if (timeout < 0) timeout = 1; DEBUG(5,("receive_local_message: EINTR : new timeout %d ms\n", timeout)); continue; } /* Check if error */ if(selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ smb_read_error = READ_ERROR; return False; } /* Did we timeout ? */ if (selrtn == 0) { smb_read_error = READ_TIMEOUT; return False; } } if (koplocks && koplocks->msg_waiting(&fds)) { return koplocks->receive_message(&fds, buffer, buffer_len); } if (!FD_ISSET(oplock_sock, &fds)) return False; /* * From here down we deal with the smbd <--> smbd * oplock break protocol only. */ /* * Read a loopback udp message. */ msg_len = sys_recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen); if(msg_len < 0) { DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno))); return False; } /* Validate message length. */ if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) { DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", msg_len, buffer_len - OPBRK_CMD_HEADER_LEN)); return False; } /* Validate message from address (must be localhost). */ if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { DEBUG(0,("receive_local_message: invalid 'from' address \ (was %lx should be 127.0.0.1)\n", (long)from.sin_addr.s_addr)); return False; }