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; }
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; }