MshPRT_v1.1, section 6.7 requires that: 1. Upon connection of a GATT proxy client to a GATT proxy server, the server sends a beacon for each known subnet to the client. 2. Upon processing a SNB or MPB with a new IV index or flags value, the GATT proxy server shall propagate the beacon to the client. 3. When the GATT proxy server is added to a new subnet, a beacon for that subnet shall be sent to the client. --- mesh/gatt-proxy-svc.c | 20 +++++++++++++++++++- mesh/gatt-proxy-svc.h | 1 + mesh/net-keys.c | 25 +++++++++++++++++++++++++ mesh/net-keys.h | 1 + mesh/net.c | 23 +++++++++++++++++++++++ mesh/net.h | 1 + 6 files changed, 70 insertions(+), 1 deletion(-) diff --git a/mesh/gatt-proxy-svc.c b/mesh/gatt-proxy-svc.c index 4100578a9f0a..020555bbfdb2 100644 --- a/mesh/gatt-proxy-svc.c +++ b/mesh/gatt-proxy-svc.c @@ -25,7 +25,8 @@ #include "mesh/net.h" // PROXY_FILTER_ACCEPT_LIST, // PROXY_FILTER_REJECT_LIST // mesh_net_attach_gatt(), - // mesh_net_detach_gatt() + // mesh_net_detach_gatt(), + // mesh_net_send_all_beacons_gatt() #include "mesh/net-keys.h" // net_key_fill_adv_service_data(), // net_key_get_next_id() #include "mesh/util.h" // print_packet() @@ -281,6 +282,11 @@ static void gatt_proxy_svc_send(enum proxy_msg_type msg_type, const void *data, } } +void gatt_proxy_svc_send_beacon(const void *data, uint8_t len) +{ + gatt_proxy_svc_send(PROXY_MSG_TYPE_MESH_BEACON, data, len); +} + void gatt_proxy_svc_send_net(uint16_t dst, const void *data, uint8_t len) { int i; @@ -331,6 +337,18 @@ static void gatt_service_notify_acquired(void *user_data) */ gatt_proxy->filter_type = PROXY_FILTER_ACCEPT_LIST; gatt_proxy->filter_count = 0; + + /* + * MshPRT_v1.1, section 6.7 - Proxy Server behavior + * Upon connection, [...] The Proxy Server shall send a mesh + * beacon for each known subnet to the Proxy Client, [...] + * + * MshPRT_v1.1, section 7.2.3.2.1 - Characteristic behavior + * [...] the client will enable notifications [...] to the + * Mesh Proxy Data Out Client Characteristic Configuration + * Descriptor after a connection is established. + */ + mesh_net_send_all_beacons_gatt(); } static void gatt_service_notify_stopped(void *user_data) diff --git a/mesh/gatt-proxy-svc.h b/mesh/gatt-proxy-svc.h index 0abb85d7109f..2784602160bb 100644 --- a/mesh/gatt-proxy-svc.h +++ b/mesh/gatt-proxy-svc.h @@ -36,5 +36,6 @@ unsigned gatt_proxy_svc_filter_count(struct gatt_proxy_svc *gatt_proxy, void gatt_proxy_svc_filter_pdu_rcvd(struct gatt_proxy_svc *gatt_proxy, uint16_t src); +void gatt_proxy_svc_send_beacon(const void *data, uint8_t len); void gatt_proxy_svc_send_net(uint16_t dst, const void *data, uint8_t len); void gatt_proxy_svc_send_proxy_cfg(const void *data, uint8_t len); diff --git a/mesh/net-keys.c b/mesh/net-keys.c index 1a2cd39421c1..918455b2200f 100644 --- a/mesh/net-keys.c +++ b/mesh/net-keys.c @@ -732,6 +732,18 @@ bool net_key_beacon_refresh(uint32_t id, uint32_t ivi, bool kr, bool ivu, print_packet("Set SNB to", key->snb, BEACON_LEN_SNB); gatt_proxy_svc_set_current_adv_key(key->id); + + /* + * MshPRT_v1.1, section 6.7 - Proxy Server behavior + * Upon successfully processing a Secure Network Beacon or + * a Mesh Private beacon with a new value for the IV Index + * field or the Flags field, the Proxy Server shall send a + * mesh beacon to the Proxy Client, ... + * When the Proxy Server is added to a new subnet, the server + * shall send a mesh beacon for that subnet to the Proxy Client, + * ... + */ + gatt_proxy_svc_send_beacon(key->snb + 1, BEACON_LEN_SNB - 1); } l_debug("Set Beacon: IVI: %8.8x, IVU: %d, KR: %d", ivi, ivu, kr); @@ -850,6 +862,19 @@ void net_key_beacon_disable(uint32_t id, bool mpb) key->observe.timeout = NULL; } +void net_key_beacon_send_gatt(uint32_t id) +{ + struct net_key *key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id)); + + if (!key) + return; + + /* FIXME: How to determine that key actually contains a valid SNB? */ + if (key->snb && key->snb[0] == BT_AD_MESH_BEACON && + key->snb[1] == BEACON_TYPE_SNB && key->snb[2] == 0) + gatt_proxy_svc_send_beacon(key->snb + 1, BEACON_LEN_SNB - 1); +} + static void free_key(void *data) { struct net_key *key = data; diff --git a/mesh/net-keys.h b/mesh/net-keys.h index b43157df29bc..0d292ee41606 100644 --- a/mesh/net-keys.h +++ b/mesh/net-keys.h @@ -40,6 +40,7 @@ bool net_key_beacon_refresh(uint32_t id, uint32_t iv_index, bool kr, bool ivu, bool force); void net_key_beacon_enable(uint32_t id, bool mpb, uint8_t refresh_count); void net_key_beacon_disable(uint32_t id, bool mpb); +void net_key_beacon_send_gatt(uint32_t id); uint32_t net_key_beacon_last_seen(uint32_t id); bool net_key_fill_adv_service_data(uint32_t id, diff --git a/mesh/net.c b/mesh/net.c index 97591a5323d1..e4998a0924f6 100644 --- a/mesh/net.c +++ b/mesh/net.c @@ -2997,6 +2997,29 @@ void net_local_beacon(uint32_t net_key_id, uint32_t ivi, bool ivu, bool kr) l_queue_foreach(nets, process_beacon, &beacon_data); } +static void send_beacon_gatt(void *a, void *b) +{ + struct mesh_subnet *subnet = a; + + net_key_beacon_send_gatt(subnet->net_key_tx); +} + +static void send_all_beacons_gatt(void *a, void *b) +{ + struct mesh_net *net = a; + + l_queue_foreach(net->subnets, send_beacon_gatt, NULL); +} + +void mesh_net_send_all_beacons_gatt(void) +{ + /* + * Upon connection, [...] The Proxy Server shall send a mesh beacon + * for each known subnet to the Proxy Client, [...] + */ + l_queue_foreach(nets, send_all_beacons_gatt, NULL); +} + bool mesh_net_set_snb_mode(struct mesh_net *net, bool enable) { if (!net) diff --git a/mesh/net.h b/mesh/net.h index af581478412c..bf537e20a57c 100644 --- a/mesh/net.h +++ b/mesh/net.h @@ -229,6 +229,7 @@ uint16_t mesh_net_get_address(struct mesh_net *net); bool mesh_net_register_unicast(struct mesh_net *net, uint16_t unicast, uint8_t num_ele); void net_local_beacon(uint32_t key_id, uint32_t ivi, bool ivu, bool kr); +void mesh_net_send_all_beacons_gatt(void); bool mesh_net_set_snb_mode(struct mesh_net *net, bool enable); bool mesh_net_set_mpb_mode(struct mesh_net *net, bool enabla, uint8_t period, bool init); -- 2.43.0