Esempio n. 1
0
static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
                             gpointer user_data)
{
    struct pan_device *dev = user_data;
    uint8_t packet[BNEP_MTU];
    int sk, n, err;

    if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
        error("Hangup or error or inval on BNEP socket");
        return FALSE;
    }

    sk = g_io_channel_unix_get_fd(chan);

    /*
     * BNEP_SETUP_CONNECTION_REQUEST_MSG should be read and left in case
     * of kernel setup connection msg handling.
     */
    n = recv(sk, packet, sizeof(packet), MSG_PEEK);
    if (n  < 0) {
        error("read(): %s(%d)", strerror(errno), errno);
        goto failed;
    }

    if (n < 3) {
        error("pan: to few setup connection request data received");
        goto failed;
    }

    err = nap_create_bridge();
    if (err < 0)
        error("pan: Failed to create bridge: %s (%d)", strerror(-err),
              -err);

    if (bnep_server_add(sk, (err < 0) ? NULL : BNEP_BRIDGE, dev->iface,
                        &dev->dst, packet, n) < 0) {
        error("pan: server_connadd failed");
        goto failed;
    }

    dev->watch = g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
                                nap_watchdog_cb, dev);
    g_io_channel_unref(dev->io);
    dev->io = NULL;

    bt_pan_notify_ctrl_state(dev, HAL_PAN_CTRL_ENABLED, HAL_STATUS_SUCCESS);
    bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTED);

    return FALSE;

failed:
    pan_device_remove(dev);

    return FALSE;
}
Esempio n. 2
0
static gboolean bnep_setup(GIOChannel *chan,
			GIOCondition cond, gpointer user_data)
{
	const uint8_t bt_base[] = { 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
					0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
	struct network_adapter *na = user_data;
	struct network_server *ns;
	uint8_t packet[BNEP_MTU];
	struct bnep_setup_conn_req *req = (void *) packet;
	uint16_t dst_role = 0;
	uint32_t val;
	int n, sk;
	char *bridge = NULL;

	if (cond & G_IO_NVAL)
		return FALSE;

	if (cond & (G_IO_ERR | G_IO_HUP)) {
		error("Hangup or error on BNEP socket");
		return FALSE;
	}

	sk = g_io_channel_unix_get_fd(chan);

	/*
	 * BNEP_SETUP_CONNECTION_REQUEST_MSG should be read and left in case
	 * of kernel setup connection msg handling.
	 */
	n = recv(sk, packet, sizeof(packet), MSG_PEEK);
	if (n < 0) {
		error("read(): %s(%d)", strerror(errno), errno);
		return FALSE;
	}

	/*
	 * Initial received data packet is BNEP_SETUP_CONNECTION_REQUEST_MSG
	 * minimal size of this frame is 3 octets: 1 byte of BNEP Type +
	 * 1 byte of BNEP Control Type + 1 byte of BNEP services UUID size.
	 */
	if (n < 3) {
		error("To few setup connection request data received");
		return FALSE;
	}

	switch (req->uuid_size) {
	case 2:
		dst_role = get_be16(req->service);
		break;
	case 16:
		if (memcmp(&req->service[4], bt_base, sizeof(bt_base)) != 0)
			break;

		/* Intentional no-brake */

	case 4:
		val = get_be32(req->service);
		if (val > 0xffff)
			break;

		dst_role = val;
		break;
	default:
		break;
	}

	ns = find_server(na->servers, dst_role);
	if (!ns || !ns->record_id || !ns->bridge)
		error("Server error, bridge not initialized: (0x%x)", dst_role);
	else
		bridge = ns->bridge;

	strncpy(na->setup->dev, BNEP_INTERFACE, 16);
	na->setup->dev[15] = '\0';

	if (bnep_server_add(sk, bridge, na->setup->dev, &na->setup->dst,
							packet, n) < 0)
		error("BNEP server cannot be added");

	na->setup = NULL;

	return FALSE;
}