static int linux_bind(struct thread *td, struct linux_bind_args *args) { struct sockaddr *sa; int error; error = linux_getsockaddr(&sa, PTRIN(args->name), args->namelen); if (error) return (error); error = kern_bind(td, args->s, sa); free(sa, M_SONAME); if (error == EADDRNOTAVAIL && args->namelen != sizeof(struct sockaddr_in)) return (EINVAL); return (error); }
static int linux_connect(struct linux_connect_args *args, int *res) { struct thread *td = curthread; /* XXX */ struct proc *p = td->td_proc; struct linux_connect_args linux_args; struct sockaddr *sa; struct socket *so; struct file *fp; int error; KKASSERT(p); error = copyin(args, &linux_args, sizeof(linux_args)); if (error) return (error); error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen); if (error) return (error); error = kern_connect(linux_args.s, 0, sa); kfree(sa, M_SONAME); if (error != EISCONN) return (error); /* * Linux doesn't return EISCONN the first time it occurs, * when on a non-blocking socket. Instead it returns the * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. */ error = holdsock(p->p_fd, linux_args.s, &fp); if (error) return (error); error = EISCONN; if (fp->f_flag & FNONBLOCK) { so = (struct socket *)fp->f_data; if (so->so_emuldata == 0) error = so->so_error; so->so_emuldata = (void *)1; } fdrop(fp); return (error); }
static int linux_bind(struct linux_bind_args *args, int *res) { struct linux_bind_args linux_args; struct sockaddr *sa; int error; error = copyin(args, &linux_args, sizeof(linux_args)); if (error) return (error); error = linux_getsockaddr(&sa, linux_args.name, linux_args.namelen); if (error) return (error); error = kern_bind(linux_args.s, sa); kfree(sa, M_SONAME); return (error); }
int linux_connect(struct thread *td, struct linux_connect_args *args) { struct socket *so; struct sockaddr *sa; u_int fflag; int error; error = linux_getsockaddr(&sa, (struct osockaddr *)PTRIN(args->name), args->namelen); if (error) return (error); error = kern_connect(td, args->s, sa); free(sa, M_SONAME); if (error != EISCONN) return (error); /* * Linux doesn't return EISCONN the first time it occurs, * when on a non-blocking socket. Instead it returns the * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. * * XXXRW: Instead of using fgetsock(), check that it is a * socket and use the file descriptor reference instead of * creating a new one. */ error = fgetsock(td, args->s, &so, &fflag); if (error == 0) { error = EISCONN; if (fflag & FNONBLOCK) { SOCK_LOCK(so); if (so->so_emuldata == 0) error = so->so_error; so->so_emuldata = (void *)1; SOCK_UNLOCK(so); } fputsock(so); } return (error); }
static int linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags, struct mbuf *control, enum uio_seg segflg) { struct sockaddr *to; int error; if (mp->msg_name != NULL) { error = linux_getsockaddr(&to, mp->msg_name, mp->msg_namelen); if (error) return (error); mp->msg_name = to; } else to = NULL; error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control, segflg); if (to) free(to, M_SONAME); return (error); }