Mesh: Add Node Reset API in FRWK
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / mesh / bt-service-mesh-nodes.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5  *
6  * @author: Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 #include <glib.h>
22 #include <dlog.h>
23 #include "bt-service-common.h"
24 #include "bt-service-core-adapter.h"
25 #include "bt-service-event-receiver.h"
26 #include "bt-request-handler.h"
27 #include "bluetooth-api.h"
28
29 #include "bluetooth-api.h"
30 #include "bluetooth-mesh-api.h"
31 #include "bt-internal-types.h"
32 #include "bt-service-util.h"
33 #include "bt-service-common.h"
34 #include "bt-service-event.h"
35
36 #include "bt-service-mesh-cdb.h"
37 #include "bt-service-mesh-keys.h"
38 #include "bt-service-mesh-util.h"
39
40 #include <ell/ell.h>
41
42 #include "bt-internal-types.h"
43
44 struct _bt_mesh_node_t {
45         uint16_t unicast;
46         struct l_queue *net_keys;
47         struct l_queue *app_keys;
48         struct l_queue **els;
49         uint8_t uuid[16];
50         uint8_t num_ele;
51 };
52
53 struct mesh_network_t {
54         uint8_t net_uuid[16];
55         struct l_queue *nodes;
56 };
57
58 static struct l_queue *networks;
59
60 struct mesh_key_index {
61         uint8_t uuid[16];
62         uint16_t idx;
63 };
64
65 static bool __mesh_match_bound_key(const void *a, const void *b)
66 {
67         uint16_t app_idx = L_PTR_TO_UINT(a);
68         const struct mesh_key_index *data = b;
69
70         uint16_t net_idx = L_PTR_TO_UINT(b);
71
72         return (net_idx == _bt_mesh_keys_get_bound_key(
73                                 (uint8_t*)data->uuid, app_idx));
74 }
75
76 static bool __mesh_match_node_dev_uuid(const void *a, const void *b)
77 {
78         const struct _bt_mesh_node_t *node = a;
79         uint8_t* dev_uuid = (uint8_t*)b;
80
81         if (memcmp(node->uuid, dev_uuid, 16) == 0) {
82                 BT_INFO("Mesh: Found Node with given Dev UUID");
83                 return true;
84         }
85
86         return false;
87 }
88
89 static bool __mesh_net_uuid_match(const void *a, const void *b)
90 {
91         const struct mesh_network_t *net = a;
92         uint8_t* uuid = (uint8_t*)b;
93
94         if (memcmp(net->net_uuid, uuid, 16) == 0) {
95                 BT_INFO("Mesh: Found network with given Net UUID");
96                 return true;
97         }
98
99         return false;
100 }
101
102 static bool __mesh_remove_node_entry(void *a, void *b)
103 {
104         uint8_t num_ele, i;
105         struct _bt_mesh_node_t *rmt = (struct _bt_mesh_node_t*) a;
106
107         num_ele = rmt->num_ele;
108
109         for (i = 0; i < num_ele; ++i)
110                 l_queue_destroy(rmt->els[i], NULL);
111
112         l_free(rmt->els);
113
114         l_queue_destroy(rmt->net_keys, l_free);
115         l_queue_destroy(rmt->app_keys, l_free);
116
117         l_free(rmt);
118         return true;
119 }
120
121 static bool __mesh_key_present(struct l_queue *keys, uint16_t app_idx)
122 {
123         const struct l_queue_entry *l;
124
125         for (l = l_queue_get_entries(keys); l; l = l->next) {
126                 uint16_t idx = L_PTR_TO_UINT(l->data);
127
128                 if (idx == app_idx)
129                         return true;
130         }
131
132         return false;
133 }
134
135 static int __mesh_compare_mod_id(const void *a, const void *b,
136                 void *user_data)
137 {
138         uint32_t id1 = L_PTR_TO_UINT(a);
139         uint32_t id2 = L_PTR_TO_UINT(b);
140
141         if (id1 >= MESH_VENDOR_ID_MASK)
142                 id1 &= ~MESH_VENDOR_ID_MASK;
143
144         if (id2 >= MESH_VENDOR_ID_MASK)
145                 id2 &= ~MESH_VENDOR_ID_MASK;
146
147         if (id1 < id2)
148                 return -1;
149
150         if (id1 > id2)
151                 return 1;
152
153         return 0;
154 }
155
156 static int __mesh_compare_unicast(const void *a, const void *b,
157                 void *user_data)
158 {
159         const struct _bt_mesh_node_t *a_rmt = a;
160         const struct _bt_mesh_node_t *b_rmt = b;
161
162         if (a_rmt->unicast < b_rmt->unicast)
163                 return -1;
164
165         if (a_rmt->unicast > b_rmt->unicast)
166                 return 1;
167
168         return 0;
169 }
170
171 static bool __mesh_match_node_addr(const void *a, const void *b)
172 {
173         const struct _bt_mesh_node_t *rmt = a;
174         uint16_t addr = L_PTR_TO_UINT(b);
175
176         if (addr >= rmt->unicast &&
177                         addr <= (rmt->unicast + rmt->num_ele - 1))
178                 return true;
179
180         return false;
181 }
182
183 void _bt_mesh_node_load_net(uint8_t net_uuid[])
184 {
185         struct mesh_network_t *network;
186         BT_INFO("Mesh:Nodes: Create new network");
187
188         if (l_queue_find(networks, __mesh_net_uuid_match, net_uuid))
189                 return;
190
191         if (!networks)
192                 networks = l_queue_new();
193
194         network = l_new(struct mesh_network_t, 1);
195         memcpy(network->net_uuid, net_uuid, 16);
196         network->nodes =  l_queue_new();
197         l_queue_push_tail(networks, network);
198 }
199
200 void _bt_mesh_node_unload_net(uint8_t net_uuid[])
201 {
202         struct mesh_network_t *network;
203         int numnodes;
204         BT_INFO("Mesh:Nodes: Unload network with all nodes");
205
206         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
207         if (!network || !network->nodes)
208                 return;
209
210         /* Only remove the ndoe from the Local Network object:
211            DONT touch configuration file */
212         numnodes = l_queue_foreach_remove(network->nodes,
213                         __mesh_remove_node_entry, NULL);
214         BT_INFO("Mesh:Nodes: Unloadeded [%d] Nodes from the network", numnodes);
215         l_queue_remove(networks, network);
216         l_free(network);
217
218         BT_INFO("Mesh: After unloading, number of networks [%d]",
219                 l_queue_length(networks));
220 }
221
222 bool _bt_mesh_node_get_unicast_from_dev_uuid(uint8_t net_uuid[],
223                 const uint8_t dev_uuid[], uint16_t *unicast)
224 {
225         struct _bt_mesh_node_t *rmt;
226         struct mesh_network_t *network;
227
228         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
229         if (!network)
230                 return false;
231
232         rmt = l_queue_find(network->nodes,
233                         __mesh_match_node_dev_uuid, dev_uuid);
234         if (!rmt)
235                 return false;
236
237         *unicast = rmt->unicast;
238         return true;
239 }
240
241 bool _bt_mesh_node_get_element_count(uint8_t net_uuid[],
242                 uint16_t unicast, uint8_t *count)
243 {
244         struct _bt_mesh_node_t *rmt;
245         struct mesh_network_t *network;
246
247         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
248         if (!network)
249                 return false;
250
251         rmt = l_queue_find(network->nodes, __mesh_match_node_addr,
252                         L_UINT_TO_PTR(unicast));
253         if (!rmt)
254                 return false;
255
256         *count = rmt->num_ele;
257
258         return true;
259 }
260
261 uint8_t _bt_mesh_node_del_node(_bt_mesh_cdb_t *cfg,
262                 uint16_t unicast)
263 {
264         struct _bt_mesh_node_t *rmt;
265         uint8_t num_ele, i;
266         struct mesh_network_t *network;
267
268         if (!cfg)
269                 return 0;
270
271         BT_INFO("Mesh: Uload Node Entry [0x%2.2x]", unicast);
272         network = l_queue_find(networks, __mesh_net_uuid_match, cfg->uuid);
273         if (!network)
274                 return 0;
275
276         rmt = l_queue_find(network->nodes,
277                         __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
278         if (!rmt)
279                 return 0;
280
281         rmt = l_queue_remove_if(network->nodes, __mesh_match_node_addr,
282                         L_UINT_TO_PTR(unicast));
283         if (!rmt)
284                 return 0;
285
286         num_ele = rmt->num_ele;
287
288         for (i = 0; i < num_ele; ++i)
289                 l_queue_destroy(rmt->els[i], NULL);
290
291         l_free(rmt->els);
292
293         l_queue_destroy(rmt->net_keys, NULL);
294         l_queue_destroy(rmt->app_keys, NULL);
295         l_free(rmt);
296
297         return num_ele;
298 }
299
300 bool _bt_mesh_node_add_node(uint8_t net_uuid[],
301         const uint8_t node_uuid[16], uint16_t unicast,
302                 uint8_t ele_cnt, uint16_t net_idx)
303 {
304         struct _bt_mesh_node_t *rmt;
305         struct mesh_network_t *network;
306
307         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
308         if (!network)
309                 return false;
310
311         rmt = l_queue_find(network->nodes,
312                         __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
313         if (rmt)
314                 return false;
315
316         rmt = l_new(struct _bt_mesh_node_t, 1);
317         memcpy(rmt->uuid, node_uuid, 16);
318         rmt->unicast = unicast;
319         rmt->num_ele = ele_cnt;
320         rmt->net_keys = l_queue_new();
321
322         l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
323
324         rmt->els = l_new(struct l_queue *, ele_cnt);
325
326         if (!network->nodes)
327                 network->nodes = l_queue_new();
328
329         if (l_queue_insert(network->nodes, rmt, __mesh_compare_unicast, NULL))
330                 BT_INFO("Mesh: node added to Network");
331         else
332                 BT_INFO("Mesh: node could not be added to Network");
333         return true;
334 }
335
336 bool _bt_mesh_node_get_models(uint8_t net_uuid[],
337                 uint16_t unicast, uint8_t ele_idx,
338                         GArray **out)
339 {
340         struct _bt_mesh_node_t *rmt;
341         struct mesh_network_t *network;
342         const struct l_queue_entry *entry;
343
344         BT_INFO("Mesh: Get All Models in an element [0x%4.4x] Index [0x%x]",
345                         unicast, ele_idx);
346
347         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
348         if (!network)
349                 return false;
350
351         rmt = l_queue_find(network->nodes,
352                         __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
353         if (!rmt)
354                 return false;
355
356         if (!rmt->els[ele_idx])
357                 return false;
358
359         entry = l_queue_get_entries(rmt->els[ele_idx]);
360
361         BT_INFO("Mesh: Total Models in Element [%d]",
362                         l_queue_length(rmt->els[ele_idx]));
363         for (; entry; entry = entry->next) {
364                 uint32_t model = L_PTR_TO_UINT(entry->data);
365                 g_array_append_vals(*out, &model, sizeof(uint32_t));
366                 BT_INFO("Mesh: Appended Model ID [0x%4.4x]", model);
367         }
368         return true;
369 }
370
371 bool _bt_mesh_node_set_model(uint8_t net_uuid[],
372         uint16_t unicast, uint8_t ele_idx,
373                 uint32_t mod_id, bool vendor)
374 {
375         struct _bt_mesh_node_t *rmt;
376         struct mesh_network_t *network;
377
378         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
379         if (!network)
380                 return false;
381
382         rmt = l_queue_find(network->nodes,
383                         __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
384         if (!rmt)
385                 return false;
386
387         if (ele_idx >= rmt->num_ele)
388                 return false;
389
390         if (!rmt->els[ele_idx])
391                 rmt->els[ele_idx] = l_queue_new();
392
393         if (!vendor)
394                 mod_id = MESH_VENDOR_ID_MASK | mod_id;
395
396         BT_INFO("Mesh: Insert Model in Element Index [0x%x]", ele_idx);
397         BT_INFO("Mesh: Insert Model Id [0x%4.4x]", mod_id);
398         l_queue_insert(rmt->els[ele_idx], L_UINT_TO_PTR(mod_id),
399                         __mesh_compare_mod_id, NULL);
400
401         BT_INFO("Mesh: Current model count after update in element is [%d]",
402                         l_queue_length(rmt->els[ele_idx]));
403
404         return true;
405 }
406
407 bool _bt_mesh_node_del_net_key(_bt_mesh_cdb_t *cfg,
408         uint8_t net_uuid[], uint16_t addr,
409                 uint16_t net_idx)
410 {
411         struct _bt_mesh_node_t *rmt;
412         void *data;
413         struct mesh_network_t *network;
414         struct mesh_key_index *user_data;
415
416         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
417         if (!network)
418                 return false;
419
420         rmt = l_queue_find(network->nodes,
421                         __mesh_match_node_addr, L_UINT_TO_PTR(addr));
422         if (!rmt)
423                 return false;
424
425         if (!l_queue_remove(rmt->net_keys, L_UINT_TO_PTR(net_idx)))
426                 return false;
427
428         user_data = g_malloc0(sizeof(struct mesh_key_index));
429         memcpy(user_data->uuid, net_uuid, 16);
430         user_data->idx = net_idx;
431
432         data = l_queue_remove_if(rmt->app_keys,
433                         __mesh_match_bound_key, user_data);
434         while (data) {
435                 uint16_t app_idx = (uint16_t) L_PTR_TO_UINT(data);
436
437                 _bt_mesh_conf_node_delete_application_key(cfg, rmt->unicast, app_idx);
438                 data = l_queue_remove_if(rmt->app_keys,
439                                 __mesh_match_bound_key, user_data);
440         }
441
442         g_free(user_data);
443         return true;
444 }
445
446 bool _bt_mesh_node_get_all_appkeys(uint8_t net_uuid[],
447                 uint16_t unicast, uint16_t netkey, GArray **out)
448 {
449         struct mesh_network_t *network;
450         const struct l_queue_entry *entry;
451         struct _bt_mesh_node_t *rmt;
452
453         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
454         if (!network)
455                 return false;
456
457         rmt = l_queue_find(network->nodes,
458                 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
459         if (!rmt)
460                 return false;
461
462         entry = l_queue_get_entries(rmt->app_keys);
463
464         for (; entry; entry = entry->next) {
465                 uint16_t net_idx;
466                 uint16_t app_idx = L_PTR_TO_UINT(entry->data);
467                 net_idx = _bt_mesh_keys_get_bound_key(net_uuid, app_idx);
468                 if (net_idx == netkey)
469                         g_array_append_vals(*out, &app_idx, sizeof(uint16_t));
470         }
471         return true;
472 }
473
474 bool _bt_mesh_node_get_all_netkeys(uint8_t net_uuid[],
475                 uint16_t unicast, GArray **out)
476 {
477         struct mesh_network_t *network;
478         const struct l_queue_entry *entry;
479         struct _bt_mesh_node_t *rmt;
480
481         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
482         if (!network)
483                 return false;
484
485         rmt = l_queue_find(network->nodes,
486                         __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
487         if (!rmt)
488                 return false;
489
490         entry = l_queue_get_entries(rmt->net_keys);
491
492         for (; entry; entry = entry->next) {
493
494                 uint16_t net_idx = L_PTR_TO_UINT(entry->data);
495
496                 g_array_append_vals(*out, &net_idx, sizeof(uint16_t));
497         }
498         return true;
499 }
500
501 bool _bt_mesh_node_get_all(uint8_t net_uuid[], GArray **out)
502 {
503         struct mesh_network_t *network;
504         const struct l_queue_entry *entry;
505         bluetooth_mesh_node_info_t n;
506
507         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
508         if (!network)
509                 return false;
510
511         entry = l_queue_get_entries(network->nodes);
512
513         for (; entry; entry = entry->next) {
514
515                 memset(&n, 0x00, sizeof(bluetooth_mesh_node_info_t));
516                 struct _bt_mesh_node_t *node = entry->data;
517
518                 n.primary_unicast = node->unicast;
519                 _bt_mesh_util_convert_hex_to_string(node->uuid, 16,
520                         n.dev_uuid, sizeof(n.dev_uuid));
521                 BT_INFO("Mesh: Dev UUID [%s]", n.dev_uuid);
522
523                 g_array_append_vals(*out, &n,
524                                 sizeof(bluetooth_mesh_node_info_t));
525         }
526         return true;
527 }
528
529 bool _bt_mesh_node_is_netkey_added_in_network(uint8_t net_uuid[],
530                 uint16_t net_idx)
531 {
532         struct mesh_network_t *network;
533         const struct l_queue_entry *entry;
534
535         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
536         if (!network)
537                 return false;
538
539         entry = l_queue_get_entries(network->nodes);
540
541         for (; entry; entry = entry->next) {
542                 struct _bt_mesh_node_t *node = entry->data;
543
544                 if (__mesh_key_present(node->net_keys, net_idx))
545                         return true;
546         }
547         return false;
548 }
549
550 bool _bt_mesh_node_is_appkey_added_in_network(uint8_t net_uuid[],
551                 uint16_t app_idx)
552 {
553         struct mesh_network_t *network;
554         const struct l_queue_entry *entry;
555
556         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
557         if (!network)
558                 return false;
559
560         entry = l_queue_get_entries(network->nodes);
561
562         for (; entry; entry = entry->next) {
563                 struct _bt_mesh_node_t *node = entry->data;
564
565                 if (__mesh_key_present(node->app_keys, app_idx))
566                         return true;
567         }
568         return false;
569 }
570
571 bool _bt_mesh_node_is_appkey_exists(uint8_t net_uuid[],
572                 uint16_t addr, uint16_t app_idx)
573 {
574         struct _bt_mesh_node_t *rmt;
575         struct mesh_network_t *network;
576
577         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
578         if (!network)
579                 return false;
580
581         rmt = l_queue_find(network->nodes,
582                         __mesh_match_node_addr, L_UINT_TO_PTR(addr));
583         if (!rmt)
584                 return false;
585
586         if (__mesh_key_present(rmt->app_keys, app_idx))
587                 return true;
588
589         return false;
590 }
591
592 bool _bt_mesh_node_is_netkey_exists(uint8_t net_uuid[],
593                 uint16_t addr, uint16_t net_idx)
594 {
595         struct _bt_mesh_node_t *rmt;
596         struct mesh_network_t *network;
597
598         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
599         if (!network)
600                 return false;
601
602         rmt = l_queue_find(network->nodes,
603                         __mesh_match_node_addr, L_UINT_TO_PTR(addr));
604         if (!rmt)
605                 return false;
606
607         if (__mesh_key_present(rmt->net_keys, net_idx))
608                 return true;
609
610         return false;
611 }
612
613 bool _bt_mesh_node_add_net_key(uint8_t net_uuid[],
614                 uint16_t addr, uint16_t net_idx)
615 {
616         struct _bt_mesh_node_t *rmt;
617         struct mesh_network_t *network;
618
619         network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
620         if (!network)
621                 return false;
622
623         rmt = l_queue_find(network->nodes,
624                         __mesh_match_node_addr, L_UINT_TO_PTR(addr));
625         if (!rmt)
626                 return false;
627
628         if (__mesh_key_present(rmt->net_keys, net_idx))
629                 return true;
630
631         l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
632         return true;
633 }
634
635 bool _bt_mesh_node_add_app_key(uint8_t net_uuid[],
636                 uint16_t addr, uint16_t app_idx)
637 {
638         struct _bt_mesh_node_t *rmt;
639         struct mesh_network_t *network;
640
641         network = l_queue_find(networks,
642                         __mesh_net_uuid_match, net_uuid);
643         if (!network)
644                 return false;
645
646         rmt = l_queue_find(network->nodes,
647                         __mesh_match_node_addr, L_UINT_TO_PTR(addr));
648         if (!rmt)
649                 return false;
650
651         if (!rmt->app_keys)
652                 rmt->app_keys = l_queue_new();
653
654         if (__mesh_key_present(rmt->app_keys, app_idx))
655                 return false;
656
657         l_queue_push_tail(rmt->app_keys, L_UINT_TO_PTR(app_idx));
658         BT_INFO("Mesh: Total appkeys present in node [%d]",
659                         l_queue_length(rmt->app_keys));
660         return true;
661 }
662
663 bool _bt_mesh_node_del_app_key(uint8_t net_uuid[],
664                 uint16_t addr, uint16_t app_idx)
665 {
666         struct _bt_mesh_node_t *rmt;
667         struct mesh_network_t *network;
668
669         network = l_queue_find(networks,
670                         __mesh_net_uuid_match, net_uuid);
671         if (!network) {
672                 BT_INFO("Mesh: Could not find Network");
673                 return false;
674         }
675
676         rmt = l_queue_find(network->nodes,
677                         __mesh_match_node_addr, L_UINT_TO_PTR(addr));
678         if (!rmt) {
679                 BT_INFO("Mesh: Remote Node not found!");
680                 return false;
681         }
682
683         BT_INFO("Mesh: Total appkeys present in node [%d]",
684                         l_queue_length(rmt->app_keys));
685         BT_INFO("Mesh: To be deleted AppKey Idx [0x%2.2x]", app_idx);
686         return l_queue_remove(rmt->app_keys, L_UINT_TO_PTR(app_idx));
687 }
688
689 uint16_t _bt_mesh_node_get_subnet_idx(uint8_t net_uuid[],
690                 uint16_t addr)
691 {
692         struct _bt_mesh_node_t *rmt;
693         uint32_t net_idx;
694         struct mesh_network_t *network;
695
696         network = l_queue_find(networks,
697                         __mesh_net_uuid_match, net_uuid);
698         if (!network)
699                 return MESH_NET_IDX_INVALID;
700
701         rmt = l_queue_find(network->nodes,
702                         __mesh_match_node_addr, L_UINT_TO_PTR(addr));
703
704         if (!rmt || l_queue_isempty(rmt->net_keys))
705                 return MESH_NET_IDX_INVALID;
706
707         net_idx = L_PTR_TO_UINT(l_queue_peek_head(rmt->net_keys));
708
709         return (uint16_t) net_idx;
710 }
711
712 uint16_t _bt_mesh_node_get_next_unicast(uint8_t net_uuid[],
713                 uint16_t low, uint16_t high, uint8_t ele_cnt)
714 {
715         struct _bt_mesh_node_t *rmt;
716         const struct l_queue_entry *l;
717         uint16_t addr;
718         struct mesh_network_t *network;
719
720         network = l_queue_find(networks,
721                         __mesh_net_uuid_match, net_uuid);
722         if (!network) {
723                 BT_ERR("Mesh: Net UUID did not match");
724                 return 0;
725         }
726
727         /* Note: the address space includes both
728            low and high terminal values */
729         if (ele_cnt > (high - low + 1))
730                 return 0;
731
732         if (!network->nodes || l_queue_isempty(network->nodes))
733                 return low;
734
735         addr = low;
736         l = l_queue_get_entries(network->nodes);
737
738         /* Cycle through the sorted (by unicast) node list */
739         for (; l; l = l->next) {
740                 rmt = l->data;
741
742                 if (rmt->unicast >= (addr + ele_cnt))
743                         return addr;
744
745                 if ((rmt->unicast + rmt->num_ele) > addr)
746                         addr = rmt->unicast + rmt->num_ele;
747         }
748
749         if ((addr + ele_cnt - 1) <= high)
750                 return addr;
751
752         return 0;
753 }