2015-03-03 16:59:45

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 01/15] android/pan: Fix removing PAN NAP bridge

PAN NAP bridge shouldn't be removed if bnep server add fails. Pan device
remove function is decreasing amount of connected devices, if count will
be zero - NAP bridge will be removed.
---
android/pan.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/android/pan.c b/android/pan.c
index 972af89..511f4fd 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -517,7 +517,6 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,

if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
&dev->dst) < 0) {
- nap_remove_bridge();
error("server_connadd failed");
rsp = BNEP_CONN_NOT_ALLOWED;
goto failed;
--
2.1.0



2015-03-09 16:19:17

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: Re: [PATCH v2 04/15] profiles/network: Move bnep connection setup logic to bnep

Hi Szymon,


On 9 March 2015 at 16:14, Szymon Janc <[email protected]> wrote:
> Hi Grzegorz,
>
> On Tuesday 03 of March 2015 17:59:48 Grzegorz Kolodziejczyk wrote:
>> BNEP connection set up logic which was added before bnep_server_add,
>> can be private method of bnep. Moved logic was almost doubled in two
>> cases: NAP role in PAN, server listening. Now set up and connect
>> scenario check of bnep connection is only handled in bnep part for
>> listen connections.
>> ---
>> android/pan.c | 27 ++--------
>> profiles/network/bnep.c | 127 ++++++++++++++++++++++++++++------------------
>> profiles/network/bnep.h | 6 +--
>> profiles/network/server.c | 48 ++++++++++--------
>> 4 files changed, 112 insertions(+), 96 deletions(-)
>>
>> diff --git a/android/pan.c b/android/pan.c
>> index 61b81a4..c4ec349 100644
>> --- a/android/pan.c
>> +++ b/android/pan.c
>> @@ -463,8 +463,7 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
>> {
>> 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)) {
>> @@ -481,24 +480,8 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
>> 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;
>> }
>>
>> @@ -509,8 +492,8 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
>> 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("pann: server_connadd failed");
>> rsp = BNEP_CONN_NOT_ALLOWED;
>> goto failed;
>> diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
>> index 7d78575..160ad1f 100644
>> --- a/profiles/network/bnep.c
>> +++ b/profiles/network/bnep.c
>> @@ -549,63 +549,25 @@ static int bnep_del_from_bridge(const char *devname, const char *bridge)
>> 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
>> @@ -629,7 +591,7 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
>> if (val > 0xffff)
>> return BNEP_CONN_INVALID_SRC;
>>
>> - *src = val;
>> + src = val;
>> break;
>> default:
>> return BNEP_CONN_INVALID_SVC;
>> @@ -639,12 +601,13 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
>> 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;
>> @@ -652,3 +615,69 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
>>
>> 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("error while decoding setup connection request: %d", err);
>
> Lets be consistent and prefix info/error appropriately.
>
OK, will update it in v3.
>> + 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 5aedf38..aa81dcb 100644
>> --- a/profiles/network/bnep.h
>> +++ b/profiles/network/bnep.h
>> @@ -41,10 +41,8 @@ void bnep_set_disconnect(struct bnep *session, bnep_disconnect_cb disconn_cb,
>> 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..30bb190 100644
>> --- a/profiles/network/server.c
>> +++ b/profiles/network/server.c
>> @@ -47,6 +47,7 @@
>> #include "src/log.h"
>> #include "src/error.h"
>> #include "src/sdpd.h"
>> +#include "src/shared/util.h"
>>
>> #include "bnep.h"
>> #include "server.h"
>> @@ -281,11 +282,14 @@ static void setup_destroy(void *user_data)
>> 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)
>> @@ -305,29 +309,31 @@ static gboolean bnep_setup(GIOChannel *chan,
>> 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);
>> -
>> + 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) {
>> @@ -348,8 +354,8 @@ static gboolean bnep_setup(GIOChannel *chan,
>> 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;
>>
>
> --
> Best regards,
> Szymon Janc

BR,
Grzegorz Kołodziejczyk

2015-03-09 16:18:17

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: Re: [PATCH v2 05/15] profiles/network: Handle ctrl rsp after conn setup by bnep

Hi Szymon,


On 9 March 2015 at 16:14, Szymon Janc <[email protected]> wrote:
> Hi Grzegorz,
>
> On Tuesday 03 of March 2015 17:59:49 Grzegorz Kolodziejczyk wrote:
>> This patch moves setup control response to bnep and makes it private.
>> ---
>> android/pan.c | 14 +++--------
>> profiles/network/bnep.c | 61 +++++++++++++++++++++++++++++------------------
>> profiles/network/bnep.h | 2 --
>> profiles/network/server.c | 36 +++++++++-------------------
>> 4 files changed, 52 insertions(+), 61 deletions(-)
>>
>> diff --git a/android/pan.c b/android/pan.c
>> index c4ec349..72d8a73 100644
>> --- a/android/pan.c
>> +++ b/android/pan.c
>> @@ -463,7 +463,6 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
>> {
>> struct pan_device *dev = user_data;
>> uint8_t packet[BNEP_MTU];
>> - uint16_t rsp = BNEP_CONN_NOT_ALLOWED;
>> int sk, n, err;
>>
>> if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
>> @@ -486,22 +485,16 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
>> }
>>
>> err = nap_create_bridge();
>> - if (err < 0) {
>> + if (err < 0)
>> error("pan: Failed to create bridge: %s (%d)", strerror(-err),
>> -err);
>> - goto failed;
>> - }
>>
>> - if (bnep_server_add(sk, BNEP_BRIDGE, dev->iface, &dev->dst, packet, n)
>> - < 0) {
>> + if (bnep_server_add(sk, (err < 0) ? NULL : BNEP_BRIDGE, dev->iface,
>> + &dev->dst, packet, n) < 0) {
>> error("pann: server_connadd failed");
>> - rsp = BNEP_CONN_NOT_ALLOWED;
>> goto failed;
>> }
>>
>> - rsp = BNEP_SUCCESS;
>> - bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
>> -
>> 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);
>> @@ -513,7 +506,6 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
>> return FALSE;
>>
>> failed:
>> - bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
>> pan_device_remove(dev);
>>
>> return FALSE;
>> diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
>> index 160ad1f..e8f9698 100644
>> --- a/profiles/network/bnep.c
>> +++ b/profiles/network/bnep.c
>> @@ -549,6 +549,18 @@ static int bnep_del_from_bridge(const char *devname, const char *bridge)
>> return err;
>> }
>>
>> +static 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);
>> +}
>> +
>> static uint16_t bnep_setup_decode(int sk, struct bnep_setup_conn_req *req,
>> uint16_t *dst)
>> {
>> @@ -603,7 +615,6 @@ static uint16_t bnep_setup_decode(int sk, struct bnep_setup_conn_req *req,
>> case BNEP_SVC_GN:
>> 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 ||
>> @@ -620,7 +631,7 @@ 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;
>> + uint16_t rsp, dst = NULL;
>> struct bnep_setup_conn_req *req = (void *) setup_data;
>>
>> /* Highest known Control command ID
>> @@ -639,26 +650,41 @@ int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
>> }
>>
>> /* Processing BNEP_SETUP_CONNECTION_REQUEST_MSG */
>> - err = bnep_setup_decode(sk, req, &dst);
>> - if (err < 0) {
>> - error("error while decoding setup connection request: %d", err);
>> - return -EINVAL;
>> + rsp = bnep_setup_decode(sk, req, &dst);
>> + if (rsp != BNEP_SUCCESS || !dst) {
>> + err = -rsp;
>> + error("bnep: error while decoding setup connection request: %d",
>> + rsp);
>> + goto reply;
>> }
>>
>> - if (!bridge || !iface || !addr || !dst)
>> - return -EINVAL;
>> + if (!dst) {
>> + error("bnep: cannot decode proper destination service UUID");
>> + rsp = BNEP_CONN_INVALID_DST;
>> + goto reply;
>> + }
>>
>> err = bnep_connadd(sk, dst, iface);
>> - if (err < 0)
>> - return err;
>> + if (err < 0) {
>> + rsp = BNEP_CONN_NOT_ALLOWED;
>> + goto reply;
>> + }
>>
>> err = bnep_add_to_bridge(iface, bridge);
>> if (err < 0) {
>> bnep_conndel(addr);
>> - return err;
>> + rsp = BNEP_CONN_NOT_ALLOWED;
>> + goto reply;
>> }
>>
>> - return bnep_if_up(iface);
>> + err = bnep_if_up(iface);
>> + if (err < 0)
>> + rsp = BNEP_CONN_NOT_ALLOWED;
>> +
>> +reply:
>> + bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
>> +
>> + return err;
>> }
>>
>> void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
>> @@ -670,14 +696,3 @@ void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
>> 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 aa81dcb..4fe79ed 100644
>> --- a/profiles/network/bnep.h
>> +++ b/profiles/network/bnep.h
>> @@ -44,5 +44,3 @@ void bnep_disconnect(struct bnep *session);
>> 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);
>> diff --git a/profiles/network/server.c b/profiles/network/server.c
>> index 30bb190..5d2fbcc 100644
>> --- a/profiles/network/server.c
>> +++ b/profiles/network/server.c
>> @@ -288,9 +288,10 @@ static gboolean bnep_setup(GIOChannel *chan,
>> struct network_server *ns;
>> uint8_t packet[BNEP_MTU];
>> struct bnep_setup_conn_req *req = (void *) packet;
>> - uint16_t dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
>> + uint16_t dst_role = 0;
>> uint32_t val;
>> int n, sk;
>> + char *bridge = NULL;
>>
>> if (cond & G_IO_NVAL)
>> return FALSE;
>> @@ -320,51 +321,36 @@ static gboolean bnep_setup(GIOChannel *chan,
>> break;
>> case 16:
>> if (memcmp(&req->service[4], bt_base, sizeof(bt_base)) != 0)
>> - return FALSE;
>> + break;
>>
>> /* Intentional no-brake */
>>
>> case 4:
>> val = get_be32(req->service);
>> if (val > 0xffff)
>> - return FALSE;
>> + break;
>>
>> dst_role = val;
>> break;
>> default:
>> - return FALSE;
>> + break;
>> }
>>
>> ns = find_server(na->servers, dst_role);
>> - if (!ns) {
>> - error("Server unavailable: (0x%x)", dst_role);
>> - goto reply;
>> - }
>> -
>> - if (!ns->record_id) {
>> - error("Service record not available");
>> - goto reply;
>> - }
>> + if (!ns || !ns->record_id || !ns->bridge)
>> + error("Server error, bridge not initialized: (0x%x)", dst_role);
>
> Lets be consistent and prefix info/error appropriately.
This file don't have any consistent prefixes, so that's why I've
decided to not do it here also.

>>
>> - if (!ns->bridge) {
>> - error("Bridge interface not configured");
>> - goto reply;
>> - }
>> + bridge = ns->bridge;
>
> This would dereference possibly null ns.
>
Right, I'll fix it in v3.

>>
>> strncpy(na->setup->dev, BNEP_INTERFACE, 16);
>> na->setup->dev[15] = '\0';
>>
>> - if (bnep_server_add(sk, ns->bridge, na->setup->dev,
>> - &na->setup->dst, packet, n) < 0)
>> - goto reply;
>> + if (bnep_server_add(sk, bridge, na->setup->dev, &na->setup->dst,
>> + packet, n) < 0)
>> + error("BNEP server cannot be added");
>>
>> na->setup = NULL;
>>
>> - rsp = BNEP_SUCCESS;
>> -
>> -reply:
>> - bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
>> -
>> return FALSE;
>> }
>>
>>
>
> --
> Best regards,
> Szymon Janc

BR,
Grzegorz Kołodziejczyk

2015-03-09 15:20:56

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH v2 01/15] android/pan: Fix removing PAN NAP bridge

Hi Grzegorz,

On Tuesday 03 of March 2015 17:59:45 Grzegorz Kolodziejczyk wrote:
> PAN NAP bridge shouldn't be removed if bnep server add fails. Pan device
> remove function is decreasing amount of connected devices, if count will
> be zero - NAP bridge will be removed.
> ---
> android/pan.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/android/pan.c b/android/pan.c
> index 972af89..511f4fd 100644
> --- a/android/pan.c
> +++ b/android/pan.c
> @@ -517,7 +517,6 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
>
> if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
> &dev->dst) < 0) {
> - nap_remove_bridge();
> error("server_connadd failed");
> rsp = BNEP_CONN_NOT_ALLOWED;
> goto failed;
>

Patches 1-3 and updated 8-9 are now applied.

--
Best regards,
Szymon Janc

2015-03-09 15:14:56

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH v2 05/15] profiles/network: Handle ctrl rsp after conn setup by bnep

Hi Grzegorz,

On Tuesday 03 of March 2015 17:59:49 Grzegorz Kolodziejczyk wrote:
> This patch moves setup control response to bnep and makes it private.
> ---
> android/pan.c | 14 +++--------
> profiles/network/bnep.c | 61 +++++++++++++++++++++++++++++------------------
> profiles/network/bnep.h | 2 --
> profiles/network/server.c | 36 +++++++++-------------------
> 4 files changed, 52 insertions(+), 61 deletions(-)
>
> diff --git a/android/pan.c b/android/pan.c
> index c4ec349..72d8a73 100644
> --- a/android/pan.c
> +++ b/android/pan.c
> @@ -463,7 +463,6 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
> {
> struct pan_device *dev = user_data;
> uint8_t packet[BNEP_MTU];
> - uint16_t rsp = BNEP_CONN_NOT_ALLOWED;
> int sk, n, err;
>
> if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
> @@ -486,22 +485,16 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
> }
>
> err = nap_create_bridge();
> - if (err < 0) {
> + if (err < 0)
> error("pan: Failed to create bridge: %s (%d)", strerror(-err),
> -err);
> - goto failed;
> - }
>
> - if (bnep_server_add(sk, BNEP_BRIDGE, dev->iface, &dev->dst, packet, n)
> - < 0) {
> + if (bnep_server_add(sk, (err < 0) ? NULL : BNEP_BRIDGE, dev->iface,
> + &dev->dst, packet, n) < 0) {
> error("pann: server_connadd failed");
> - rsp = BNEP_CONN_NOT_ALLOWED;
> goto failed;
> }
>
> - rsp = BNEP_SUCCESS;
> - bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
> -
> 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);
> @@ -513,7 +506,6 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
> return FALSE;
>
> failed:
> - bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
> pan_device_remove(dev);
>
> return FALSE;
> diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
> index 160ad1f..e8f9698 100644
> --- a/profiles/network/bnep.c
> +++ b/profiles/network/bnep.c
> @@ -549,6 +549,18 @@ static int bnep_del_from_bridge(const char *devname, const char *bridge)
> return err;
> }
>
> +static 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);
> +}
> +
> static uint16_t bnep_setup_decode(int sk, struct bnep_setup_conn_req *req,
> uint16_t *dst)
> {
> @@ -603,7 +615,6 @@ static uint16_t bnep_setup_decode(int sk, struct bnep_setup_conn_req *req,
> case BNEP_SVC_GN:
> 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 ||
> @@ -620,7 +631,7 @@ 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;
> + uint16_t rsp, dst = NULL;
> struct bnep_setup_conn_req *req = (void *) setup_data;
>
> /* Highest known Control command ID
> @@ -639,26 +650,41 @@ int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
> }
>
> /* Processing BNEP_SETUP_CONNECTION_REQUEST_MSG */
> - err = bnep_setup_decode(sk, req, &dst);
> - if (err < 0) {
> - error("error while decoding setup connection request: %d", err);
> - return -EINVAL;
> + rsp = bnep_setup_decode(sk, req, &dst);
> + if (rsp != BNEP_SUCCESS || !dst) {
> + err = -rsp;
> + error("bnep: error while decoding setup connection request: %d",
> + rsp);
> + goto reply;
> }
>
> - if (!bridge || !iface || !addr || !dst)
> - return -EINVAL;
> + if (!dst) {
> + error("bnep: cannot decode proper destination service UUID");
> + rsp = BNEP_CONN_INVALID_DST;
> + goto reply;
> + }
>
> err = bnep_connadd(sk, dst, iface);
> - if (err < 0)
> - return err;
> + if (err < 0) {
> + rsp = BNEP_CONN_NOT_ALLOWED;
> + goto reply;
> + }
>
> err = bnep_add_to_bridge(iface, bridge);
> if (err < 0) {
> bnep_conndel(addr);
> - return err;
> + rsp = BNEP_CONN_NOT_ALLOWED;
> + goto reply;
> }
>
> - return bnep_if_up(iface);
> + err = bnep_if_up(iface);
> + if (err < 0)
> + rsp = BNEP_CONN_NOT_ALLOWED;
> +
> +reply:
> + bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
> +
> + return err;
> }
>
> void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
> @@ -670,14 +696,3 @@ void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
> 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 aa81dcb..4fe79ed 100644
> --- a/profiles/network/bnep.h
> +++ b/profiles/network/bnep.h
> @@ -44,5 +44,3 @@ void bnep_disconnect(struct bnep *session);
> 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);
> diff --git a/profiles/network/server.c b/profiles/network/server.c
> index 30bb190..5d2fbcc 100644
> --- a/profiles/network/server.c
> +++ b/profiles/network/server.c
> @@ -288,9 +288,10 @@ static gboolean bnep_setup(GIOChannel *chan,
> struct network_server *ns;
> uint8_t packet[BNEP_MTU];
> struct bnep_setup_conn_req *req = (void *) packet;
> - uint16_t dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
> + uint16_t dst_role = 0;
> uint32_t val;
> int n, sk;
> + char *bridge = NULL;
>
> if (cond & G_IO_NVAL)
> return FALSE;
> @@ -320,51 +321,36 @@ static gboolean bnep_setup(GIOChannel *chan,
> break;
> case 16:
> if (memcmp(&req->service[4], bt_base, sizeof(bt_base)) != 0)
> - return FALSE;
> + break;
>
> /* Intentional no-brake */
>
> case 4:
> val = get_be32(req->service);
> if (val > 0xffff)
> - return FALSE;
> + break;
>
> dst_role = val;
> break;
> default:
> - return FALSE;
> + break;
> }
>
> ns = find_server(na->servers, dst_role);
> - if (!ns) {
> - error("Server unavailable: (0x%x)", dst_role);
> - goto reply;
> - }
> -
> - if (!ns->record_id) {
> - error("Service record not available");
> - goto reply;
> - }
> + if (!ns || !ns->record_id || !ns->bridge)
> + error("Server error, bridge not initialized: (0x%x)", dst_role);

Lets be consistent and prefix info/error appropriately.
>
> - if (!ns->bridge) {
> - error("Bridge interface not configured");
> - goto reply;
> - }
> + bridge = ns->bridge;

This would dereference possibly null ns.

>
> strncpy(na->setup->dev, BNEP_INTERFACE, 16);
> na->setup->dev[15] = '\0';
>
> - if (bnep_server_add(sk, ns->bridge, na->setup->dev,
> - &na->setup->dst, packet, n) < 0)
> - goto reply;
> + if (bnep_server_add(sk, bridge, na->setup->dev, &na->setup->dst,
> + packet, n) < 0)
> + error("BNEP server cannot be added");
>
> na->setup = NULL;
>
> - rsp = BNEP_SUCCESS;
> -
> -reply:
> - bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
> -
> return FALSE;
> }
>
>

--
Best regards,
Szymon Janc

2015-03-09 15:14:59

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH v2 04/15] profiles/network: Move bnep connection setup logic to bnep

Hi Grzegorz,

On Tuesday 03 of March 2015 17:59:48 Grzegorz Kolodziejczyk wrote:
> BNEP connection set up logic which was added before bnep_server_add,
> can be private method of bnep. Moved logic was almost doubled in two
> cases: NAP role in PAN, server listening. Now set up and connect
> scenario check of bnep connection is only handled in bnep part for
> listen connections.
> ---
> android/pan.c | 27 ++--------
> profiles/network/bnep.c | 127 ++++++++++++++++++++++++++++------------------
> profiles/network/bnep.h | 6 +--
> profiles/network/server.c | 48 ++++++++++--------
> 4 files changed, 112 insertions(+), 96 deletions(-)
>
> diff --git a/android/pan.c b/android/pan.c
> index 61b81a4..c4ec349 100644
> --- a/android/pan.c
> +++ b/android/pan.c
> @@ -463,8 +463,7 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
> {
> 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)) {
> @@ -481,24 +480,8 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
> 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;
> }
>
> @@ -509,8 +492,8 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
> 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("pann: server_connadd failed");
> rsp = BNEP_CONN_NOT_ALLOWED;
> goto failed;
> diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
> index 7d78575..160ad1f 100644
> --- a/profiles/network/bnep.c
> +++ b/profiles/network/bnep.c
> @@ -549,63 +549,25 @@ static int bnep_del_from_bridge(const char *devname, const char *bridge)
> 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
> @@ -629,7 +591,7 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
> if (val > 0xffff)
> return BNEP_CONN_INVALID_SRC;
>
> - *src = val;
> + src = val;
> break;
> default:
> return BNEP_CONN_INVALID_SVC;
> @@ -639,12 +601,13 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
> 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;
> @@ -652,3 +615,69 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
>
> 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("error while decoding setup connection request: %d", err);

Lets be consistent and prefix info/error appropriately.

> + 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 5aedf38..aa81dcb 100644
> --- a/profiles/network/bnep.h
> +++ b/profiles/network/bnep.h
> @@ -41,10 +41,8 @@ void bnep_set_disconnect(struct bnep *session, bnep_disconnect_cb disconn_cb,
> 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..30bb190 100644
> --- a/profiles/network/server.c
> +++ b/profiles/network/server.c
> @@ -47,6 +47,7 @@
> #include "src/log.h"
> #include "src/error.h"
> #include "src/sdpd.h"
> +#include "src/shared/util.h"
>
> #include "bnep.h"
> #include "server.h"
> @@ -281,11 +282,14 @@ static void setup_destroy(void *user_data)
> 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)
> @@ -305,29 +309,31 @@ static gboolean bnep_setup(GIOChannel *chan,
> 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);
> -
> + 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) {
> @@ -348,8 +354,8 @@ static gboolean bnep_setup(GIOChannel *chan,
> 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;
>

--
Best regards,
Szymon Janc

2015-03-03 16:59:59

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 15/15] android/pts: Add BNEP PTS 6.0 results for android 5.0

This patch adds test case list and results for BNEP profile against
android 5.0
---
android/pics-bnep.txt | 26 ++++++++++++++
android/pixit-bnep.txt | 30 ++++++++++++++++
android/pts-bnep.txt | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 148 insertions(+)
create mode 100644 android/pics-bnep.txt
create mode 100644 android/pixit-bnep.txt
create mode 100644 android/pts-bnep.txt

diff --git a/android/pics-bnep.txt b/android/pics-bnep.txt
new file mode 100644
index 0000000..2279c9a
--- /dev/null
+++ b/android/pics-bnep.txt
@@ -0,0 +1,26 @@
+BNEP PICS for the PTS tool.
+
+PTS version: 6.0
+
+* - different than PTS defaults
+# - not yet implemented/supported
+
+M - mandatory if such role selected
+O - optional
+
+ Profile Version
+-------------------------------------------------------------------------------
+Parameter Name Selected Description
+-------------------------------------------------------------------------------
+TSPC_BNEP_1_1 True BNEP Connection Setup (M)
+TSPC_BNEP_1_2 False BNEP Data Packet Reception (M)
+TSPC_BNEP_1_3 False BNEP Data Packet Transmission (M)
+TSPC_BNEP_1_3a False BNEP Compressed Packet Transmission (O)
+TSPC_BNEP_1_3b False BNEP Compressed Packet Transmission Source Only
+ (O)
+TSPC_BNEP_1_4 True BNEP Control Message Processing (M)
+TSPC_BNEP_1_5 True BNEP Extension Header Processing (M)
+TSPC_BNEP_1_6 True Network Protocol Filter Message Transmission (O)
+TSPC_BNEP_1_7 True Multicast Address Filter Message Transmission
+ (O)
+-------------------------------------------------------------------------------
diff --git a/android/pixit-bnep.txt b/android/pixit-bnep.txt
new file mode 100644
index 0000000..9a26cd2
--- /dev/null
+++ b/android/pixit-bnep.txt
@@ -0,0 +1,30 @@
+BNEP PIXIT for the PTS tool.
+
+PTS version: 6.0
+
+* - different than PTS defaults
+& - should be set to IUT Bluetooth address
+# - should be set to PTS's bin/audio folder
+
+Required PIXIT settings
+-------------------------------------------------------------------------------
+Parameter Name Value
+-------------------------------------------------------------------------------
+TSPX_class_of_device 04041C
+TSPX_security_control_data
+TSPX_content_protection_data
+TSPX_bd_addr_iut 112233445566 (*&)
+TSPX_delete_link_key FALSE
+TSPX_pin_code 1234
+TSPX_security_enabled FALSE
+TSPX_time_guard 300000
+TSPX_use_implicit_send TRUE
+TSPX_auth_password 0000
+TSPX_auth_user_id PTS
+TSPX_l2cap_psm 000F
+TSPX_rfcomm_channel 8
+TSPX_no_confirmations FALSE
+TSPX_UUID_dest_address 1116
+TSPX_UUID_source_address 1115
+TSPX_MAC_dest_address 000000000000 (*&)
+TSPX_MAC_source_address 000000000000 (*&)
diff --git a/android/pts-bnep.txt b/android/pts-bnep.txt
new file mode 100644
index 0000000..7945385
--- /dev/null
+++ b/android/pts-bnep.txt
@@ -0,0 +1,92 @@
+PTS test results for BNEP
+
+PTS version: 6.0
+Tested: 03-March-2015
+Android version: 5.0
+Kernel version: 3.20
+
+Results:
+PASS test passed
+FAIL test failed
+INC test is inconclusive
+N/A test is disabled due to PICS setup
+
+--------------------------------------------------------------------------------
+Test Name Result Notes
+--------------------------------------------------------------------------------
+TC_CTRL_BV_01_C PASS bneptest -s
+TC_CTRL_BV_02_C PASS bneptest -c <PTS addr>
+TC_CTRL_BV_03_C PASS bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_CTRL_BV_04_C INC PTS issue #13169
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_CTRL_BV_05_C INC PTS issue #13169
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_CTRL_BV_06_C INC PTS issue #13169
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_CTRL_BV_07_C INC PTS issue #13170
+ bneptest -c <PTS addr> -t 3 -d 0 -e 1500
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_CTRL_BV_08_C INC PTS issue #13169
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_CTRL_BV_09_C INC PTS issue #13170
+ bneptest -c 00:1b:dc:06:06:ca -n enp0s29u1u7
+ -t 5 -g 00:00:00:00:00:00
+ -j ff:ff:ff:ff:ff:ff
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_CTRL_BV_10_C INC PTS issue #13169
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_CTRL_BV_19_C INC PTS issue #13169
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_RX_TYPE_0_BV_11_C N/A
+TC_RX_C_BV_12_C N/A
+TC_RX_C_S_BV_13_C N/A
+TC_RX_C_S_BV_14_C N/A
+TC_RX_TYPE_0_BV_15_C INC PTS issue #13169
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_RX_TYPE_0_BV_16_C INC PTS issue #13171
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_RX_TYPE_0_BV_17_C INC PTS issue #13169
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_RX_TYPE_0_BV_18_C INC PTS issue #13171
+ bneptest -s
+ Note: could be necessary setting approperiate
+ naming of interface using option
+ -n <iface name>, eg. -n enp0s29u1u7
+TC_TX_TYPE_0_BV_20_C N/A
+TC_TX_C_BV_21_C N/A
+TC_TX_C_S_BV_22_C N/A
+TC_TX_C_D_BV_23_C N/A
--
2.1.0


2015-03-03 16:59:58

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 14/15] tools/bneptest: Add generic connect/listen funcionality

This patch adds general funcionality of bnep connect and listen.
---
tools/bneptest.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 548 insertions(+), 5 deletions(-)

diff --git a/tools/bneptest.c b/tools/bneptest.c
index cafeba9..251b71d 100644
--- a/tools/bneptest.c
+++ b/tools/bneptest.c
@@ -26,43 +26,549 @@
#endif

#include <stdio.h>
+#include <signal.h>
#include <stdlib.h>
#include <getopt.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#include <netinet/in.h>
+#include <linux/if_bridge.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>

#include <glib.h>

#include "src/log.h"
+#include "btio/btio.h"
+#include "lib/bnep.h"
+#include "profiles/network/bnep.h"
+
+enum {
+ MODE_NONE,
+ MODE_CONNECT,
+ MODE_LISTEN,
+};

static GMainLoop *mloop;
+static GIOChannel *bnep_io;
+
+static int mode;
+static bool no_close_after_disconn;
+static int send_ctrl_frame_timeout;
+
+static bdaddr_t src_addr, dst_addr;
+static char iface[16] = "nap_iface%d";
+static char bridge[16] = "bnep_bridge";
+static uint8_t send_msg_type = 0x00;
+static uint16_t local_role = BNEP_SVC_PANU;
+static uint16_t remote_role = BNEP_SVC_NAP;
+static uint16_t ntw_proto_down_range = 0x0000;
+static uint16_t ntw_proto_up_range = 0xdc05;
+static uint8_t mcast_addr_down_range[6] = { 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00 };
+static uint8_t mcast_addr_up_range[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+static struct bnep *session;
+
+
+static int set_forward_delay(int sk)
+{
+ unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 0, 0, 0 };
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
+ ifr.ifr_data = (char *) args;
+
+ if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0) {
+ error("setting forward delay failed: %d (%s)",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int nap_create_bridge(void)
+{
+ int sk, err;
+
+ sk = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return -EOPNOTSUPP;
+
+ if (ioctl(sk, SIOCBRADDBR, bridge) < 0) {
+ err = -errno;
+ if (err != -EEXIST) {
+ close(sk);
+ return -EOPNOTSUPP;
+ }
+ }
+
+ err = set_forward_delay(sk);
+ if (err < 0) {
+ printf("failed to set forward delay\n");
+ ioctl(sk, SIOCBRDELBR, bridge);
+ }
+
+ close(sk);
+
+ return err;
+}
+
+static int cleanup(void)
+{
+ bnep_cleanup();
+
+ if (mode == MODE_LISTEN)
+ bnep_server_delete(bridge, iface, &dst_addr);
+
+ if (bnep_io) {
+ g_io_channel_shutdown(bnep_io, TRUE, NULL);
+ g_io_channel_unref(bnep_io);
+ }
+
+ return 0;
+}
+
+static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ printf("%s\n", __func__);
+
+ if (no_close_after_disconn)
+ return FALSE;
+
+ /* Cleanup since it's called when disconnected l2cap */
+ if (cleanup() < 0) {
+ printf("cleanup went wrong...\n");
+ return FALSE;
+ }
+
+ g_main_loop_quit(mloop);
+ return FALSE;
+}
+
+static ssize_t send_ctrl_frame(int sk)
+{
+ /* Max buff size = type(1byte) + ctrl(1byte) + len(2byte) +
+ * mcast_addr_down(6byte) + mcast_addr_up(6byte) */
+ uint8_t buff[16];
+ int err;
+
+ printf("%s\n", __func__);
+
+ if (send_ctrl_frame_timeout > 0) {
+ printf("waiting %d seconds before sending msg\n",
+ send_ctrl_frame_timeout);
+ sleep(send_ctrl_frame_timeout);
+ }
+
+ switch (send_msg_type) {
+ case BNEP_FILTER_NET_TYPE_SET: {
+ struct bnep_set_filter_req *frame = (void *)buff;
+
+ frame->type = BNEP_CONTROL;
+ frame->ctrl = send_msg_type;
+ frame->len = htons(sizeof(ntw_proto_down_range) +
+ sizeof(ntw_proto_up_range));
+ memcpy(frame->list, &ntw_proto_down_range,
+ sizeof(ntw_proto_down_range));
+ memcpy(frame->list + sizeof(ntw_proto_down_range),
+ &ntw_proto_up_range, sizeof(ntw_proto_up_range));
+
+ err = send(sk, frame, sizeof(*frame) +
+ sizeof(ntw_proto_down_range) +
+ sizeof(ntw_proto_up_range), 0);
+
+ break;
+
+ }
+ case BNEP_FILTER_MULT_ADDR_SET: {
+ struct bnep_set_filter_req *frame = (void *)buff;
+
+ frame->type = BNEP_CONTROL;
+ frame->ctrl = send_msg_type;
+ frame->len = htons(sizeof(mcast_addr_down_range) +
+ sizeof(mcast_addr_up_range));
+ memcpy(frame->list, mcast_addr_down_range,
+ sizeof(mcast_addr_down_range));
+ memcpy(frame->list + sizeof(mcast_addr_down_range),
+ mcast_addr_up_range, sizeof(mcast_addr_up_range));
+
+ err = send(sk, frame, sizeof(*frame) +
+ sizeof(mcast_addr_down_range) +
+ sizeof(mcast_addr_up_range), 0);
+
+ break;
+
+ }
+ default:
+ err = -1;
+ }
+
+ return err;
+}
+
+static gboolean setup_bnep_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer user_data)
+{
+ uint8_t packet[BNEP_MTU];
+ int sk, n, err;
+
+ printf("%s\n", __func__);
+
+ 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);
+
+ /* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */
+ n = read(sk, packet, sizeof(packet));
+ if (n < 0) {
+ error("read(): %s(%d)", strerror(errno), errno);
+ return FALSE;
+ }
+
+ err = nap_create_bridge();
+ if (err < 0) {
+ error("failed to create bridge: %s (%d)", strerror(-err), err);
+ return FALSE;
+ }
+
+ if (bnep_server_add(sk, (err < 0) ? NULL : bridge, iface, &dst_addr,
+ packet, n) < 0) {
+ printf("server_connadd failed\n");
+ cleanup();
+ return FALSE;
+ }
+
+ g_io_add_watch(chan, G_IO_HUP | G_IO_ERR | G_IO_NVAL, bnep_watchdog_cb,
+ NULL);
+
+ if (send_msg_type) {
+ if (send_ctrl_frame(sk) < 0)
+ printf("error while sending ctrl frame : %s (%d)\n",
+ strerror(errno), errno);
+ }
+
+ g_io_channel_unref(bnep_io);
+ bnep_io = NULL;
+
+ return FALSE;
+}
+
+static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ printf("%s\n", __func__);
+
+ if (err) {
+ error("%s", err->message);
+ return;
+ }
+
+ g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ setup_bnep_cb, NULL);
+}
+
+static void connected_client_cb(char *iface, int err, void *data)
+{
+ int sk = *((int *)data);
+
+ printf("%s\n", __func__);
+
+ free(data);
+
+ if (send_msg_type) {
+ if (send_ctrl_frame(sk) < 0)
+ printf("error while sendind ctrl frame : %s (%d)\n",
+ strerror(errno), errno);
+ }
+}
+
+static void disconnected_client_cb(void *data)
+{
+ printf("%s\n", __func__);
+
+ if (no_close_after_disconn)
+ return;
+
+ /* Cleanup since it's called when disconnected l2cap */
+ if (cleanup() < 0) {
+ printf("cleanup went wrong...\n");
+ return;
+ }
+
+ g_main_loop_quit(mloop);
+}
+
+static void connect_client_cb(GIOChannel *chan, GError *err, gpointer user_data)
+{
+ int perr;
+ int *sk;
+
+ sk = malloc(sizeof(*sk));
+
+ *sk = g_io_channel_unix_get_fd(bnep_io);
+
+ session = bnep_new(*sk, local_role, remote_role, bridge);
+ if (!session) {
+ printf("cannot create bnep session\n");
+ free(sk);
+ return;
+ }
+
+ perr = bnep_connect(session, connected_client_cb,
+ disconnected_client_cb, sk, NULL);
+ if (perr < 0)
+ printf("cannot initiate bnep connection\n");
+}
+
+static void confirm_cb(GIOChannel *chan, gpointer data)
+{
+ GError *err = NULL;
+ char address[18];
+
+ printf("%s\n", __func__);
+
+ bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst_addr, BT_IO_OPT_DEST,
+ address, BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ return;
+ }
+
+ printf("incoming connection from: %s\n", address);
+
+ bnep_io = g_io_channel_ref(chan);
+ g_io_channel_set_close_on_unref(bnep_io, TRUE);
+
+ if (!bt_io_accept(bnep_io, connect_cb, NULL, NULL, &err)) {
+ error("bt_io_accept: %s", err->message);
+ g_error_free(err);
+ }
+}
+
+static int bnep_server_listen(void)
+{
+ GError *gerr = NULL;
+
+ printf("%s\n", __func__);
+
+ bnep_io = bt_io_listen(NULL, confirm_cb, NULL, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &src_addr,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+
+ if (!bnep_io) {
+ printf("can't start server listening: err %s\n", gerr->message);
+ g_error_free(gerr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int bnep_client_connect(void)
+{
+ GError *gerr = NULL;
+ char *dst_addr_str = batostr(&dst_addr);
+
+ printf("%s\n", __func__);
+
+ printf("connecting %s\n", dst_addr_str);
+ free(dst_addr_str);
+
+ bnep_io = bt_io_connect(connect_client_cb, NULL, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &src_addr,
+ BT_IO_OPT_DEST_BDADDR, &dst_addr,
+ BT_IO_OPT_PSM, BNEP_PSM,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_OMTU, BNEP_MTU,
+ BT_IO_OPT_IMTU, BNEP_MTU,
+ BT_IO_OPT_INVALID);
+
+ if (!bnep_io) {
+ printf("cannot connect: err %s\n", gerr->message);
+ g_error_free(gerr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void exit_handler(int sig)
+{
+ printf("got sig = %d, cleaning up...\n", sig);
+
+ if (cleanup() < 0)
+ printf("cleanup failure...\n");
+ else
+ printf("cleanup successful - exit\n");
+
+ exit(0);
+}

static void usage(void)
{
printf("bneptest - BNEP testing ver %s\n", VERSION);
printf("Usage:\n"
- "\tbneptest [options]\n");
+ "\tbneptest <connection mode> [send_ctrl_cmd] [options]\n");
+ printf("Connect Mode:\n"
+ "\t-c connect <dst_addr>\n"
+ "\t-r remote role <16 bit svc value>\n"
+ "\t-l local role <16 bit svc valu>\n");
+ printf("Listen Mode:\n"
+ "\t-s start server listening\n");
+ printf("Send control command:\n"
+ "\t-t send message type <control msg type>\n"
+ "\t-T send message timeout after setup <seconds>\n"
+ "\t-e starting network protocol type range <16 bit value>\n"
+ "\t-d ending network protocol type range <16 bit value>\n"
+ "\t-g starting multicast addr range <xx:xx:xx:xx:xx:xx>\n"
+ "\t-j ending multicast addr range <xx:xx:xx:xx:xx:xx>\n");
+ printf("Options:\n"
+ "\t-b bridge name <string>\n"
+ "\t-n interface name <string>\n");
}

static struct option main_options[] = {
- { "help", 0, 0, 'h' },
+ { "device", 1, 0, 'i' },
+ { "listen", 0, 0, 's' },
+ { "connect", 1, 0, 'c' },
+ { "snd_msg_type", 1, 0, 't' },
+ { "send_timeout", 1, 0, 'T' },
+ { "ntw_proto_down_range", 1, 0, 'd' },
+ { "ntw_proto_up_range", 1, 0, 'e' },
+ { "mcast_addr_down_range", 1, 0, 'g' },
+ { "mcast_addr_up_range", 1, 0, 'j' },
+ { "local_role", 1, 0, 'l' },
+ { "remote_role", 1, 0, 'r' },
+ { "bridge name", 1, 0, 'b' },
+ { "iface name", 1, 0, 'n' },
+ { "no_close", 0, 0, 'N' },
+ { "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
};

int main(int argc, char *argv[])
{
int opt;
+ int err;

DBG("");

+ signal(SIGINT, exit_handler);
+
+ hci_devba(0, &src_addr);
+ bacpy(&src_addr, BDADDR_ANY);
+
mloop = g_main_loop_new(NULL, FALSE);
if (!mloop) {
- printf("Cannot create main loop\n");
+ printf("cannot create main loop\n");

exit(1);
}

- while ((opt = getopt_long(argc, argv, "h", main_options, NULL))
- != EOF) {
+ while ((opt = getopt_long(argc, argv, "+i:b:n:c:t:T:d:e:g:j:Nsh",
+ main_options, NULL)) != EOF) {
switch (opt) {
+ case 'i':
+ if (!strncmp(optarg, "hci", 3))
+ hci_devba(atoi(optarg + 3), &src_addr);
+ else
+ str2ba(optarg, &src_addr);
+
+ break;
+
+ case 's':
+ mode = MODE_LISTEN;
+ break;
+
+ case 'c':
+ str2ba(optarg, &dst_addr);
+ mode = MODE_CONNECT;
+
+ break;
+
+ case 't':
+ send_msg_type = atoi(optarg);
+
+ break;
+
+ case 'T':
+ send_ctrl_frame_timeout = atoi(optarg);
+
+ break;
+
+ case 'd':
+ ntw_proto_down_range = htons(atoi(optarg));
+
+ break;
+
+ case 'e':
+ ntw_proto_up_range = htons(atoi(optarg));
+
+ break;
+
+ case 'g': {
+ int i = 0;
+
+ for (i = 5; i >= 0; i--, optarg += 3)
+ mcast_addr_down_range[i] =
+ strtol(optarg, NULL, 16);
+
+ break;
+ }
+
+ case 'j': {
+ int i = 0;
+
+ for (i = 5; i >= 0; i--, optarg += 3)
+ mcast_addr_up_range[i] =
+ strtol(optarg, NULL, 16);
+
+ break;
+ }
+
+ case 'l':
+ local_role = atoi(optarg);
+
+ break;
+
+ case 'r':
+ remote_role = atoi(optarg);
+
+ break;
+
+ case 'b':
+ strncpy(bridge, optarg, 16);
+ bridge[15] = '\0';
+
+ break;
+
+ case 'n':
+ strncpy(iface, optarg, 16);
+ iface[15] = '\0';
+
+ break;
+
+ case 'N':
+ no_close_after_disconn = true;
+
+ break;
+
case 'h':
default:
usage();
@@ -70,5 +576,42 @@ int main(int argc, char *argv[])
}
}

+ switch (mode) {
+ case MODE_CONNECT:
+ err = bnep_init();
+ if (err < 0) {
+ printf("cannot initialize bnep\n");
+ exit(1);
+ }
+ err = bnep_client_connect();
+ if (err < 0)
+ exit(1);
+
+ break;
+
+ case MODE_LISTEN:
+ err = bnep_init();
+ if (err < 0) {
+ printf("cannot initialize bnep\n");
+ exit(1);
+ }
+ err = bnep_server_listen();
+ if (err < 0)
+ exit(1);
+
+ break;
+
+ case MODE_NONE:
+ default:
+ printf("connect/listen mode not set, exit...\n");
+ exit(1);
+ }
+
+ g_main_loop_run(mloop);
+
+ printf("Done\n");
+
+ g_main_loop_unref(mloop);
+
return 0;
}
--
2.1.0


2015-03-03 16:59:54

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 10/15] profiles/network: Remove unneded bnep_uuid function from bnep code

This function is no longer needed since connection and server can handle
this funcionality by itself.
---
profiles/network/bnep.c | 10 ----------
profiles/network/bnep.h | 1 -
profiles/network/connection.c | 19 ++++++++++++-------
profiles/network/server.c | 24 +++++++++++++++++++++---
4 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 3fe63f0..a81a260 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -85,16 +85,6 @@ struct bnep {
void *disconn_data;
};

-const char *bnep_uuid(uint16_t id)
-{
- int i;
-
- for (i = 0; __svc[i].uuid128; i++)
- if (__svc[i].id == id)
- return __svc[i].uuid128;
- return NULL;
-}
-
const char *bnep_name(uint16_t id)
{
int i;
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 31579f9..811ea14 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -26,7 +26,6 @@ struct bnep;
int bnep_init(void);
int bnep_cleanup(void);

-const char *bnep_uuid(uint16_t id);
const char *bnep_name(uint16_t id);

struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 2b24a0c..538e7ad 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -284,21 +284,23 @@ static DBusMessage *local_connect(DBusConnection *conn,
struct btd_service *service;
struct network_conn *nc;
const char *svc;
- const char *uuid;
uint16_t id;
int err;
+ char uuid_str[MAX_LEN_UUID_STR];
+ bt_uuid_t uuid;

if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc,
DBUS_TYPE_INVALID) == FALSE)
return btd_error_invalid_args(msg);

id = get_pan_srv_id(svc);
- uuid = bnep_uuid(id);
+ bt_uuid16_create(&uuid, id);
+ bt_uuid_to_uuid128(&uuid, &uuid);

- if (uuid == NULL)
+ if (bt_uuid_to_string(&uuid, uuid_str, MAX_LEN_UUID_STR) < 0)
return btd_error_invalid_args(msg);

- service = btd_device_get_service(peer->device, uuid);
+ service = btd_device_get_service(peer->device, uuid_str);
if (service == NULL)
return btd_error_not_supported(msg);

@@ -439,15 +441,18 @@ static gboolean network_property_get_uuid(const GDBusPropertyTable *property,
{
struct network_peer *peer = data;
struct network_conn *nc;
- const char *uuid;
+ char uuid_str[MAX_LEN_UUID_STR];
+ bt_uuid_t uuid;

nc = find_connection_by_state(peer->connections, CONNECTED);
if (nc == NULL)
return FALSE;

- uuid = bnep_uuid(nc->id);
+ bt_uuid16_create(&uuid, nc->id);
+ bt_uuid_to_uuid128(&uuid, &uuid);
+ bt_uuid_to_string(&uuid, uuid_str, MAX_LEN_UUID_STR);

- dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid_str);

return TRUE;
}
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 5d2fbcc..ba1dfd4 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -114,14 +114,32 @@ static struct network_server *find_server(GSList *list, uint16_t id)
static struct network_server *find_server_by_uuid(GSList *list,
const char *uuid)
{
+ bt_uuid_t srv_uuid, bnep_uuid;
+
for (; list; list = list->next) {
struct network_server *ns = list->data;
+ bt_uuid16_create(&bnep_uuid, ns->id);

- if (strcasecmp(uuid, bnep_uuid(ns->id)) == 0)
+ /* UUID value compare */
+ if (!bt_string_to_uuid(&srv_uuid, uuid) &&
+ !bt_uuid_cmp(&srv_uuid, &bnep_uuid))
return ns;

- if (strcasecmp(uuid, bnep_name(ns->id)) == 0)
- return ns;
+ /* String value compare */
+ switch (ns->id) {
+ case BNEP_SVC_PANU:
+ if (!strcasecmp(uuid, "panu"))
+ return ns;
+ break;
+ case BNEP_SVC_NAP:
+ if (!strcasecmp(uuid, "nap"))
+ return ns;
+ break;
+ case BNEP_SVC_GN:
+ if (!strcasecmp(uuid, "gn"))
+ return ns;
+ break;
+ }
}

return NULL;
--
2.1.0


2015-03-03 16:59:57

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 13/15] tools/bneptest: Add initial support for bneptest tool

This tool should be designed to help testing bnep on Bluez.
---
.gitignore | 1 +
Makefile.tools | 12 ++++++---
android/Android.mk | 35 ++++++++++++++++++++++++++
tools/bneptest.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 119 insertions(+), 3 deletions(-)
create mode 100644 tools/bneptest.c

diff --git a/.gitignore b/.gitignore
index a207a0f..a4f06dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,6 +82,7 @@ tools/gatt-service
tools/btgatt-client
tools/btgatt-server
tools/mcaptest
+tools/bneptest
test/sap_client.pyc
test/bluezutils.pyc
unit/test-ringbuf
diff --git a/Makefile.tools b/Makefile.tools
index e28f3cb..1aafb28 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -223,9 +223,9 @@ noinst_PROGRAMS += tools/bdaddr tools/avinfo tools/avtest \
tools/hcieventmask tools/hcisecfilter \
tools/btmgmt tools/btinfo tools/btattach \
tools/btsnoop tools/btproxy \
- tools/btiotest tools/mcaptest tools/cltest \
- tools/oobtest tools/seq2bseq tools/ibeacon \
- tools/btgatt-client tools/btgatt-server
+ tools/btiotest tools/bneptest tools/mcaptest \
+ tools/cltest tools/oobtest tools/seq2bseq \
+ tools/ibeacon tools/btgatt-client tools/btgatt-server

tools_bdaddr_SOURCES = tools/bdaddr.c src/oui.h src/oui.c
tools_bdaddr_LDADD = lib/libbluetooth-internal.la @UDEV_LIBS@
@@ -267,6 +267,12 @@ tools_mcaptest_SOURCES = tools/mcaptest.c \
profiles/health/mcap.h profiles/health/mcap.c
tools_mcaptest_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@

+tools_bneptest_SOURCES = tools/bneptest.c \
+ btio/btio.h btio/btio.c \
+ src/log.c src/log.h \
+ profiles/network/bnep.h profiles/network/bnep.c
+tools_bneptest_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
tools_cltest_SOURCES = tools/cltest.c
tools_cltest_LDADD = lib/libbluetooth-internal.la src/libshared-mainloop.la

diff --git a/android/Android.mk b/android/Android.mk
index 6c0eda8..f218805 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -256,6 +256,41 @@ LOCAL_MODULE := mcaptest
include $(BUILD_EXECUTABLE)

#
+# bneptest
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ bluez/src/log.c \
+ bluez/btio/btio.c \
+ bluez/lib/bluetooth.c \
+ bluez/lib/hci.c \
+ bluez/profiles/network/bnep.c \
+ bluez/tools/bneptest.c \
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, glib) \
+ $(call include-path-for, glib)/glib \
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/bluez \
+
+LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)
+
+LOCAL_SHARED_LIBRARIES := \
+ libglib \
+
+LOCAL_STATIC_LIBRARIES := \
+ bluetooth-headers \
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := bneptest
+
+include $(BUILD_EXECUTABLE)
+
+#
# avdtptest
#

diff --git a/tools/bneptest.c b/tools/bneptest.c
new file mode 100644
index 0000000..cafeba9
--- /dev/null
+++ b/tools/bneptest.c
@@ -0,0 +1,74 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2015 Intel Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <glib.h>
+
+#include "src/log.h"
+
+static GMainLoop *mloop;
+
+static void usage(void)
+{
+ printf("bneptest - BNEP testing ver %s\n", VERSION);
+ printf("Usage:\n"
+ "\tbneptest [options]\n");
+}
+
+static struct option main_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+ int opt;
+
+ DBG("");
+
+ mloop = g_main_loop_new(NULL, FALSE);
+ if (!mloop) {
+ printf("Cannot create main loop\n");
+
+ exit(1);
+ }
+
+ while ((opt = getopt_long(argc, argv, "h", main_options, NULL))
+ != EOF) {
+ switch (opt) {
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ }
+ }
+
+ return 0;
+}
--
2.1.0


2015-03-03 16:59:52

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 08/15] profiles/network: Shortening service name argument to srv

Current argument naming is long and it can be simplified to srv.
---
profiles/network/connection.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 8f1a65b..92b7af3 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -79,9 +79,9 @@ struct network_conn {

static GSList *peers = NULL;

-static uint16_t get_service_id(struct btd_service *service)
+static uint16_t get_service_id(struct btd_service *srv)
{
- return bnep_service_id(btd_service_get_profile(service)->remote_uuid);
+ return bnep_service_id(btd_service_get_profile(srv)->remote_uuid);
}

static struct network_peer *find_peer(GSList *list, struct btd_device *device)
@@ -309,11 +309,11 @@ static DBusMessage *local_connect(DBusConnection *conn,
}

/* Connect and initiate BNEP session */
-int connection_connect(struct btd_service *service)
+int connection_connect(struct btd_service *srv)
{
- struct network_conn *nc = btd_service_get_user_data(service);
+ struct network_conn *nc = btd_service_get_user_data(srv);
struct network_peer *peer = nc->peer;
- uint16_t id = get_service_id(service);
+ uint16_t id = get_service_id(srv);
GError *err = NULL;
const bdaddr_t *src;
const bdaddr_t *dst;
@@ -343,9 +343,9 @@ int connection_connect(struct btd_service *service)
return 0;
}

-int connection_disconnect(struct btd_service *service)
+int connection_disconnect(struct btd_service *srv)
{
- struct network_conn *nc = btd_service_get_user_data(service);
+ struct network_conn *nc = btd_service_get_user_data(srv);

if (nc->state == DISCONNECTED)
return 0;
@@ -497,12 +497,12 @@ static const GDBusPropertyTable connection_properties[] = {
{ }
};

-void connection_unregister(struct btd_service *service)
+void connection_unregister(struct btd_service *srv)
{
- struct btd_device *device = btd_service_get_device(service);
- struct network_conn *conn = btd_service_get_user_data(service);
+ struct btd_device *device = btd_service_get_device(srv);
+ struct network_conn *conn = btd_service_get_user_data(srv);
struct network_peer *peer = conn->peer;
- uint16_t id = get_service_id(service);
+ uint16_t id = get_service_id(srv);

DBG("%s id %u", device_get_path(device), id);

@@ -544,12 +544,12 @@ static struct network_peer *create_peer(struct btd_device *device)
return peer;
}

-int connection_register(struct btd_service *service)
+int connection_register(struct btd_service *srv)
{
- struct btd_device *device = btd_service_get_device(service);
+ struct btd_device *device = btd_service_get_device(srv);
struct network_peer *peer;
struct network_conn *nc;
- uint16_t id = get_service_id(service);
+ uint16_t id = get_service_id(srv);

DBG("%s id %u", device_get_path(device), id);

@@ -563,11 +563,11 @@ int connection_register(struct btd_service *service)

nc = g_new0(struct network_conn, 1);
nc->id = id;
- nc->service = btd_service_ref(service);
+ nc->service = btd_service_ref(srv);
nc->state = DISCONNECTED;
nc->peer = peer;

- btd_service_set_user_data(service, nc);
+ btd_service_set_user_data(srv, nc);

DBG("id %u registered", id);

--
2.1.0


2015-03-03 16:59:55

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 11/15] profiles/network: Remove not needed get name by bnep id function

This function and service structure declaration is no longer needed
since related code was distracted.
---
profiles/network/bnep.c | 21 ---------------------
profiles/network/bnep.h | 2 --
2 files changed, 23 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index a81a260..e133dd9 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -54,17 +54,6 @@

static int ctl;

-static struct {
- const char *name; /* Friendly name */
- const char *uuid128; /* UUID 128 */
- uint16_t id; /* Service class identifier */
-} __svc[] = {
- { "panu", PANU_UUID, BNEP_SVC_PANU },
- { "gn", GN_UUID, BNEP_SVC_GN },
- { "nap", NAP_UUID, BNEP_SVC_NAP },
- { NULL }
-};
-
struct __service_16 {
uint16_t dst;
uint16_t src;
@@ -85,16 +74,6 @@ struct bnep {
void *disconn_data;
};

-const char *bnep_name(uint16_t id)
-{
- int i;
-
- for (i = 0; __svc[i].name; i++)
- if (__svc[i].id == id)
- return __svc[i].name;
- return NULL;
-}
-
int bnep_init(void)
{
ctl = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 811ea14..da706ac 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -26,8 +26,6 @@ struct bnep;
int bnep_init(void);
int bnep_cleanup(void);

-const char *bnep_name(uint16_t id);
-
struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
char *iface);
void bnep_free(struct bnep *session);
--
2.1.0


2015-03-03 16:59:50

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 06/15] profiles/network: Fix sending command responses

Command response can be three bytes long (in case if command is not
understood) 1 byte(packet type) + 1 byte(control type) + 1 byte(unknown
control type). Command response can be also four bytes long if it's
response for setup connection, filter net type and filter multi addr,
1 byte(packet type) + 1 byte(control type) + 2 byte(response message).
---
lib/bnep.h | 6 +++++
profiles/network/bnep.c | 60 +++++++++++++++++++++++++++++++++++--------------
2 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/lib/bnep.h b/lib/bnep.h
index 2bbfb17..aa46852 100644
--- a/lib/bnep.h
+++ b/lib/bnep.h
@@ -103,6 +103,12 @@ struct bnep_set_filter_req {
uint8_t list[0];
} __attribute__((packed));

+struct bnep_ctrl_cmd_not_understood_cmd {
+ uint8_t type;
+ uint8_t ctrl;
+ uint8_t unkn_ctrl;
+} __attribute__((packed));
+
struct bnep_control_rsp {
uint8_t type;
uint8_t ctrl;
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index e8f9698..d6bd630 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -549,16 +549,40 @@ static int bnep_del_from_bridge(const char *devname, const char *bridge)
return err;
}

-static ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl,
- uint16_t resp)
+static ssize_t bnep_send_ctrl_rsp(int sk, uint8_t ctrl, uint16_t resp)
{
- struct bnep_control_rsp rsp;
+ ssize_t sent;

- rsp.type = type;
- rsp.ctrl = ctrl;
- rsp.resp = htons(resp);
+ switch (ctrl) {
+ case BNEP_CMD_NOT_UNDERSTOOD: {
+ struct bnep_ctrl_cmd_not_understood_cmd rsp;

- return send(sk, &rsp, sizeof(rsp), 0);
+ rsp.type = BNEP_CONTROL;
+ rsp.ctrl = ctrl;
+ rsp.unkn_ctrl = (uint8_t) resp;
+
+ sent = send(sk, &rsp, sizeof(rsp), 0);
+ break;
+ }
+ case BNEP_FILTER_MULT_ADDR_RSP:
+ case BNEP_FILTER_NET_TYPE_RSP:
+ case BNEP_SETUP_CONN_RSP: {
+ struct bnep_control_rsp rsp;
+
+ rsp.type = BNEP_CONTROL;
+ rsp.ctrl = ctrl;
+ rsp.resp = htons(resp);
+
+ sent = send(sk, &rsp, sizeof(rsp), 0);
+ break;
+ }
+ default:
+ error("bnep: wrong response type");
+ sent = -1;
+ break;
+ }
+
+ return sent;
}

static uint16_t bnep_setup_decode(int sk, struct bnep_setup_conn_req *req,
@@ -637,16 +661,15 @@ int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
/* 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;
+ req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) {
+ error("bnep: cmd not understood");
+ err = bnep_send_ctrl_rsp(sk, BNEP_CMD_NOT_UNDERSTOOD,
+ req->ctrl);
+ if (err < 0)
+ error("send not understood ctrl rsp error: %s (%d)",
+ strerror(errno), errno);

- send(sk, pkt, sizeof(pkt), 0);
-
- return -EINVAL;
+ return err;
}

/* Processing BNEP_SETUP_CONNECTION_REQUEST_MSG */
@@ -682,7 +705,10 @@ int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
rsp = BNEP_CONN_NOT_ALLOWED;

reply:
- bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+ err = bnep_send_ctrl_rsp(sk, BNEP_SETUP_CONN_RSP, rsp);
+ if (err < 0)
+ error("bnep: send ctrl rsp error: %s (%d)", strerror(errno),
+ errno);

return err;
}
--
2.1.0


2015-03-03 16:59:48

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 04/15] profiles/network: Move bnep connection setup logic to bnep

BNEP connection set up logic which was added before bnep_server_add,
can be private method of bnep. Moved logic was almost doubled in two
cases: NAP role in PAN, server listening. Now set up and connect
scenario check of bnep connection is only handled in bnep part for
listen connections.
---
android/pan.c | 27 ++--------
profiles/network/bnep.c | 127 ++++++++++++++++++++++++++++------------------
profiles/network/bnep.h | 6 +--
profiles/network/server.c | 48 ++++++++++--------
4 files changed, 112 insertions(+), 96 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 61b81a4..c4ec349 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -463,8 +463,7 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
{
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)) {
@@ -481,24 +480,8 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
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;
}

@@ -509,8 +492,8 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
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("pann: server_connadd failed");
rsp = BNEP_CONN_NOT_ALLOWED;
goto failed;
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 7d78575..160ad1f 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -549,63 +549,25 @@ static int bnep_del_from_bridge(const char *devname, const char *bridge)
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
@@ -629,7 +591,7 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
if (val > 0xffff)
return BNEP_CONN_INVALID_SRC;

- *src = val;
+ src = val;
break;
default:
return BNEP_CONN_INVALID_SVC;
@@ -639,12 +601,13 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
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;
@@ -652,3 +615,69 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,

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("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 5aedf38..aa81dcb 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -41,10 +41,8 @@ void bnep_set_disconnect(struct bnep *session, bnep_disconnect_cb disconn_cb,
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..30bb190 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -47,6 +47,7 @@
#include "src/log.h"
#include "src/error.h"
#include "src/sdpd.h"
+#include "src/shared/util.h"

#include "bnep.h"
#include "server.h"
@@ -281,11 +282,14 @@ static void setup_destroy(void *user_data)
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)
@@ -305,29 +309,31 @@ static gboolean bnep_setup(GIOChannel *chan,
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);
-
+ 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) {
@@ -348,8 +354,8 @@ static gboolean bnep_setup(GIOChannel *chan,
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;
--
2.1.0


2015-03-03 16:59:51

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 07/15] profiles/network: Keep interface arguments naming consistent

Arguments shall keep consistent naming.
---
profiles/network/bnep.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index 4fe79ed..df6464d 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -35,7 +35,7 @@ struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
void bnep_free(struct bnep *session);

typedef void (*bnep_connect_cb) (char *iface, int err, void *data);
-int bnep_connect(struct bnep *b, bnep_connect_cb conn_cb, void *data);
+int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb, void *data);
typedef void (*bnep_disconnect_cb) (void *data);
void bnep_set_disconnect(struct bnep *session, bnep_disconnect_cb disconn_cb,
void *data);
--
2.1.0


2015-03-03 16:59:53

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 09/15] profiles/network: Make get_service_id connections private method

get_service_id method is used only within connection code to get id (16
bit value) of received string format 128bit uuid or service named e.g.
panu, gn or nap. There is no need to make it public as bnep.c only
related code.
---
profiles/network/bnep.c | 25 -------------------------
profiles/network/bnep.h | 1 -
profiles/network/connection.c | 20 ++++++++++++++------
3 files changed, 14 insertions(+), 32 deletions(-)

diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index d6bd630..3fe63f0 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -85,31 +85,6 @@ struct bnep {
void *disconn_data;
};

-uint16_t bnep_service_id(const char *svc)
-{
- int i;
- uint16_t id;
-
- /* Friendly service name */
- for (i = 0; __svc[i].name; i++) {
- if (!strcasecmp(svc, __svc[i].name))
- return __svc[i].id;
- }
-
- /* UUID 128 string */
- for (i = 0; __svc[i].uuid128; i++) {
- if (!strcasecmp(svc, __svc[i].uuid128))
- return __svc[i].id;
- }
-
- /* Try convert to HEX */
- id = strtol(svc, NULL, 16);
- if ((id < BNEP_SVC_PANU) || (id > BNEP_SVC_GN))
- return 0;
-
- return id;
-}
-
const char *bnep_uuid(uint16_t id)
{
int i;
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index df6464d..31579f9 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -26,7 +26,6 @@ struct bnep;
int bnep_init(void);
int bnep_cleanup(void);

-uint16_t bnep_service_id(const char *svc);
const char *bnep_uuid(uint16_t id);
const char *bnep_name(uint16_t id);

diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 92b7af3..2b24a0c 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -47,6 +47,7 @@
#include "src/profile.h"
#include "src/service.h"
#include "src/error.h"
+#include "lib/uuid.h"

#include "bnep.h"
#include "connection.h"
@@ -79,9 +80,16 @@ struct network_conn {

static GSList *peers = NULL;

-static uint16_t get_service_id(struct btd_service *srv)
+static uint16_t get_pan_srv_id(const char *svc)
{
- return bnep_service_id(btd_service_get_profile(srv)->remote_uuid);
+ if (!strcasecmp(svc, "panu") || !strcasecmp(svc, PANU_UUID))
+ return BNEP_SVC_PANU;
+ if (!strcasecmp(svc, "nap") || !strcasecmp(svc, NAP_UUID))
+ return BNEP_SVC_NAP;
+ if (!strcasecmp(svc, "gn") || !strcasecmp(svc, GN_UUID))
+ return BNEP_SVC_GN;
+
+ return 0;
}

static struct network_peer *find_peer(GSList *list, struct btd_device *device)
@@ -284,7 +292,7 @@ static DBusMessage *local_connect(DBusConnection *conn,
DBUS_TYPE_INVALID) == FALSE)
return btd_error_invalid_args(msg);

- id = bnep_service_id(svc);
+ id = get_pan_srv_id(svc);
uuid = bnep_uuid(id);

if (uuid == NULL)
@@ -313,7 +321,7 @@ int connection_connect(struct btd_service *srv)
{
struct network_conn *nc = btd_service_get_user_data(srv);
struct network_peer *peer = nc->peer;
- uint16_t id = get_service_id(srv);
+ uint16_t id = get_pan_srv_id(btd_service_get_profile(srv)->remote_uuid);
GError *err = NULL;
const bdaddr_t *src;
const bdaddr_t *dst;
@@ -502,7 +510,7 @@ void connection_unregister(struct btd_service *srv)
struct btd_device *device = btd_service_get_device(srv);
struct network_conn *conn = btd_service_get_user_data(srv);
struct network_peer *peer = conn->peer;
- uint16_t id = get_service_id(srv);
+ uint16_t id = get_pan_srv_id(btd_service_get_profile(srv)->remote_uuid);

DBG("%s id %u", device_get_path(device), id);

@@ -549,7 +557,7 @@ int connection_register(struct btd_service *srv)
struct btd_device *device = btd_service_get_device(srv);
struct network_peer *peer;
struct network_conn *nc;
- uint16_t id = get_service_id(srv);
+ uint16_t id = get_pan_srv_id(btd_service_get_profile(srv)->remote_uuid);

DBG("%s id %u", device_get_path(device), id);

--
2.1.0


2015-03-03 16:59:56

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 12/15] profiles/network: Move disconn cb setting to bnep connect method

Disconnect callback can be set while connececting bnep. In previous
implementation there was separated method to setting up the disconnect
callback and it was always called immediately after calling connect -
this method was redundand.
---
android/pan.c | 5 ++---
profiles/network/bnep.c | 22 +++++++---------------
profiles/network/bnep.h | 6 +++---
profiles/network/connection.c | 4 +---
4 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 72d8a73..87f1bca 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -324,14 +324,13 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
if (!dev->session)
goto fail;

- perr = bnep_connect(dev->session, bnep_conn_cb, dev);
+ perr = bnep_connect(dev->session, bnep_conn_cb, bnep_disconn_cb, dev,
+ dev);
if (perr < 0) {
error("bnep connect req failed: %s", strerror(-perr));
goto fail;
}

- bnep_set_disconnect(dev->session, bnep_disconn_cb, dev);
-
if (dev->io) {
g_io_channel_unref(dev->io);
dev->io = NULL;
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index e133dd9..87f50fd 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -369,17 +369,21 @@ void bnep_free(struct bnep *session)
g_free(session);
}

-int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb, void *data)
+int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb,
+ bnep_disconnect_cb disconn_cb,
+ void *conn_data, void *disconn_data)
{
GError *gerr = NULL;
int err;

- if (!session || !conn_cb)
+ if (!session || !conn_cb || !disconn_cb)
return -EINVAL;

session->attempts = 0;
session->conn_cb = conn_cb;
- session->conn_data = data;
+ session->disconn_cb = disconn_cb;
+ session->conn_data = conn_data;
+ session->disconn_data = disconn_data;

bt_io_get(session->io, &gerr, BT_IO_OPT_DEST_BDADDR, &session->dst_addr,
BT_IO_OPT_INVALID);
@@ -417,18 +421,6 @@ void bnep_disconnect(struct bnep *session)
bnep_conndel(&session->dst_addr);
}

-void bnep_set_disconnect(struct bnep *session, bnep_disconnect_cb disconn_cb,
- void *data)
-{
- if (!session || !disconn_cb)
- return;
-
- if (!session->disconn_cb && !session->disconn_data) {
- session->disconn_cb = disconn_cb;
- session->disconn_data = data;
- }
-}
-
static int bnep_add_to_bridge(const char *devname, const char *bridge)
{
int ifindex;
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index da706ac..e9f4c1c 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -31,10 +31,10 @@ struct bnep *bnep_new(int sk, uint16_t local_role, uint16_t remote_role,
void bnep_free(struct bnep *session);

typedef void (*bnep_connect_cb) (char *iface, int err, void *data);
-int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb, void *data);
typedef void (*bnep_disconnect_cb) (void *data);
-void bnep_set_disconnect(struct bnep *session, bnep_disconnect_cb disconn_cb,
- void *data);
+int bnep_connect(struct bnep *session, bnep_connect_cb conn_cb,
+ bnep_disconnect_cb disconn_cb,
+ void *conn_data, void *disconn_data);
void bnep_disconnect(struct bnep *session);

int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 538e7ad..46bb999 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -258,14 +258,12 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data)
if (!nc->session)
goto failed;

- perr = bnep_connect(nc->session, bnep_conn_cb, nc);
+ perr = bnep_connect(nc->session, bnep_conn_cb, bnep_disconn_cb, nc, nc);
if (perr < 0) {
error("bnep connect(): %s (%d)", strerror(-perr), -perr);
goto failed;
}

- bnep_set_disconnect(nc->session, bnep_disconn_cb, nc);
-
if (nc->io) {
g_io_channel_unref(nc->io);
nc->io = NULL;
--
2.1.0


2015-03-03 16:59:49

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 05/15] profiles/network: Handle ctrl rsp after conn setup by bnep

This patch moves setup control response to bnep and makes it private.
---
android/pan.c | 14 +++--------
profiles/network/bnep.c | 61 +++++++++++++++++++++++++++++------------------
profiles/network/bnep.h | 2 --
profiles/network/server.c | 36 +++++++++-------------------
4 files changed, 52 insertions(+), 61 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index c4ec349..72d8a73 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -463,7 +463,6 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
{
struct pan_device *dev = user_data;
uint8_t packet[BNEP_MTU];
- uint16_t rsp = BNEP_CONN_NOT_ALLOWED;
int sk, n, err;

if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
@@ -486,22 +485,16 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
}

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

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

- rsp = BNEP_SUCCESS;
- bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
-
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);
@@ -513,7 +506,6 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
return FALSE;

failed:
- bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
pan_device_remove(dev);

return FALSE;
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 160ad1f..e8f9698 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -549,6 +549,18 @@ static int bnep_del_from_bridge(const char *devname, const char *bridge)
return err;
}

+static 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);
+}
+
static uint16_t bnep_setup_decode(int sk, struct bnep_setup_conn_req *req,
uint16_t *dst)
{
@@ -603,7 +615,6 @@ static uint16_t bnep_setup_decode(int sk, struct bnep_setup_conn_req *req,
case BNEP_SVC_GN:
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 ||
@@ -620,7 +631,7 @@ 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;
+ uint16_t rsp, dst = NULL;
struct bnep_setup_conn_req *req = (void *) setup_data;

/* Highest known Control command ID
@@ -639,26 +650,41 @@ int bnep_server_add(int sk, char *bridge, char *iface, const bdaddr_t *addr,
}

/* Processing BNEP_SETUP_CONNECTION_REQUEST_MSG */
- err = bnep_setup_decode(sk, req, &dst);
- if (err < 0) {
- error("error while decoding setup connection request: %d", err);
- return -EINVAL;
+ rsp = bnep_setup_decode(sk, req, &dst);
+ if (rsp != BNEP_SUCCESS || !dst) {
+ err = -rsp;
+ error("bnep: error while decoding setup connection request: %d",
+ rsp);
+ goto reply;
}

- if (!bridge || !iface || !addr || !dst)
- return -EINVAL;
+ if (!dst) {
+ error("bnep: cannot decode proper destination service UUID");
+ rsp = BNEP_CONN_INVALID_DST;
+ goto reply;
+ }

err = bnep_connadd(sk, dst, iface);
- if (err < 0)
- return err;
+ if (err < 0) {
+ rsp = BNEP_CONN_NOT_ALLOWED;
+ goto reply;
+ }

err = bnep_add_to_bridge(iface, bridge);
if (err < 0) {
bnep_conndel(addr);
- return err;
+ rsp = BNEP_CONN_NOT_ALLOWED;
+ goto reply;
}

- return bnep_if_up(iface);
+ err = bnep_if_up(iface);
+ if (err < 0)
+ rsp = BNEP_CONN_NOT_ALLOWED;
+
+reply:
+ bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
+
+ return err;
}

void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
@@ -670,14 +696,3 @@ void bnep_server_delete(char *bridge, char *iface, const bdaddr_t *addr)
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 aa81dcb..4fe79ed 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -44,5 +44,3 @@ void bnep_disconnect(struct bnep *session);
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);
diff --git a/profiles/network/server.c b/profiles/network/server.c
index 30bb190..5d2fbcc 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -288,9 +288,10 @@ static gboolean bnep_setup(GIOChannel *chan,
struct network_server *ns;
uint8_t packet[BNEP_MTU];
struct bnep_setup_conn_req *req = (void *) packet;
- uint16_t dst_role, rsp = BNEP_CONN_NOT_ALLOWED;
+ uint16_t dst_role = 0;
uint32_t val;
int n, sk;
+ char *bridge = NULL;

if (cond & G_IO_NVAL)
return FALSE;
@@ -320,51 +321,36 @@ static gboolean bnep_setup(GIOChannel *chan,
break;
case 16:
if (memcmp(&req->service[4], bt_base, sizeof(bt_base)) != 0)
- return FALSE;
+ break;

/* Intentional no-brake */

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

dst_role = val;
break;
default:
- return FALSE;
+ break;
}

ns = find_server(na->servers, dst_role);
- if (!ns) {
- error("Server unavailable: (0x%x)", dst_role);
- goto reply;
- }
-
- if (!ns->record_id) {
- error("Service record not available");
- goto reply;
- }
+ if (!ns || !ns->record_id || !ns->bridge)
+ error("Server error, bridge not initialized: (0x%x)", dst_role);

- if (!ns->bridge) {
- error("Bridge interface not configured");
- goto reply;
- }
+ bridge = ns->bridge;

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

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

na->setup = NULL;

- rsp = BNEP_SUCCESS;
-
-reply:
- bnep_send_ctrl_rsp(sk, BNEP_CONTROL, BNEP_SETUP_CONN_RSP, rsp);
-
return FALSE;
}

--
2.1.0


2015-03-03 16:59:46

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 02/15] profiles/network: Add appropriate log prefix

Logs should have appropriate prefixes eg. bnep, pan.
---
android/pan.c | 2 +-
profiles/network/bnep.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 511f4fd..94f2daf 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -517,7 +517,7 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,

if (bnep_server_add(sk, dst_role, BNEP_BRIDGE, dev->iface,
&dev->dst) < 0) {
- error("server_connadd failed");
+ error("pann: server_connadd failed");
rsp = BNEP_CONN_NOT_ALLOWED;
goto failed;
}
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index 3986638..b3c6179 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -509,7 +509,7 @@ static int bnep_add_to_bridge(const char *devname, const char *bridge)
error("bnep: Can't add %s to the bridge %s: %s(%d)",
devname, bridge, strerror(-err), -err);
} else {
- info("bridge %s: interface %s added", bridge, devname);
+ info("bnep: bridge %s: interface %s added", bridge, devname);
}

close(sk);
@@ -541,7 +541,7 @@ static int bnep_del_from_bridge(const char *devname, const char *bridge)
error("bnep: Can't delete %s from the bridge %s: %s(%d)",
devname, bridge, strerror(-err), -err);
} else {
- info("bridge %s: interface %s removed", bridge, devname);
+ info("bnep: bridge %s: interface %s removed", bridge, devname);
}

close(sk);
--
2.1.0


2015-03-03 16:59:47

by Grzegorz Kolodziejczyk

[permalink] [raw]
Subject: [PATCH v2 03/15] profiles/network: Integrate get and check bnep setup services roles

While bnep setup, roles must be determined and checked if the connection
scanario is possible. Get and check possible service roles routines are
always performed in serie. So there is no need to split it to separate
calls.
---
android/pan.c | 8 +-------
profiles/network/bnep.c | 37 ++++++++++++++++---------------------
profiles/network/bnep.h | 1 -
profiles/network/server.c | 6 +-----
4 files changed, 18 insertions(+), 34 deletions(-)

diff --git a/android/pan.c b/android/pan.c
index 94f2daf..61b81a4 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -497,17 +497,11 @@ static gboolean nap_setup_cb(GIOChannel *chan, GIOCondition cond,
}

rsp = bnep_setup_decode(req, &dst_role, &src_role);
- if (rsp) {
+ if (rsp != BNEP_SUCCESS) {
error("bnep_setup_decode failed");
goto failed;
}

- rsp = bnep_setup_chk(dst_role, src_role);
- if (rsp) {
- error("benp_setup_chk failed");
- goto failed;
- }
-
err = nap_create_bridge();
if (err < 0) {
error("pan: Failed to create bridge: %s (%d)", strerror(-err),
diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
index b3c6179..7d78575 100644
--- a/profiles/network/bnep.c
+++ b/profiles/network/bnep.c
@@ -591,26 +591,6 @@ ssize_t bnep_send_ctrl_rsp(int sk, uint8_t type, uint8_t ctrl, uint16_t resp)
return send(sk, &rsp, sizeof(rsp), 0);
}

-uint16_t bnep_setup_chk(uint16_t dst, uint16_t src)
-{
- /* Allowed PAN Profile scenarios */
- switch (dst) {
- case BNEP_SVC_NAP:
- case BNEP_SVC_GN:
- if (src == BNEP_SVC_PANU)
- return 0;
- return BNEP_CONN_INVALID_SRC;
- case BNEP_SVC_PANU:
- if (src == BNEP_SVC_PANU || src == BNEP_SVC_GN ||
- src == BNEP_SVC_NAP)
- return 0;
-
- return BNEP_CONN_INVALID_SRC;
- }
-
- return BNEP_CONN_INVALID_DST;
-}
-
uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
uint16_t *src)
{
@@ -655,5 +635,20 @@ uint16_t bnep_setup_decode(struct bnep_setup_conn_req *req, uint16_t *dst,
return BNEP_CONN_INVALID_SVC;
}

- return BNEP_SUCCESS;
+ /* Allowed PAN Profile scenarios */
+ switch (*dst) {
+ case BNEP_SVC_NAP:
+ case BNEP_SVC_GN:
+ 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)
+ return BNEP_SUCCESS;
+
+ return BNEP_CONN_INVALID_SRC;
+ }
+
+ return BNEP_CONN_INVALID_DST;
}
diff --git a/profiles/network/bnep.h b/profiles/network/bnep.h
index bc43d4f..5aedf38 100644
--- a/profiles/network/bnep.h
+++ b/profiles/network/bnep.h
@@ -46,6 +46,5 @@ int bnep_server_add(int sk, uint16_t dst, char *bridge, char *iface,
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_chk(uint16_t dst_role, uint16_t src_role);
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 332525e..04f188a 100644
--- a/profiles/network/server.c
+++ b/profiles/network/server.c
@@ -324,11 +324,7 @@ static gboolean bnep_setup(GIOChannel *chan,
return FALSE;

rsp = bnep_setup_decode(req, &dst_role, &src_role);
- if (rsp)
- goto reply;
-
- rsp = bnep_setup_chk(dst_role, src_role);
- if (rsp)
+ if (rsp != BNEP_SUCCESS)
goto reply;

rsp = BNEP_CONN_NOT_ALLOWED;
--
2.1.0