Exemple #1
0
/*
 * Get peer socket name.
 */
int
do_sys_getpeername(int fd, struct mbuf **nam)
{
	struct socket	*so;
	struct mbuf	*m;
	int		error;

	if ((error = fd_getsock(fd, &so)) != 0)
		return error;

	m = m_getclr(M_WAIT, MT_SONAME);
	MCLAIM(m, so->so_mowner);

	solock(so);
	if ((so->so_state & SS_ISCONNECTED) == 0)
		error = ENOTCONN;
	else {
		*nam = m;
		error = (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, m);
	}
	sounlock(so);
	if (error != 0)
		m_free(m);
	fd_putfile(fd);
	return error;
}
Exemple #2
0
static int
kttcp_recv(struct lwp *l, struct kttcp_io_args *kio)
{
	struct socket *so;
	int error;
	struct timeval t0, t1;
	unsigned long long len, done;

	done = 0;	/* XXX gcc */

	if (kio->kio_totalsize > KTTCP_MAX_XMIT)
		return EINVAL;

	if ((error = fd_getsock(kio->kio_socket, &so)) != 0)
		return error;
	len = kio->kio_totalsize;
	microtime(&t0);
	do {
		error = kttcp_soreceive(so, len, &done, l, NULL);
		len -= done;
	} while (error == 0 && len > 0 && done > 0);

	fd_putfile(kio->kio_socket);

	microtime(&t1);
	if (error == EPIPE)
		error = 0;
	if (error != 0)
		return error;
	timersub(&t1, &t0, &kio->kio_elapsed);

	kio->kio_bytesdone = kio->kio_totalsize - len;

	return 0;
}
Exemple #3
0
int
do_sys_connect(struct lwp *l, int fd, struct mbuf *nam)
{
	struct socket	*so;
	int		error;
	int		interrupted = 0;

	if ((error = fd_getsock(fd, &so)) != 0) {
		m_freem(nam);
		return (error);
	}
	solock(so);
	MCLAIM(nam, so->so_mowner);
	if ((so->so_state & SS_ISCONNECTING) != 0) {
		error = EALREADY;
		goto out;
	}

	error = soconnect(so, nam, l);
	if (error)
		goto bad;
	if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) ==
	    (SS_NBIO|SS_ISCONNECTING)) {
		error = EINPROGRESS;
		goto out;
	}
	while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) {
		error = sowait(so, true, 0);
		if (__predict_false((so->so_state & SS_ISABORTING) != 0)) {
			error = EPIPE;
			interrupted = 1;
			break;
		}
		if (error) {
			if (error == EINTR || error == ERESTART)
				interrupted = 1;
			break;
		}
	}
	if (error == 0) {
		error = so->so_error;
		so->so_error = 0;
	}
 bad:
	if (!interrupted)
		so->so_state &= ~SS_ISCONNECTING;
	if (error == ERESTART)
		error = EINTR;
 out:
	sounlock(so);
	fd_putfile(fd);
	m_freem(nam);
	return error;
}
Exemple #4
0
int
do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
    struct mbuf **control, register_t *retsize)
{
	int error;
	struct socket *so;

	if ((error = fd_getsock(s, &so)) != 0)
		return error;
	error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize);
	fd_putfile(s);
	return error;
}
Exemple #5
0
int
sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval)
{
	/* {
		syscallarg(int)	s;
		syscallarg(int)	backlog;
	} */
	struct socket	*so;
	int		error;

	if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
		return (error);
	error = solisten(so, SCARG(uap, backlog), l);
	fd_putfile(SCARG(uap, s));
	return error;
}
Exemple #6
0
int
do_sys_bind(struct lwp *l, int fd, struct mbuf *nam)
{
	struct socket	*so;
	int		error;

	if ((error = fd_getsock(fd, &so)) != 0) {
		m_freem(nam);
		return (error);
	}
	MCLAIM(nam, so->so_mowner);
	error = sobind(so, nam, l);
	m_freem(nam);
	fd_putfile(fd);
	return error;
}
Exemple #7
0
int
sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(int)	s;
		syscallarg(int)	how;
	} */
	struct socket	*so;
	int		error;

	if ((error = fd_getsock(SCARG(uap, s), &so)) != 0)
		return error;
	solock(so);
	error = soshutdown(so, SCARG(uap, how));
	sounlock(so);
	fd_putfile(SCARG(uap, s));
	return error;
}
Exemple #8
0
/*
 * Get local socket name.
 */
int
do_sys_getsockname(int fd, struct mbuf **nam)
{
	struct socket	*so;
	struct mbuf	*m;
	int		error;

	if ((error = fd_getsock(fd, &so)) != 0)
		return error;

	m = m_getclr(M_WAIT, MT_SONAME);
	MCLAIM(m, so->so_mowner);

	*nam = m;
	solock(so);
	error = (*so->so_proto->pr_usrreqs->pr_sockaddr)(so, m);
	sounlock(so);
	if (error != 0)
		m_free(m);
	fd_putfile(fd);
	return error;
}
int
recvit32(struct lwp *l, int s, struct netbsd32_msghdr *mp, struct iovec *iov, void *namelenp, register_t *retsize)
{
	struct uio auio;
	int i, len, error, iovlen;
	struct mbuf *from = 0, *control = 0;
	struct socket *so;
	struct proc *p;
	struct iovec *ktriov = NULL;
	p = l->l_proc;

	/* fd_getsock() will use the descriptor for us */
	if ((error = fd_getsock(s, &so)) != 0)
		return (error);
	auio.uio_iov = iov;
	auio.uio_iovcnt = mp->msg_iovlen;
	auio.uio_rw = UIO_READ;
	auio.uio_vmspace = l->l_proc->p_vmspace;
	auio.uio_offset = 0;			/* XXX */
	auio.uio_resid = 0;
	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
#if 0
		/* cannot happen iov_len is unsigned */
		if (iov->iov_len < 0) {
			error = EINVAL;
			goto out1;
		}
#endif
		/*
		 * Reads return ssize_t because -1 is returned on error.
		 * Therefore we must restrict the length to SSIZE_MAX to
		 * avoid garbage return values.
		 */
		auio.uio_resid += iov->iov_len;
		if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
			error = EINVAL;
			goto out1;
		}
	}

	if (ktrpoint(KTR_GENIO)) {
		iovlen = auio.uio_iovcnt * sizeof(struct iovec);
		ktriov = (struct iovec *)malloc(iovlen, M_TEMP, M_WAITOK);
		memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen);
	}

	len = auio.uio_resid;
	error = (*so->so_receive)(so, &from, &auio, NULL,
			  NETBSD32PTR64(mp->msg_control) ? &control : NULL,
			  &mp->msg_flags);
	if (error) {
		if (auio.uio_resid != len && (error == ERESTART ||
		    error == EINTR || error == EWOULDBLOCK))
			error = 0;
	}

	if (ktriov != NULL) {
		ktrgeniov(s, UIO_READ, ktriov, len - auio.uio_resid, error);
		FREE(ktriov, M_TEMP);
	}

	if (error)
		goto out;
	*retsize = len - auio.uio_resid;
	if (NETBSD32PTR64(mp->msg_name)) {
		len = mp->msg_namelen;
		if (len <= 0 || from == 0)
			len = 0;
		else {
			if (len > from->m_len)
				len = from->m_len;
			/* else if len < from->m_len ??? */
			error = copyout(mtod(from, void *),
			    (void *)NETBSD32PTR64(mp->msg_name),
			    (unsigned)len);
			if (error)
				goto out;
		}
		mp->msg_namelen = len;
		if (namelenp &&
		    (error = copyout((void *)&len, namelenp, sizeof(int))))
			goto out;
	}
Exemple #10
0
int
sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(int)			s;
		syscallarg(struct mmsghdr *)	mmsg;
		syscallarg(unsigned int)	vlen;
		syscallarg(unsigned int)	flags;
		syscallarg(struct timespec *)	timeout;
	} */
	struct mmsghdr mmsg;
	struct socket *so;
	struct msghdr *msg = &mmsg.msg_hdr;
	int error, s;
	struct mbuf *from, *control;
	struct timespec ts, now;
	unsigned int vlen, flags, dg;

	if (SCARG(uap, timeout)) {
		if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0)
			return error;
		getnanotime(&now);
		timespecadd(&now, &ts, &ts);
	}

	s = SCARG(uap, s);
	if ((error = fd_getsock(s, &so)) != 0)
		return error;

	vlen = SCARG(uap, vlen);
	if (vlen > 1024)
		vlen = 1024;

	from = NULL;
	flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;

	for (dg = 0; dg < vlen;) {
		error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
		if (error)
			break;

		msg->msg_flags = flags & ~MSG_WAITFORONE;

		if (from != NULL) {
			m_free(from);
			from = NULL;
		}

		error = do_sys_recvmsg_so(l, s, so, msg, &from,
		    msg->msg_control != NULL ? &control : NULL, retval);
		if (error) {
			if (error == EAGAIN && dg > 0)
				error = 0;
			break;
		}

		if (msg->msg_control != NULL)
			error = copyout_msg_control(l, msg, control);
		if (error)
			break;

		error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
		    from);
		if (error)
			break;

		ktrkuser("msghdr", msg, sizeof *msg);
		mmsg.msg_len = *retval;

		error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
		if (error)
			break;

		dg++;
		if (msg->msg_flags & MSG_OOB)
			break;

		if (SCARG(uap, timeout)) {
			getnanotime(&now);
			timespecsub(&now, &ts, &now);
			if (now.tv_sec > 0)
				break;
		}

		if (flags & MSG_WAITFORONE)
			flags |= MSG_DONTWAIT;

	}

	if (from != NULL)
		m_free(from);

	*retval = dg;
	if (error)
		so->so_error = error;

	fd_putfile(s);

	/*
	 * If we succeeded at least once, return 0, hopefully so->so_error
	 * will catch it next time.
	 */
	if (dg)
		return 0;

	return error;
}
int
ultrix_sys_setsockopt(struct lwp *l, const struct ultrix_sys_setsockopt_args *uap, register_t *retval)
{
	struct sockopt sopt;
	struct socket *so;
	int error;
	struct sys_setsockopt_args ap;

	SCARG(&ap, s) = SCARG(uap, s);
	SCARG(&ap, level) = SCARG(uap, level);
	SCARG(&ap, name) = SCARG(uap, name);
	SCARG(&ap, val) = SCARG(uap, val);
	SCARG(&ap, valsize) = SCARG(uap, valsize);

	/* fd_getsock() will use the descriptor for us */
	if ((error = fd_getsock(SCARG(&ap, s), &so))  != 0)
		return error;
#define	SO_DONTLINGER (~SO_LINGER)
	if (SCARG(&ap, name) == SO_DONTLINGER) {
		struct linger lg;

		lg.l_onoff = 0;
		error = so_setsockopt(l, so, SCARG(&ap, level), SO_LINGER,
		    &lg, sizeof(lg));
		goto out;
	}
	if (SCARG(&ap, level) == IPPROTO_IP) {
#define		EMUL_IP_MULTICAST_IF		2
#define		EMUL_IP_MULTICAST_TTL		3
#define		EMUL_IP_MULTICAST_LOOP		4
#define		EMUL_IP_ADD_MEMBERSHIP		5
#define		EMUL_IP_DROP_MEMBERSHIP	6
		static const int ipoptxlat[] = {
			IP_MULTICAST_IF,
			IP_MULTICAST_TTL,
			IP_MULTICAST_LOOP,
			IP_ADD_MEMBERSHIP,
			IP_DROP_MEMBERSHIP
		};
		if (SCARG(&ap, name) >= EMUL_IP_MULTICAST_IF &&
		    SCARG(&ap, name) <= EMUL_IP_DROP_MEMBERSHIP) {
			SCARG(&ap, name) =
			    ipoptxlat[SCARG(&ap, name) - EMUL_IP_MULTICAST_IF];
		}
	}
	if (SCARG(&ap, valsize) > MLEN) {
		error = EINVAL;
		goto out;
	}
	sockopt_init(&sopt, SCARG(&ap, level), SCARG(&ap, name),
	    SCARG(&ap, valsize));
	if (SCARG(&ap, val)) {
		error = copyin(SCARG(&ap, val), sopt.sopt_data,
		    (u_int)SCARG(&ap, valsize));
	}
	if (error == 0)
		error = sosetopt(so, &sopt);
	sockopt_destroy(&sopt);
 out:
 	fd_putfile(SCARG(uap, s));
	return error;
}