diff --git a/android/pan.c b/android/pan.c
index 2afc92a..a1356eb 100644
--- a/android/pan.c
+++ b/android/pan.c
{
struct pan_device *dev = user_data;
uint8_t packet[BNEP_MTU];
- struct bnep_setup_conn_req *req = (void *) packet;
- uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
+ uint16_t rsp = BNEP_CONN_NOT_ALLOWED;
int sk, n, err;
if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
goto failed;
}
- /* Highest known control command id BNEP_FILTER_MULT_ADDR_RSP 0x06 */
- if (req->type == BNEP_CONTROL &&
- req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
- error("cmd not understood");
- bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_CMD_NOT_UNDERSTOOD,
- req->ctrl);
- goto failed;
- }
-
- if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ) {
- error("cmd is not BNEP_SETUP_CONN_REQ %02X %02X", req->type,
- req->ctrl);
- goto failed;
- }
-
- rsp = bnep_setup_decode(req, &dst_role, &src_role);
- if (rsp != BNEP_SUCCESS) {
- error("bnep_setup_decode failed");
+ if (n < 3) {
+ error("pan: to few setup connection request data received");
goto failed;
}
goto failed;
}
- if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
- &dev->dst) < 0) {
+ if (bnep_server_add(sk, BNEP_BRIDGE, dev->iface, &dev->dst, packet, n)
+ < 0) {
error("pan: server_connadd failed");
rsp = BNEP_CONN_NOT_ALLOWED;
goto failed;
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 0493260..0a41d73 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
return err;
}
-int bnep_server_add(int sk, uint16_t dst, char *bridge, char *iface,
- const bdaddr_t *addr)
-{
- int err;
-
- if (!bridge || !iface || !addr)
- return -EINVAL;
-
- err = bnep_connadd(sk, dst, iface);
- if (err < 0)
- return err;
-
- err = bnep_add_to_bridge(iface, bridge);
- if (err < 0) {
- bnep_conndel(addr);
- return err;
- }
-
- return bnep_if_up(iface);
-}
-
-void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
-{
- if (!bridge || !iface || !addr)
- return;
-
- bnep_del_from_bridge(iface, bridge);
- bnep_if_down(iface);
- bnep_conndel(addr);
-}
-
-ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp)
-{
- struct bnep_control_rsp rsp;
-
- rsp.type = type;
- rsp.ctrl = ctrl;
- rsp.resp = htons(resp);
-
- return send(sk, &rsp, sizeof(rsp), 0);
-}
-
-uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
- uint16_t *src)
+static uint16_t bnep_setup_decode(int sk, struct bnep_setup_conn_req *req,
+ uint16_t *dst)
{
const uint8_t bt_base[] = { 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
+ uint16_t src;
uint8_t *dest, *source;
uint32_t val;
+ if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ)
+ return BNEP_CONN_NOT_ALLOWED;
+
dest = req->service;
source = req->service + req->uuid_size;
switch (req->uuid_size) {
case 2: /* UUID16 */
*dst = get_be16(dest);
- *src = get_be16(source);
+ src = get_be16(source);
break;
case 16: /* UUID128 */
/* Check that the bytes in the UUID, except the service ID
if (val > 0xffff)
return BNEP_CONN_INVALID_SRC;
- *src = val;
+ src = val;
break;
default:
return BNEP_CONN_INVALID_SVC;
switch (*dst) {
case BNEP_SVC_NAP:
case BNEP_SVC_GN:
- if (*src == BNEP_SVC_PANU)
+ if (src == BNEP_SVC_PANU)
return BNEP_SUCCESS;
+
return BNEP_CONN_INVALID_SRC;
case BNEP_SVC_PANU:
- if (*src == BNEP_SVC_PANU || *src == BNEP_SVC_GN ||
- *src == BNEP_SVC_NAP)
+ if (src == BNEP_SVC_PANU || src == BNEP_SVC_GN ||
+ src == BNEP_SVC_NAP)
return BNEP_SUCCESS;
return BNEP_CONN_INVALID_SRC;
return BNEP_CONN_INVALID_DST;
}
+
+int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
+ uint8_t *setup_data, int len)
+{
+ int err;
+ uint16_t dst = NULL;
+ struct bnep_setup_conn_req *req = (void *) setup_data;
+
+ /* Highest known Control command ID
+ * is BNEP_FILTER_MULT_ADDR_RSP = 0x06 */
+ if (req->type == BNEP_CONTROL &&
+ req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
+ uint8_t pkt[3];
+
+ pkt[0] = BNEP_CONTROL;
+ pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
+ pkt[2] = req->ctrl;
+
+ send(sk, pkt, sizeof(pkt), 0);
+
+ return -EINVAL;
+ }
+
+ /* Processing BNEP_SETUP_CONNECTION_REQUEST_MSG */
+ err = bnep_setup_decode(sk, req, &dst);
+ if (err < 0) {
+ error("bnep: error while decoding setup connection request: %d",
+ err);
+ return -EINVAL;
+ }
+
+ if (!bridge || !iface || !addr || !dst)
+ return -EINVAL;
+
+ err = bnep_connadd(sk, dst, iface);
+ if (err < 0)
+ return err;
+
+ err = bnep_add_to_bridge(iface, bridge);
+ if (err < 0) {
+ bnep_conndel(addr);
+ return err;
+ }
+
+ return bnep_if_up(iface);
+}
+
+void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
+{
+ if (!bridge || !iface || !addr)
+ return;
+
+ bnep_del_from_bridge(iface, bridge);
+ bnep_if_down(iface);
+ bnep_conndel(addr);
+}
+
+ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp)
+{
+ struct bnep_control_rsp rsp;
+
+ rsp.type = type;
+ rsp.ctrl = ctrl;
+ rsp.resp = htons(resp);
+
+ return send(sk, &rsp, sizeof(rsp), 0);
+}
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index b0a91e5..2686ea8 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
void *data);
void bnep_disconnect(struct bnep *session);
-int bnep_server_add(int sk, uint16_t dst, char *bridge, char *iface,
- const bdaddr_t *addr);
+int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
+ uint8_t *setup_data, int len);
void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr);
ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp);
-uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
- uint16_t *src);
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 04f188a..4644133 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
#include "src/log.h"
#include "src/error.h"
#include "src/sdpd.h"
+#include "src/shared/util.h"
#include "bnep.h"
#include "server.h"
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 src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
+ uint16_t dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
+ uint32_t val;
int n, sk;
if (cond & G_IO_NVAL)
return FALSE;
}
- /* Highest known Control command ID
- * is BNEP_FILTER_MULT_ADDR_RSP = 0x06 */
- if (req->type == BNEP_CONTROL &&
- req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
- uint8_t pkt[3];
-
- pkt[0] = BNEP_CONTROL;
- pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
- pkt[2] = req->ctrl;
-
- send(sk, pkt, sizeof(pkt), 0);
-
+ /*
+ * 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;
}
- if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ)
- 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)
+ return FALSE;
- rsp = bnep_setup_decode(req, &dst_role, &src_role);
- if (rsp != BNEP_SUCCESS)
- goto reply;
+ /* Intentional no-brake */
- rsp = BNEP_CONN_NOT_ALLOWED;
+ case 4:
+ val = get_be32(req->service);
+ if (val > 0xffff)
+ return FALSE;
+
+ dst_role = val;
+ break;
+ default:
+ return FALSE;
+ }
ns = find_server(na->servers, dst_role);
if (!ns) {
strncpy(na->setup->dev, BNEP_INTERFACE, 16);
na->setup->dev[15] = '\0';
- if (bnep_server_add(sk, dst_role, ns->bridge, na->setup->dev,
- &na->setup->dst) < 0)
+ if (bnep_server_add(sk, ns->bridge, na->setup->dev,
+ &na->setup->dst, packet, n) < 0)
goto reply;
na->setup = NULL;