xref: /btstack/src/mesh/beacon.c (revision 2fca4dad957cd7b88f4657ed51e89c12615dda72)
1 /*
2  * Copyright (C) 2017 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "beacon.c"
39 
40 #include "mesh/beacon.h"
41 
42 #include <stdio.h>
43 #include <string.h>
44 
45 #include "ble/core.h"
46 #include "bluetooth.h"
47 #include "bluetooth_data_types.h"
48 #include "btstack_debug.h"
49 #include "btstack_event.h"
50 #include "btstack_run_loop.h"
51 #include "btstack_util.h"
52 #include "gap.h"
53 
54 #include "mesh/adv_bearer.h"
55 #include "mesh/gatt_bearer.h"
56 #include "mesh/mesh_foundation.h"
57 #include "mesh/mesh_iv_index_seq_number.h"
58 #include "mesh/mesh_keys.h"
59 
60 #define BEACON_TYPE_UNPROVISIONED_DEVICE 0
61 #define BEACON_TYPE_SECURE_NETWORK 1
62 
63 #define UNPROVISIONED_BEACON_INTERVAL_MS 5000
64 #define UNPROVISIONED_BEACON_LEN      23
65 
66 #define SECURE_NETWORK_BEACON_INTERVAL_MIN_MS  10000
67 #define SECURE_NETWORK_BEACON_INTERVAL_MAX_MS 600000
68 #define SECURE_NETWORK_BEACON_LEN                 22
69 
70 // prototypes
71 static void mesh_secure_network_beacon_run(btstack_timer_source_t * ts);
72 
73 // bearers
74 #ifdef ENABLE_MESH_GATT_BEARER
75 static hci_con_handle_t gatt_bearer_con_handle;
76 #endif
77 
78 // beacon
79 static uint8_t mesh_beacon_data[29];
80 static uint8_t mesh_beacon_len;
81 static btstack_timer_source_t   beacon_timer;
82 static int                      beacon_timer_active;
83 
84 // unprovisioned device beacon
85 #ifdef ENABLE_MESH_ADV_BEARER
86 static const uint8_t * beacon_device_uuid;
87 static       uint16_t  beacon_oob_information;
88 static       uint32_t  beacon_uri_hash;
89 static int             beacon_send_device_beacon;
90 #endif
91 
92 static btstack_packet_handler_t unprovisioned_device_beacon_handler;
93 
94 // secure network beacon
95 static btstack_crypto_aes128_cmac_t        mesh_secure_network_beacon_cmac_request;
96 static uint8_t                             mesh_secure_network_beacon_auth_value[16];
97 static btstack_packet_handler_t            mesh_secure_network_beacon_handler;
98 static int                                 mesh_secure_network_beacon_active;
99 #ifdef ENABLE_MESH_ADV_BEARER
100 static uint8_t                             mesh_secure_network_beacon_validate_buffer[SECURE_NETWORK_BEACON_LEN];
101 #endif
102 
103 #ifdef ENABLE_MESH_ADV_BEARER
beacon_timer_handler(btstack_timer_source_t * ts)104 static void beacon_timer_handler(btstack_timer_source_t * ts){
105     // restart timer
106     btstack_run_loop_set_timer(ts, UNPROVISIONED_BEACON_INTERVAL_MS);
107     btstack_run_loop_add_timer(ts);
108     beacon_timer_active = 1;
109 
110     // setup beacon
111     mesh_beacon_len = UNPROVISIONED_BEACON_LEN;
112     mesh_beacon_data[0] = BEACON_TYPE_UNPROVISIONED_DEVICE;
113     (void)memcpy(&mesh_beacon_data[1], beacon_device_uuid, 16);
114     big_endian_store_16(mesh_beacon_data, 17, beacon_oob_information);
115     big_endian_store_32(mesh_beacon_data, 19, beacon_uri_hash);
116 
117     // request to send
118     beacon_send_device_beacon = 1;
119     adv_bearer_request_can_send_now_for_beacon();
120 }
121 #endif
122 
mesh_secure_network_beacon_auth_value_calculated(void * arg)123 static void mesh_secure_network_beacon_auth_value_calculated(void * arg){
124     mesh_subnet_t * mesh_subnet = (mesh_subnet_t *) arg;
125 
126     (void)memcpy(&mesh_beacon_data[14],
127                  mesh_secure_network_beacon_auth_value, 8);
128     mesh_beacon_len = SECURE_NETWORK_BEACON_LEN;
129 
130     printf("Secure Network Beacon\n");
131     printf("- ");
132     printf_hexdump(mesh_beacon_data, mesh_beacon_len);
133 
134     mesh_secure_network_beacon_active = 0;
135     mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_AUTH_VALUE;
136 
137     mesh_secure_network_beacon_run(NULL);
138 }
139 
mesh_secure_network_beacon_get_flags(mesh_subnet_t * mesh_subnet)140 static uint8_t mesh_secure_network_beacon_get_flags(mesh_subnet_t * mesh_subnet){
141     uint8_t mesh_flags = 0;
142     if (mesh_subnet->key_refresh != MESH_KEY_REFRESH_NOT_ACTIVE){
143         mesh_flags |= 1;
144     }
145     if (mesh_iv_update_active()){
146         mesh_flags |= 2;
147     }
148 
149     return mesh_flags;
150 }
151 
mesh_secure_network_beacon_setup(mesh_subnet_t * mesh_subnet)152 static void mesh_secure_network_beacon_setup(mesh_subnet_t * mesh_subnet){
153     mesh_beacon_data[0] = BEACON_TYPE_SECURE_NETWORK;
154     mesh_beacon_data[1] = mesh_secure_network_beacon_get_flags(mesh_subnet);
155     // TODO: pick correct key based on key refresh phase
156 
157     (void)memcpy(&mesh_beacon_data[2], mesh_subnet->old_key->network_id, 8);
158     big_endian_store_32(mesh_beacon_data, 10, mesh_get_iv_index());
159     mesh_network_key_t * network_key = mesh_subnet_get_outgoing_network_key(mesh_subnet);
160     btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, network_key->beacon_key, 13,
161         &mesh_beacon_data[1], mesh_secure_network_beacon_auth_value, &mesh_secure_network_beacon_auth_value_calculated, mesh_subnet);
162 }
163 
mesh_secure_network_beacon_update_interval(mesh_subnet_t * subnet)164 static void mesh_secure_network_beacon_update_interval(mesh_subnet_t * subnet){
165     uint32_t min_observation_period_ms = 2 * subnet->beacon_interval_ms;
166     uint32_t actual_observation_period = btstack_time_delta(btstack_run_loop_get_time_ms(), subnet->beacon_observation_start_ms);
167 
168     // The Observation Period in seconds should typically be double the typical Beacon Interval.
169     if (actual_observation_period < min_observation_period_ms) return;
170 
171     // Expected Number of Beacons (1 beacon per 10 seconds)
172     uint16_t expected_number_of_beacons = actual_observation_period / SECURE_NETWORK_BEACON_INTERVAL_MIN_MS;
173 
174     // Beacon Interval = Observation Period * (Observed Number of Beacons + 1) / Expected Number of Beacons
175     uint32_t new_beacon_interval  =  actual_observation_period * (subnet->beacon_observation_counter + 1) / expected_number_of_beacons;
176 
177     if (new_beacon_interval > SECURE_NETWORK_BEACON_INTERVAL_MAX_MS){
178         new_beacon_interval = SECURE_NETWORK_BEACON_INTERVAL_MAX_MS;
179     }
180     else if (new_beacon_interval < SECURE_NETWORK_BEACON_INTERVAL_MIN_MS){
181         new_beacon_interval = SECURE_NETWORK_BEACON_INTERVAL_MAX_MS;
182     }
183     subnet->beacon_interval_ms = new_beacon_interval;
184     log_info("New beacon interval %u seconds", (int) (subnet->beacon_interval_ms / 1000));
185 }
186 
mesh_secure_network_beacon_run(btstack_timer_source_t * ts)187 static void mesh_secure_network_beacon_run(btstack_timer_source_t * ts){
188     UNUSED(ts);
189 
190     uint32_t next_timeout_ms = 0;
191 
192     // iterate over all networks
193     mesh_subnet_iterator_t it;
194     mesh_subnet_iterator_init(&it);
195     while (mesh_subnet_iterator_has_more(&it)){
196         mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
197         switch (subnet->beacon_state){
198             case MESH_SECURE_NETWORK_BEACON_W4_INTERVAL:
199                 // update beacon interval
200                 mesh_secure_network_beacon_update_interval(subnet);
201 
202                 if (mesh_foundation_beacon_get() == 0){
203                     // beacon off, continue observing
204                     if (next_timeout_ms == 0 || next_timeout_ms > subnet->beacon_interval_ms){
205                         next_timeout_ms = subnet->beacon_interval_ms;
206                     }
207                     break;
208                 }
209 
210                 // send new beacon
211                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE;
212 
213                 /* fall through */
214 
215             case MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE:
216                 if (mesh_secure_network_beacon_active){
217                     // just try again in 10 ms
218                     next_timeout_ms = 10;
219                     break;
220                 }
221                 subnet->beacon_state  = MESH_SECURE_NETWORK_BEACON_W4_AUTH_VALUE;
222                 mesh_secure_network_beacon_active = 1;
223                 mesh_secure_network_beacon_setup(subnet);
224                 break;
225 
226             case MESH_SECURE_NETWORK_BEACON_AUTH_VALUE:
227 
228 #ifdef ENABLE_MESH_ADV_BEARER
229                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV;
230                 adv_bearer_request_can_send_now_for_beacon();
231                 break;
232 #endif
233                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_ADV_SENT;
234 
235                 /* fall through */
236 
237             case MESH_SECURE_NETWORK_BEACON_ADV_SENT:
238 
239 #ifdef ENABLE_MESH_GATT_BEARER
240                 if (gatt_bearer_con_handle != HCI_CON_HANDLE_INVALID && mesh_foundation_gatt_proxy_get() != 0){
241                     subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_SEND_GATT;
242                     gatt_bearer_request_can_send_now_for_beacon();
243                     break;
244                 }
245 #endif
246                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT;
247 
248                 /* fall through */
249 
250             case MESH_SECURE_NETWORK_BEACON_GATT_SENT:
251                 // now, start listening for beacons
252                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W4_INTERVAL;
253                 // and request timeout
254                 if (next_timeout_ms == 0 || next_timeout_ms > subnet->beacon_interval_ms){
255                     next_timeout_ms = subnet->beacon_interval_ms;
256                 }
257                 break;
258 
259             default:
260                 break;
261         }
262     }
263 
264     if (beacon_timer_active){
265         btstack_run_loop_remove_timer(&beacon_timer);
266         beacon_timer_active = 0;
267     }
268 
269     // setup next run
270     if (next_timeout_ms == 0) return;
271 
272     btstack_run_loop_set_timer(&beacon_timer, next_timeout_ms);
273     btstack_run_loop_set_timer_handler(&beacon_timer, mesh_secure_network_beacon_run);
274     btstack_run_loop_add_timer(&beacon_timer);
275     beacon_timer_active = 1;
276 }
277 
278 #ifdef ENABLE_MESH_ADV_BEARER
beacon_handle_secure_beacon_auth_value_calculated(void * arg)279 static void beacon_handle_secure_beacon_auth_value_calculated(void * arg){
280     UNUSED(arg);
281 
282     // pass on, if auth value checks out
283     if (memcmp(&mesh_secure_network_beacon_validate_buffer[14], mesh_secure_network_beacon_auth_value, 8) == 0) {
284         if (mesh_secure_network_beacon_handler){
285             (*mesh_secure_network_beacon_handler)(MESH_BEACON_PACKET, 0, mesh_secure_network_beacon_validate_buffer, SECURE_NETWORK_BEACON_LEN);
286         }
287     }
288 
289     // done
290     mesh_secure_network_beacon_active = 0;
291     mesh_secure_network_beacon_run(NULL);
292 }
293 
beacon_handle_secure_beacon(uint8_t * packet,uint16_t size)294 static void beacon_handle_secure_beacon(uint8_t * packet, uint16_t size){
295     if (size != SECURE_NETWORK_BEACON_LEN) return;
296 
297     // lookup subnet and netkey by network id
298     uint8_t * beacon_network_id = &packet[2];
299     mesh_subnet_iterator_t it;
300     mesh_subnet_iterator_init(&it);
301     mesh_subnet_t * subnet = NULL;
302     mesh_network_key_t * network_key = NULL;
303     while (mesh_subnet_iterator_has_more(&it)){
304         mesh_subnet_t * item = mesh_subnet_iterator_get_next(&it);
305         if (memcmp(item->old_key->network_id, beacon_network_id, 8) == 0 ) {
306             subnet = item;
307             network_key = item->old_key;
308         }
309         if (item->new_key != NULL && memcmp(item->new_key->network_id, beacon_network_id, 8) == 0 ) {
310             subnet = item;
311             network_key = item->new_key;
312         }
313         break;
314     }
315     if (subnet == NULL) return;
316 
317     // count beacon
318     subnet->beacon_observation_counter++;
319 
320     // check if new flags are set
321     uint8_t current_flags = mesh_secure_network_beacon_get_flags(subnet);
322     uint8_t new_flags = packet[1] & (~current_flags);
323 
324     if (new_flags == 0) return;
325 
326     // validate beacon - if crytpo ready
327     if (mesh_secure_network_beacon_active) return;
328 
329     mesh_secure_network_beacon_active = 1;
330     (void)memcpy(mesh_secure_network_beacon_validate_buffer, &packet[0],
331                  SECURE_NETWORK_BEACON_LEN);
332 
333     btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, network_key->beacon_key, 13,
334         &mesh_secure_network_beacon_validate_buffer[1], mesh_secure_network_beacon_auth_value, &beacon_handle_secure_beacon_auth_value_calculated, subnet);
335 }
336 
beacon_handle_beacon_packet(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)337 static void beacon_handle_beacon_packet(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
338     log_info("beacon type %u", packet[0]);
339     switch (packet[0]){
340         case BEACON_TYPE_UNPROVISIONED_DEVICE:
341             if (unprovisioned_device_beacon_handler){
342                 (*unprovisioned_device_beacon_handler)(packet_type, channel, packet, size);
343             }
344             break;
345         case BEACON_TYPE_SECURE_NETWORK:
346             beacon_handle_secure_beacon(packet, size);
347             break;
348         default:
349             break;
350     }
351 }
352 
beacon_adv_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)353 static void beacon_adv_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
354     mesh_subnet_iterator_t it;
355     switch (packet_type){
356         case HCI_EVENT_PACKET:
357             switch(packet[0]){
358                 case HCI_EVENT_MESH_META:
359                     switch(packet[2]){
360                         case MESH_SUBEVENT_CAN_SEND_NOW:
361                             if (beacon_send_device_beacon){
362                                 beacon_send_device_beacon = 0;
363                                 adv_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len);
364                                 break;
365                             }
366                             // secure beacon state machine
367                             mesh_subnet_iterator_init(&it);
368                             while (mesh_subnet_iterator_has_more(&it)){
369                                 mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
370                                 switch (subnet->beacon_state){
371                                     case MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV:
372                                         adv_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len);
373                                         subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_ADV_SENT;
374                                         mesh_secure_network_beacon_run(NULL);
375                                         break;
376                                     default:
377                                         break;
378                                 }
379                             }
380                             break;
381                         default:
382                             break;
383                     }
384                     break;
385                 default:
386                     break;
387             }
388             break;
389         case MESH_BEACON_PACKET:
390             beacon_handle_beacon_packet(packet_type, channel, packet, size);
391             break;
392         default:
393             break;
394     }
395 }
396 #endif
397 
398 #ifdef ENABLE_MESH_GATT_BEARER
399 // handle MESH_SUBEVENT_PROXY_DISCONNECTED and MESH_SUBEVENT_CAN_SEND_NOW
beacon_gatt_handle_mesh_event(uint8_t mesh_subevent)400 static void beacon_gatt_handle_mesh_event(uint8_t mesh_subevent){
401     mesh_subnet_iterator_t it;
402     mesh_subnet_iterator_init(&it);
403     while (mesh_subnet_iterator_has_more(&it)){
404         mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
405         switch (subnet->beacon_state){
406             case MESH_SECURE_NETWORK_BEACON_W2_SEND_GATT:
407                 // skip send on MESH_SUBEVENT_PROXY_DISCONNECTED
408                 if (mesh_subevent == MESH_SUBEVENT_CAN_SEND_NOW){
409                     gatt_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len);
410                 }
411                 subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT;
412                 mesh_secure_network_beacon_run(NULL);
413                 break;
414             default:
415                 break;
416         }
417     }
418 
419 }
420 
beacon_gatt_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)421 static void beacon_gatt_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
422     uint8_t mesh_subevent;
423     switch (packet_type){
424         case HCI_EVENT_PACKET:
425             switch(packet[0]){
426                 case HCI_EVENT_MESH_META:
427                     mesh_subevent = packet[2];
428                     switch(mesh_subevent){
429                         case MESH_SUBEVENT_PROXY_CONNECTED:
430                             gatt_bearer_con_handle = mesh_subevent_proxy_connected_get_con_handle(packet);
431                             break;
432                         case MESH_SUBEVENT_PROXY_DISCONNECTED:
433                             gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID;
434                             beacon_gatt_handle_mesh_event(mesh_subevent);
435                             break;
436                         case MESH_SUBEVENT_CAN_SEND_NOW:
437                             beacon_gatt_handle_mesh_event(mesh_subevent);
438                             break;
439                         default:
440                             break;
441                     }
442                     break;
443                 default:
444                     break;
445             }
446             break;
447         case MESH_BEACON_PACKET:
448             beacon_handle_beacon_packet(packet_type, channel, packet, size);
449             break;
450         default:
451             break;
452     }
453 }
454 #endif
455 
beacon_init(void)456 void beacon_init(void){
457 #ifdef ENABLE_MESH_ADV_BEARER
458     adv_bearer_register_for_beacon(&beacon_adv_packet_handler);
459 #endif
460 #ifdef ENABLE_MESH_GATT_BEARER
461     gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID;
462     gatt_bearer_register_for_beacon(&beacon_gatt_packet_handler);
463 #endif
464 }
465 
466 /**
467  * Start Unprovisioned Device Beacon
468  */
beacon_unprovisioned_device_start(const uint8_t * device_uuid,uint16_t oob_information)469 void beacon_unprovisioned_device_start(const uint8_t * device_uuid, uint16_t oob_information){
470 #ifdef ENABLE_MESH_ADV_BEARER
471     beacon_oob_information = oob_information;
472     if (device_uuid){
473         beacon_device_uuid = device_uuid;
474         beacon_timer.process = &beacon_timer_handler;
475         btstack_run_loop_remove_timer(&beacon_timer);
476         beacon_timer_handler(&beacon_timer);
477     }
478 #endif
479 }
480 
481 /**
482  * Stop Unprovisioned Device Beacon
483  */
beacon_unprovisioned_device_stop(void)484 void beacon_unprovisioned_device_stop(void){
485 #ifdef ENABLE_MESH_ADV_BEARER
486     btstack_run_loop_remove_timer(&beacon_timer);
487     beacon_timer_active = 0;
488 #endif
489 }
490 
491 // secure network beacons
492 
beacon_secure_network_start(mesh_subnet_t * mesh_subnet)493 void beacon_secure_network_start(mesh_subnet_t * mesh_subnet){
494     // default interval
495     mesh_subnet->beacon_interval_ms = SECURE_NETWORK_BEACON_INTERVAL_MIN_MS;
496     mesh_subnet->beacon_observation_start_ms = btstack_run_loop_get_time_ms();
497     mesh_subnet->beacon_observation_counter = 0;
498     if (mesh_foundation_beacon_get()){
499         mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE;
500     } else {
501         mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_GATT_SENT;
502     }
503 
504     // start sending
505     mesh_secure_network_beacon_run(NULL);
506 }
507 
508 // register handler
beacon_register_for_unprovisioned_device_beacons(btstack_packet_handler_t packet_handler)509 void beacon_register_for_unprovisioned_device_beacons(btstack_packet_handler_t packet_handler){
510     unprovisioned_device_beacon_handler = packet_handler;
511 }
512 
beacon_register_for_secure_network_beacons(btstack_packet_handler_t packet_handler)513 void beacon_register_for_secure_network_beacons(btstack_packet_handler_t packet_handler){
514     mesh_secure_network_beacon_handler = packet_handler;
515 }
516