예제 #1
0
int
sys_getsockopt(struct lwp *l, const struct sys_getsockopt_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(int)			s;
		syscallarg(int)			level;
		syscallarg(int)			name;
		syscallarg(void *)		val;
		syscallarg(unsigned int *)	avalsize;
	} */
	struct sockopt	sopt;
	struct socket	*so;
	file_t		*fp;
	unsigned int	valsize, len;
	int		error;

	if (SCARG(uap, val) != NULL) {
		error = copyin(SCARG(uap, avalsize), &valsize, sizeof(valsize));
		if (error)
			return error;
	} else
		valsize = 0;

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

	sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), 0);

	if (fp->f_flag & FNOSIGPIPE)
		so->so_options |= SO_NOSIGPIPE;
	else
		so->so_options &= ~SO_NOSIGPIPE;
	error = sogetopt(so, &sopt);
	if (error)
		goto out;

	if (valsize > 0) {
		len = min(valsize, sopt.sopt_size);
		error = copyout(sopt.sopt_data, SCARG(uap, val), len);
		if (error)
			goto out;

		error = copyout(&len, SCARG(uap, avalsize), sizeof(len));
		if (error)
			goto out;
	}

 out:
	sockopt_destroy(&sopt);
	fd_putfile(SCARG(uap, s));
	return error;
}
예제 #2
0
int
sys_setsockopt(struct lwp *l, const struct sys_setsockopt_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(int)			s;
		syscallarg(int)			level;
		syscallarg(int)			name;
		syscallarg(const void *)	val;
		syscallarg(unsigned int)	valsize;
	} */
	struct sockopt	sopt;
	struct socket	*so;
	file_t		*fp;
	int		error;
	unsigned int	len;

	len = SCARG(uap, valsize);
	if (len > 0 && SCARG(uap, val) == NULL)
		return EINVAL;

	if (len > MCLBYTES)
		return EINVAL;

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

	sockopt_init(&sopt, SCARG(uap, level), SCARG(uap, name), len);

	if (len > 0) {
		error = copyin(SCARG(uap, val), sopt.sopt_data, len);
		if (error)
			goto out;
	}

	error = sosetopt(so, &sopt);
	if (so->so_options & SO_NOSIGPIPE)
		atomic_or_uint(&fp->f_flag, FNOSIGPIPE);
	else
		atomic_and_uint(&fp->f_flag, ~FNOSIGPIPE);

 out:
	sockopt_destroy(&sopt);
	fd_putfile(SCARG(uap, s));
	return error;
}
예제 #3
0
static void
bthidev_attach(device_t parent, device_t self, void *aux)
{
	struct bthidev_softc *sc = device_private(self);
	prop_dictionary_t dict = aux;
	prop_object_t obj;
	device_t dev;
	struct bthidev_attach_args bha;
	struct bthidev *hidev;
	struct hid_data *d;
	struct hid_item h;
	const void *desc;
	int locs[BTHIDBUSCF_NLOCS];
	int maxid, rep, dlen;

	/*
	 * Init softc
	 */
	sc->sc_dev = self;
	LIST_INIT(&sc->sc_list);
	callout_init(&sc->sc_reconnect, 0);
	callout_setfunc(&sc->sc_reconnect, bthidev_timeout, sc);
	sc->sc_state = BTHID_CLOSED;
	sc->sc_flags = BTHID_CONNECTING;
	sc->sc_ctlpsm = L2CAP_PSM_HID_CNTL;
	sc->sc_intpsm = L2CAP_PSM_HID_INTR;

	sockopt_init(&sc->sc_mode, BTPROTO_L2CAP, SO_L2CAP_LM, 0);

	/*
	 * extract config from proplist
	 */
	obj = prop_dictionary_get(dict, BTDEVladdr);
	bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj));

	obj = prop_dictionary_get(dict, BTDEVraddr);
	bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));

	obj = prop_dictionary_get(dict, BTDEVmode);
	if (prop_object_type(obj) == PROP_TYPE_STRING) {
		if (prop_string_equals_cstring(obj, BTDEVauth))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_AUTH);
		else if (prop_string_equals_cstring(obj, BTDEVencrypt))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_ENCRYPT);
		else if (prop_string_equals_cstring(obj, BTDEVsecure))
			sockopt_setint(&sc->sc_mode, L2CAP_LM_SECURE);
		else  {
			aprint_error(" unknown %s\n", BTDEVmode);
			return;
		}

		aprint_verbose(" %s %s", BTDEVmode,
					 prop_string_cstring_nocopy(obj));
	}

	obj = prop_dictionary_get(dict, BTHIDEVcontrolpsm);
	if (prop_object_type(obj) == PROP_TYPE_NUMBER) {
		sc->sc_ctlpsm = prop_number_integer_value(obj);
		if (L2CAP_PSM_INVALID(sc->sc_ctlpsm)) {
			aprint_error(" invalid %s\n", BTHIDEVcontrolpsm);
			return;
		}
	}

	obj = prop_dictionary_get(dict, BTHIDEVinterruptpsm);
	if (prop_object_type(obj) == PROP_TYPE_NUMBER) {
		sc->sc_intpsm = prop_number_integer_value(obj);
		if (L2CAP_PSM_INVALID(sc->sc_intpsm)) {
			aprint_error(" invalid %s\n", BTHIDEVinterruptpsm);
			return;
		}
	}

	obj = prop_dictionary_get(dict, BTHIDEVdescriptor);
	if (prop_object_type(obj) == PROP_TYPE_DATA) {
		dlen = prop_data_size(obj);
		desc = prop_data_data_nocopy(obj);
	} else {
		aprint_error(" no %s\n", BTHIDEVdescriptor);
		return;
	}

	obj = prop_dictionary_get(dict, BTHIDEVreconnect);
	if (prop_object_type(obj) == PROP_TYPE_BOOL
	    && !prop_bool_true(obj))
		sc->sc_flags |= BTHID_RECONNECT;

	/*
	 * Parse the descriptor and attach child devices, one per report.
	 */
	maxid = -1;
	h.report_ID = 0;
	d = hid_start_parse(desc, dlen, hid_none);
	while (hid_get_item(d, &h)) {
		if (h.report_ID > maxid)
			maxid = h.report_ID;
	}
	hid_end_parse(d);

	if (maxid < 0) {
		aprint_error(" no reports found\n");
		return;
	}

	aprint_normal("\n");

	for (rep = 0 ; rep <= maxid ; rep++) {
		if (hid_report_size(desc, dlen, hid_feature, rep) == 0
		    && hid_report_size(desc, dlen, hid_input, rep) == 0
		    && hid_report_size(desc, dlen, hid_output, rep) == 0)
			continue;

		bha.ba_desc = desc;
		bha.ba_dlen = dlen;
		bha.ba_input = bthidev_null;
		bha.ba_feature = bthidev_null;
		bha.ba_output = bthidev_output;
		bha.ba_id = rep;

		locs[BTHIDBUSCF_REPORTID] = rep;

		dev = config_found_sm_loc(self, "bthidbus",
					locs, &bha, bthidev_print, config_stdsubmatch);
		if (dev != NULL) {
			hidev = device_private(dev);
			hidev->sc_dev = dev;
			hidev->sc_parent = self;
			hidev->sc_id = rep;
			hidev->sc_input = bha.ba_input;
			hidev->sc_feature = bha.ba_feature;
			LIST_INSERT_HEAD(&sc->sc_list, hidev, sc_next);
		}
	}

	/*
	 * start bluetooth connections
	 */
	mutex_enter(bt_lock);
	if ((sc->sc_flags & BTHID_RECONNECT) == 0)
		bthidev_listen(sc);

	if (sc->sc_flags & BTHID_CONNECTING)
		bthidev_connect(sc);
	mutex_exit(bt_lock);
}
예제 #4
0
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;
}
예제 #5
0
파일: btsco.c 프로젝트: goroutines/rumprun
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;
}