Esempio n. 1
0
int
sotoxsocket(struct socket *so, struct xsocket *xso)
{
	struct protosw proto;
	struct domain domain;

	bzero(xso, sizeof *xso);
	xso->xso_len = sizeof *xso;
	xso->xso_so = so;
	xso->so_type = so->so_type;
	xso->so_options = so->so_options;
	xso->so_linger = so->so_linger;
	xso->so_state = so->so_state;
	xso->so_pcb = so->so_pcb;
	if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0)
		return (-1);
	xso->xso_protocol = proto.pr_protocol;
	if (kread((uintptr_t)proto.pr_domain, &domain, sizeof(domain)) != 0)
		return (-1);
	xso->xso_family = domain.dom_family;
	xso->so_timeo = so->so_timeo;
	xso->so_error = so->so_error;
	if (SOLISTENING(so)) {
		xso->so_qlen = so->sol_qlen;
		xso->so_incqlen = so->sol_incqlen;
		xso->so_qlimit = so->sol_qlimit;
	} else {
		sbtoxsockbuf(&so->so_snd, &xso->so_snd);
		sbtoxsockbuf(&so->so_rcv, &xso->so_rcv);
		xso->so_oobmark = so->so_oobmark;
	}
	return (0);
}
Esempio n. 2
0
static int
soo_stat(struct file *fp, struct stat *ub, struct ucred *active_cred,
    struct thread *td)
{
	struct socket *so = fp->f_data;
#ifdef MAC
	int error;
#endif

	bzero((caddr_t)ub, sizeof (*ub));
	ub->st_mode = S_IFSOCK;
#ifdef MAC
	error = mac_socket_check_stat(active_cred, so);
	if (error)
		return (error);
#endif
	if (!SOLISTENING(so)) {
		struct sockbuf *sb;

		/*
		 * If SBS_CANTRCVMORE is set, but there's still data left
		 * in the receive buffer, the socket is still readable.
		 */
		sb = &so->so_rcv;
		SOCKBUF_LOCK(sb);
		if ((sb->sb_state & SBS_CANTRCVMORE) == 0 || sbavail(sb))
			ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
		ub->st_size = sbavail(sb) - sb->sb_ctl;
		SOCKBUF_UNLOCK(sb);
	
		sb = &so->so_snd;
		SOCKBUF_LOCK(sb);
		if ((sb->sb_state & SBS_CANTSENDMORE) == 0)
			ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
		SOCKBUF_UNLOCK(sb);
	}
	ub->st_uid = so->so_cred->cr_uid;
	ub->st_gid = so->so_cred->cr_gid;
	return (*so->so_proto->pr_usrreqs->pru_sense)(so, ub);
}
Esempio n. 3
0
int
sbsetopt(struct socket *so, int cmd, u_long cc)
{
	struct sockbuf *sb;
	short *flags;
	u_int *hiwat, *lowat;
	int error;

	sb = NULL;
	SOCK_LOCK(so);
	if (SOLISTENING(so)) {
		switch (cmd) {
			case SO_SNDLOWAT:
			case SO_SNDBUF:
				lowat = &so->sol_sbsnd_lowat;
				hiwat = &so->sol_sbsnd_hiwat;
				flags = &so->sol_sbsnd_flags;
				break;
			case SO_RCVLOWAT:
			case SO_RCVBUF:
				lowat = &so->sol_sbrcv_lowat;
				hiwat = &so->sol_sbrcv_hiwat;
				flags = &so->sol_sbrcv_flags;
				break;
		}
	} else {
		switch (cmd) {
			case SO_SNDLOWAT:
			case SO_SNDBUF:
				sb = &so->so_snd;
				break;
			case SO_RCVLOWAT:
			case SO_RCVBUF:
				sb = &so->so_rcv;
				break;
		}
		flags = &sb->sb_flags;
		hiwat = &sb->sb_hiwat;
		lowat = &sb->sb_lowat;
		SOCKBUF_LOCK(sb);
	}

	error = 0;
	switch (cmd) {
	case SO_SNDBUF:
	case SO_RCVBUF:
		if (SOLISTENING(so)) {
			if (cc > sb_max_adj) {
				error = ENOBUFS;
				break;
			}
			*hiwat = cc;
			if (*lowat > *hiwat)
				*lowat = *hiwat;
		} else {
			if (!sbreserve_locked(sb, cc, so, curthread))
				error = ENOBUFS;
		}
		if (error == 0)
			*flags &= ~SB_AUTOSIZE;
		break;
	case SO_SNDLOWAT:
	case SO_RCVLOWAT:
		/*
		 * Make sure the low-water is never greater than the
		 * high-water.
		 */
		*lowat = (cc > *hiwat) ? *hiwat : cc;
		break;
	}

	if (!SOLISTENING(so))
		SOCKBUF_UNLOCK(sb);
	SOCK_UNLOCK(so);
	return (error);
}
Esempio n. 4
0
static int
soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
    struct thread *td)
{
	struct socket *so = fp->f_data;
	int error = 0;

	switch (cmd) {
	case FIONBIO:
		SOCK_LOCK(so);
		if (*(int *)data)
			so->so_state |= SS_NBIO;
		else
			so->so_state &= ~SS_NBIO;
		SOCK_UNLOCK(so);
		break;

	case FIOASYNC:
		if (*(int *)data) {
			SOCK_LOCK(so);
			so->so_state |= SS_ASYNC;
			if (SOLISTENING(so)) {
				so->sol_sbrcv_flags |= SB_ASYNC;
				so->sol_sbsnd_flags |= SB_ASYNC;
			} else {
				SOCKBUF_LOCK(&so->so_rcv);
				so->so_rcv.sb_flags |= SB_ASYNC;
				SOCKBUF_UNLOCK(&so->so_rcv);
				SOCKBUF_LOCK(&so->so_snd);
				so->so_snd.sb_flags |= SB_ASYNC;
				SOCKBUF_UNLOCK(&so->so_snd);
			}
			SOCK_UNLOCK(so);
		} else {
			SOCK_LOCK(so);
			so->so_state &= ~SS_ASYNC;
			if (SOLISTENING(so)) {
				so->sol_sbrcv_flags &= ~SB_ASYNC;
				so->sol_sbsnd_flags &= ~SB_ASYNC;
			} else {
				SOCKBUF_LOCK(&so->so_rcv);
				so->so_rcv.sb_flags &= ~SB_ASYNC;
				SOCKBUF_UNLOCK(&so->so_rcv);
				SOCKBUF_LOCK(&so->so_snd);
				so->so_snd.sb_flags &= ~SB_ASYNC;
				SOCKBUF_UNLOCK(&so->so_snd);
			}
			SOCK_UNLOCK(so);
		}
		break;

	case FIONREAD:
		/* Unlocked read. */
		*(int *)data = sbavail(&so->so_rcv);
		break;

	case FIONWRITE:
		/* Unlocked read. */
		*(int *)data = sbavail(&so->so_snd);
		break;

	case FIONSPACE:
		/* Unlocked read. */
		if ((so->so_snd.sb_hiwat < sbused(&so->so_snd)) ||
		    (so->so_snd.sb_mbmax < so->so_snd.sb_mbcnt))
			*(int *)data = 0;
		else
			*(int *)data = sbspace(&so->so_snd);
		break;

	case FIOSETOWN:
		error = fsetown(*(int *)data, &so->so_sigio);
		break;

	case FIOGETOWN:
		*(int *)data = fgetown(&so->so_sigio);
		break;

	case SIOCSPGRP:
		error = fsetown(-(*(int *)data), &so->so_sigio);
		break;

	case SIOCGPGRP:
		*(int *)data = -fgetown(&so->so_sigio);
		break;

	case SIOCATMARK:
		/* Unlocked read. */
		*(int *)data = (so->so_rcv.sb_state & SBS_RCVATMARK) != 0;
		break;
	default:
		/*
		 * Interface/routing/protocol specific ioctls: interface and
		 * routing ioctls should have a different entry since a
		 * socket is unnecessary.
		 */
		if (IOCGROUP(cmd) == 'i')
			error = ifioctl(so, cmd, data, td);
		else if (IOCGROUP(cmd) == 'r') {
			CURVNET_SET(so->so_vnet);
			error = rtioctl_fib(cmd, data, so->so_fibnum);
			CURVNET_RESTORE();
		} else {
			CURVNET_SET(so->so_vnet);
			error = ((*so->so_proto->pr_usrreqs->pru_control)
			    (so, cmd, data, 0, td));
			CURVNET_RESTORE();
		}
		break;
	}
	return (error);
}