コード例 #1
0
int
afmioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag,
    struct lwp *l)
{
	int	error = 0;
	struct atm_flowmap *flowmap;
	struct ifnet *ifp;

	/* check cmd for superuser only */
	switch (cmd) {
	case AFM_GETFMAP:
		break;
	default:
#if (__FreeBSD_version > 400000)
		error = suser(p);
#else
		error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_ALTQ,
		    KAUTH_REQ_NETWORK_ALTQ_AFMAP, NULL, NULL, NULL);
#endif
		if (error)
			return (error);
		break;
	}

	/* lookup interface */
	flowmap = (struct atm_flowmap *)addr;
	flowmap->af_ifname[IFNAMSIZ-1] = '\0';
	ifp = ifunit(flowmap->af_ifname);
	if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0)
		error = ENXIO;
	else
		error = ifp->if_ioctl(ifp, cmd, addr);

	return error;
}
コード例 #2
0
int
altqioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag, struct lwp *l)
{
	int unit = minor(dev);

	if (unit == 0) {
		struct ifnet *ifp;
		struct altqreq *typereq;
		struct tbrreq *tbrreq;
		int error;

		switch (cmd) {
		case ALTQGTYPE:
		case ALTQTBRGET:
			break;
		default:
#if (__FreeBSD_version > 400000)
			if ((error = suser(p)) != 0)
				return (error);
#else
			if ((error = kauth_authorize_network(l->l_cred,
			    KAUTH_NETWORK_ALTQ, KAUTH_REQ_NETWORK_ALTQ_CONF,
			    NULL, NULL, NULL)) != 0)
				return (error);
#endif
			break;
		}

		switch (cmd) {
		case ALTQGTYPE:
			typereq = (struct altqreq *)addr;
			if ((ifp = ifunit(typereq->ifname)) == NULL)
				return (EINVAL);
			typereq->arg = (u_long)ifp->if_snd.altq_type;
			return (0);
		case ALTQTBRSET:
			tbrreq = (struct tbrreq *)addr;
			if ((ifp = ifunit(tbrreq->ifname)) == NULL)
				return (EINVAL);
			return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
		case ALTQTBRGET:
			tbrreq = (struct tbrreq *)addr;
			if ((ifp = ifunit(tbrreq->ifname)) == NULL)
				return (EINVAL);
			return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
		default:
			return (EINVAL);
		}
	}
	if (unit < naltqsw)
		return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, l);

	return ENXIO;
}
コード例 #3
0
static int
npf_dev_open(dev_t dev, int flag, int mode, lwp_t *l)
{

	/* Available only for super-user. */
	if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FIREWALL,
	    KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, NULL, NULL)) {
		return EPERM;
	}
	return 0;
}
コード例 #4
0
static int
npf_dev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
{
	int error;

	/* Available only for super-user. */
	if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FIREWALL,
	    KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, NULL, NULL)) {
		return EPERM;
	}

	switch (cmd) {
	case IOC_NPF_TABLE:
		error = npfctl_table(data);
		break;
	case IOC_NPF_RULE:
		error = npfctl_rule(cmd, data);
		break;
	case IOC_NPF_GETCONF:
		error = npfctl_getconf(cmd, data);
		break;
	case IOC_NPF_STATS:
		error = npfctl_stats(data);
		break;
	case IOC_NPF_SESSIONS_SAVE:
		error = npfctl_sessions_save(cmd, data);
		break;
	case IOC_NPF_SESSIONS_LOAD:
		error = npfctl_sessions_load(cmd, data);
		break;
	case IOC_NPF_SWITCH:
		error = npfctl_switch(data);
		break;
	case IOC_NPF_RELOAD:
		error = npfctl_reload(cmd, data);
		break;
	case IOC_NPF_VERSION:
		*(int *)data = NPF_VERSION;
		error = 0;
		break;
	default:
		error = ENOTTY;
		break;
	}
	return error;
}
コード例 #5
0
/*
 * tunnel open - must be superuser & the device must be
 * configured in
 */
static int
tunopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct ifnet	*ifp;
	struct tun_softc *tp;
	int	s, error;

	error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE_TUN,
	    KAUTH_REQ_NETWORK_INTERFACE_TUN_ADD, NULL, NULL, NULL);
	if (error)
		return (error);

	s = splnet();
	tp = tun_find_unit(dev);

	if (tp == NULL) {
		(void)tun_clone_create(&tun_cloner, minor(dev));
		tp = tun_find_unit(dev);
		if (tp == NULL) {
			error = ENXIO;
			goto out_nolock;
		}
	}

	if (tp->tun_flags & TUN_OPEN) {
		error = EBUSY;
		goto out;
	}

	ifp = &tp->tun_if;
	tp->tun_flags |= TUN_OPEN;
	TUNDEBUG("%s: open\n", ifp->if_xname);
out:
	mutex_exit(&tp->tun_lock);
out_nolock:
	splx(s);
	return (error);
}
コード例 #6
0
ファイル: altq_cbq.c プロジェクト: Tommmster/netbsd-avr32
int
cbqioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag,
    struct lwp *l)
{
	int	error = 0;

	/* check cmd for superuser only */
	switch (cmd) {
	case CBQ_GETSTATS:
		/* currently only command that an ordinary user can call */
		break;
	default:
#if (__FreeBSD_version > 400000)
		error = suser(p);
#else
		error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_ALTQ,
		    KAUTH_REQ_NETWORK_ALTQ_CBQ, NULL, NULL, NULL);
#endif
		if (error)
			return (error);
		break;
	}

	switch (cmd) {

	case CBQ_ENABLE:
		error = cbq_set_enable((struct cbq_interface *)addr, ENABLE);
		break;

	case CBQ_DISABLE:
		error = cbq_set_enable((struct cbq_interface *)addr, DISABLE);
		break;

	case CBQ_ADD_FILTER:
		error = cbq_add_filter((struct cbq_add_filter *)addr);
		break;

	case CBQ_DEL_FILTER:
		error = cbq_delete_filter((struct cbq_delete_filter *)addr);
		break;

	case CBQ_ADD_CLASS:
		error = cbq_add_class((struct cbq_add_class *)addr);
		break;

	case CBQ_DEL_CLASS:
		error = cbq_delete_class((struct cbq_delete_class *)addr);
		break;

	case CBQ_MODIFY_CLASS:
		error = cbq_modify_class((struct cbq_modify_class *)addr);
		break;

	case CBQ_CLEAR_HIERARCHY:
		error = cbq_clear_hierarchy((struct cbq_interface *)addr);
		break;

	case CBQ_IF_ATTACH:
		error = cbq_ifattach((struct cbq_interface *)addr);
		break;

	case CBQ_IF_DETACH:
		error = cbq_ifdetach((struct cbq_interface *)addr);
		break;

	case CBQ_GETSTATS:
		error = cbq_getstats((struct cbq_getstats *)addr);
		break;

	default:
		error = EINVAL;
		break;
	}

	return error;
}
コード例 #7
0
/*
 * Bind port from sin6 to in6p.
 */
static int
in6_pcbbind_port(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
{
	struct inpcbtable *table = in6p->in6p_table;
	struct socket *so = in6p->in6p_socket;
	int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
	int error;

	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
	   ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
	    (so->so_options & SO_ACCEPTCONN) == 0))
		wild = 1;

	if (sin6->sin6_port != 0) {
		enum kauth_network_req req;

#ifndef IPNOPRIVPORTS
		if (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED)
			req = KAUTH_REQ_NETWORK_BIND_PRIVPORT;
		else
#endif /* IPNOPRIVPORTS */
			req = KAUTH_REQ_NETWORK_BIND_PORT;

		error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_BIND,
		    req, so, sin6, NULL);
		if (error)
			return (EACCES);
	}

	if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
		/*
		 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
		 * allow compepte duplication of binding if
		 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
		 * and a multicast address is bound on both
		 * new and duplicated sockets.
		 */
		if (so->so_options & SO_REUSEADDR)
			reuseport = SO_REUSEADDR|SO_REUSEPORT;
	}

	if (sin6->sin6_port != 0) {
		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
#ifdef INET
			struct inpcb *t;
			struct vestigial_inpcb vestige;

			t = in_pcblookup_port(table,
			    *(struct in_addr *)&sin6->sin6_addr.s6_addr32[3],
			    sin6->sin6_port, wild, &vestige);
			if (t && (reuseport & t->inp_socket->so_options) == 0)
				return (EADDRINUSE);
			if (!t
			    && vestige.valid
			    && !(reuseport && vestige.reuse_port))
			    return EADDRINUSE;
#else
			return (EADDRNOTAVAIL);
#endif
		}

		{
			struct in6pcb *t;
			struct vestigial_inpcb vestige;

			t = in6_pcblookup_port(table, &sin6->sin6_addr,
			    sin6->sin6_port, wild, &vestige);
			if (t && (reuseport & t->in6p_socket->so_options) == 0)
				return (EADDRINUSE);
			if (!t
			    && vestige.valid
			    && !(reuseport && vestige.reuse_port))
			    return EADDRINUSE;
		}
	}

	if (sin6->sin6_port == 0) {
		int e;
		e = in6_pcbsetport(sin6, in6p, l);
		if (e != 0)
			return (e);
	} else {
		in6p->in6p_lport = sin6->sin6_port;
		in6_pcbstate(in6p, IN6P_BOUND);
	}

	LIST_REMOVE(&in6p->in6p_head, inph_lhash);
	LIST_INSERT_HEAD(IN6PCBHASH_PORT(table, in6p->in6p_lport),
	    &in6p->in6p_head, inph_lhash);

	return (0);
}
コード例 #8
0
/*
 * Check whether the port picked by the port randomizer is available
 * and whether KAUTH approves of our choice. This part of the code
 * shamelessly copied from in_pcb.c.
 */
static bool
check_suitable_port(uint16_t port, struct inpcb_hdr *inp_hdr, kauth_cred_t cred)
{
	struct inpcbtable * const table = inp_hdr->inph_table;
#ifdef INET
	vestigial_inpcb_t vestigial;
#endif
	int error;
#ifdef INET6
	struct socket *so;
	int wild = 0;
#endif

	DPRINTF("%s called for argument %d\n", __func__, port);

	switch (inp_hdr->inph_af) {
#ifdef INET
	case AF_INET: { /* IPv4 */
		struct inpcb *inp = (struct inpcb *)(void *)inp_hdr;
		struct inpcb *pcb;
		struct sockaddr_in sin;

		if (__BITMAP_ISSET(port, &inet4_reserve))
			return false;

		sin.sin_addr = inp->inp_laddr;
		pcb = in_pcblookup_port(table, sin.sin_addr, htons(port), 1,
		    &vestigial);

		DPRINTF("%s in_pcblookup_port returned %p and "
		    "vestigial.valid %d\n",
		    __func__, pcb, vestigial.valid);

		if ((!pcb) && (!vestigial.valid)) {
			enum kauth_network_req req;

			/* We have a free port. Check with the secmodel. */
			if (inp->inp_flags & INP_LOWPORT) {
#ifndef IPNOPRIVPORTS
				req = KAUTH_REQ_NETWORK_BIND_PRIVPORT;
#else
				req = KAUTH_REQ_NETWORK_BIND_PORT;
#endif
			} else
				req = KAUTH_REQ_NETWORK_BIND_PORT;

			sin.sin_port = port;
			error = kauth_authorize_network(cred,
			    KAUTH_NETWORK_BIND,
			    req, inp->inp_socket, &sin, NULL);
			DPRINTF("%s kauth_authorize_network returned %d\n",
			    __func__, error);

			if (error == 0) {
				DPRINTF("%s port approved\n", __func__);
				return true;	/* KAUTH agrees */
			}
		}
		break;
	}
#endif
#ifdef INET6
	case AF_INET6: { /* IPv6 */
		struct in6pcb *in6p = (struct in6pcb *)(void *)inp_hdr;
		struct sockaddr_in6 sin6;
		void *t;

		if (__BITMAP_ISSET(port, &inet6_reserve))
			return false;

		sin6.sin6_addr = in6p->in6p_laddr;
		so = in6p->in6p_socket;

		/* XXX: this is redundant when called from in6_pcbbind */
		if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
		    ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
			(so->so_options & SO_ACCEPTCONN) == 0))
			wild = 1;

#ifdef INET
		if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
			t = in_pcblookup_port(table,
			    *(struct in_addr *)&sin6.sin6_addr.s6_addr32[3],
			    htons(port), wild, &vestigial);
			if (!t && vestigial.valid) {
				DPRINTF("%s in_pcblookup_port returned "
				    "a result\n", __func__);
				return false;
			}
		} else
#endif
		{
			t = in6_pcblookup_port(table, &sin6.sin6_addr,
			    htons(port), wild, &vestigial);
			if (!t && vestigial.valid) {
				DPRINTF("%s in6_pcblookup_port returned "
				    "a result\n", __func__);
				return false;
			}
		}
		if (t == NULL) {
			enum kauth_network_req req;

			/* We have a free port. Check with the secmodel. */
			if (in6p->in6p_flags & IN6P_LOWPORT) {
#ifndef IPNOPRIVPORTS
				req = KAUTH_REQ_NETWORK_BIND_PRIVPORT;
#else
				req = KAUTH_REQ_NETWORK_BIND_PORT;
#endif
			} else {
				req = KAUTH_REQ_NETWORK_BIND_PORT;
			}

			sin6.sin6_port = port;
			error = kauth_authorize_network(cred,
			    KAUTH_NETWORK_BIND, req, so, &sin6, NULL);
			if (error) {
				/* Secmodel says no. Keep looking. */
				DPRINTF("%s secmodel says no\n", __func__);
				return false;
			}
			DPRINTF("%s port approved\n", __func__);
			return true;
		}
		break;
	}
#endif
	default:
		DPRINTF("%s unknown address family\n", __func__);
		return false;
	}
	return false;
}