Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
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);
}
Пример #4
0
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);
}
Пример #5
0
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);
}