/*
 * Handle MRT setsockopt commands to modify the multicast routing tables.
 */
int
ip6_mrouter_set(struct socket *so, struct sockopt *sopt)
{
	int error, optval;
	struct mif6ctl mifc;
	struct mf6cctl mfcc;
	mifi_t mifi;

	if (sopt->sopt_name != MRT6_INIT && so != ip6_mrouter)
		return (EACCES);

	error = 0;

	switch (sopt->sopt_name) {
#ifdef MRT6_OINIT
	case MRT6_OINIT:
#endif
	case MRT6_INIT:
		error = sockopt_getint(sopt, &optval);
		if (error)
			break;
		return (ip6_mrouter_init(so, optval, sopt->sopt_name));
	case MRT6_DONE:
		return (ip6_mrouter_done());
	case MRT6_ADD_MIF:
		error = sockopt_get(sopt, &mifc, sizeof(mifc));
		if (error)
			break;
		return (add_m6if(&mifc));
	case MRT6_DEL_MIF:
		error = sockopt_get(sopt, &mifi, sizeof(mifi));
		if (error)
			break;
		return (del_m6if(&mifi));
	case MRT6_ADD_MFC:
		error = sockopt_get(sopt, &mfcc, sizeof(mfcc));
		if (error)
			break;
		return (add_m6fc(&mfcc));
	case MRT6_DEL_MFC:
		error = sockopt_get(sopt, &mfcc, sizeof(mfcc));
		if (error)
			break;
		return (del_m6fc(&mfcc));
	case MRT6_PIM:
		error = sockopt_getint(sopt, &optval);
		if (error)
			break;
		return (set_pim6(&optval));
	default:
		error = EOPNOTSUPP;
	}

	return (error);
}
Пример #2
0
static int
btsco_open(void *hdl, int flags)
{
	struct sockaddr_bt sa;
	struct btsco_softc *sc = hdl;
	struct sockopt sopt;
	int err, timo;

	DPRINTF("%s flags 0x%x\n", sc->sc_name, flags);
	/* flags FREAD & FWRITE? */

	if (sc->sc_sco != NULL || sc->sc_sco_l != NULL)
		return EIO;

	KASSERT(mutex_owned(bt_lock));

	memset(&sa, 0, sizeof(sa));
	sa.bt_len = sizeof(sa);
	sa.bt_family = AF_BLUETOOTH;
	bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);

	if (sc->sc_flags & BTSCO_LISTEN) {
		err = sco_attach_pcb(&sc->sc_sco_l, &btsco_sco_proto, sc);
		if (err)
			goto done;

		err = sco_bind_pcb(sc->sc_sco_l, &sa);
		if (err) {
			sco_detach_pcb(&sc->sc_sco_l);
			goto done;
		}

		err = sco_listen_pcb(sc->sc_sco_l);
		if (err) {
			sco_detach_pcb(&sc->sc_sco_l);
			goto done;
		}

		timo = 0;	/* no timeout */
	} else {
		err = sco_attach_pcb(&sc->sc_sco, &btsco_sco_proto, sc);
		if (err)
			goto done;

		err = sco_bind_pcb(sc->sc_sco, &sa);
		if (err) {
			sco_detach_pcb(&sc->sc_sco);
			goto done;
		}

		bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
		err = sco_connect_pcb(sc->sc_sco, &sa);
		if (err) {
			sco_detach_pcb(&sc->sc_sco);
			goto done;
		}

		timo = BTSCO_TIMEOUT;
	}

	sc->sc_state = BTSCO_WAIT_CONNECT;
	while (err == 0 && sc->sc_state == BTSCO_WAIT_CONNECT)
		err = cv_timedwait_sig(&sc->sc_connect, bt_lock, timo);

	switch (sc->sc_state) {
	case BTSCO_CLOSED:		/* disconnected */
		err = sc->sc_err;

		/* fall through to */
	case BTSCO_WAIT_CONNECT:	/* error */
		if (sc->sc_sco != NULL)
			sco_detach_pcb(&sc->sc_sco);

		if (sc->sc_sco_l != NULL)
			sco_detach_pcb(&sc->sc_sco_l);

		break;

	case BTSCO_OPEN:		/* hurrah */
		sockopt_init(&sopt, BTPROTO_SCO, SO_SCO_MTU, 0);
		(void)sco_getopt(sc->sc_sco, &sopt);
		(void)sockopt_get(&sopt, &sc->sc_mtu, sizeof(sc->sc_mtu));
		sockopt_destroy(&sopt);
		break;

	default:
		UNKNOWN(sc->sc_state);
		break;
	}

done:
	DPRINTF("done err=%d, sc_state=%d, sc_mtu=%d\n",
			err, sc->sc_state, sc->sc_mtu);
	return err;
}