2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
27 #include <arpa/inet.h>
30 #include "thread-log.h"
31 #include "thread-private.h"
32 #include "thread-dbus-handler.h"
33 #include "thread-socket-handler.h"
35 #define THREAD_NETWORK_DEFAULT_NAME ""
36 #define THREAD_NETWORK_DEFAULT_KEY ""
37 #define THREAD_NETWORK_DEFAULT_PSKC ""
38 #define THREAD_NETWORK_DEFAULT_CHANNEL 0
39 #define THREAD_NETWORK_DEFAULT_EXTENDED_PANID 0
40 #define THREAD_NETWORK_DEFAULT_PANID 0
42 void _thread_network_free(thread_network_h network)
53 int thread_network_create(thread_network_h *network)
56 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
57 THREAD_CHECK_INIT_STATUS();
58 THREAD_VALIDATE_INPUT_PARAMETER(network);
60 thread_network_s *new_network = NULL;
61 new_network = g_malloc0(sizeof(thread_network_s));
64 THREAD_ERR("g_malloc0 failed");
65 return THREAD_ERROR_OUT_OF_MEMORY;
69 new_network->is_network_active = FALSE;
70 new_network->is_operational_network_set = FALSE;
71 (void)g_strlcpy(new_network->name,
72 THREAD_NETWORK_DEFAULT_NAME, THREAD_NETWORK_NAME_MAX + 1);
73 (void)g_strlcpy(new_network->key,
74 THREAD_NETWORK_DEFAULT_KEY, THREAD_NETWORK_KEY_STRING_MAX + 1);
75 (void)g_strlcpy(new_network->pskc,
76 THREAD_NETWORK_DEFAULT_PSKC, THREAD_NETWORK_PSKC_STRING_MAX + 1);
77 new_network->channel = THREAD_NETWORK_DEFAULT_CHANNEL;
78 new_network->extended_panid = THREAD_NETWORK_DEFAULT_EXTENDED_PANID;
79 new_network->panid = THREAD_NETWORK_DEFAULT_PANID;
80 *network = (thread_network_h)new_network;
83 return THREAD_ERROR_NONE;
86 int thread_network_destroy(thread_network_h network)
89 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
90 THREAD_CHECK_INIT_STATUS();
91 THREAD_VALIDATE_INPUT_PARAMETER(network);
93 thread_network_s *current_network = network;
95 if (current_network->is_operational_network_set) {
96 THREAD_DBG("Thread operational network set, can't be destroyed:: \
97 first unset the operational network");
98 return THREAD_ERROR_OPERATION_FAILED;
101 if (current_network->is_network_active) {
102 THREAD_DBG("Thread network active, can't be destroyed:: \
103 first reset the network");
104 return THREAD_ERROR_OPERATION_FAILED;
107 _thread_network_free(current_network);
108 current_network = NULL;
111 return THREAD_ERROR_NONE;
114 int thread_network_set_name(thread_network_h network, const char *name)
117 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
118 THREAD_CHECK_INIT_STATUS();
119 THREAD_VALIDATE_INPUT_PARAMETER(network);
120 THREAD_VALIDATE_INPUT_PARAMETER(name);
122 retv_if(strlen(name) > THREAD_NETWORK_NAME_MAX,
123 THREAD_ERROR_INVALID_PARAMETER);
125 THREAD_DBG("Network Name: %s", name);
127 thread_network_s *current_network = network;
128 (void)g_strlcpy(current_network->name, name, THREAD_NETWORK_NAME_MAX + 1);
131 return THREAD_ERROR_NONE;
134 int thread_network_set_key(thread_network_h network, const char *key)
137 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
138 THREAD_CHECK_INIT_STATUS();
139 THREAD_VALIDATE_INPUT_PARAMETER(network);
140 THREAD_VALIDATE_INPUT_PARAMETER(key);
142 retv_if(strlen(key) > THREAD_NETWORK_KEY_STRING_MAX,
143 THREAD_ERROR_INVALID_PARAMETER);
145 THREAD_DBG("Network key: %s", key);
147 thread_network_s *current_network = network;
148 (void)g_strlcpy(current_network->key, key, THREAD_NETWORK_KEY_STRING_MAX + 1);
151 return THREAD_ERROR_NONE;
154 int thread_network_set_pskc(thread_network_h network, const char *pskc)
157 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
158 THREAD_CHECK_INIT_STATUS();
159 THREAD_VALIDATE_INPUT_PARAMETER(network);
160 THREAD_VALIDATE_INPUT_PARAMETER(pskc);
162 retv_if(strlen(pskc) > THREAD_NETWORK_PSKC_STRING_MAX,
163 THREAD_ERROR_INVALID_PARAMETER);
165 THREAD_DBG("Network pskc: %s", pskc);
167 thread_network_s *current_network = network;
168 (void)g_strlcpy(current_network->pskc, pskc, THREAD_NETWORK_PSKC_STRING_MAX + 1);
171 return THREAD_ERROR_NONE;
174 int thread_network_set_channel(thread_network_h network, uint32_t channel)
177 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
178 THREAD_CHECK_INIT_STATUS();
179 THREAD_VALIDATE_INPUT_PARAMETER(network);
181 THREAD_DBG("Network channel: 0x%8.8x", channel);
183 thread_network_s *current_network = network;
184 current_network->channel = channel;
187 return THREAD_ERROR_NONE;
190 int thread_network_set_extended_panid(thread_network_h network, uint64_t extended_panid)
193 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
194 THREAD_CHECK_INIT_STATUS();
195 THREAD_VALIDATE_INPUT_PARAMETER(network);
197 THREAD_DBG("Network extended_panid: %zu", (size_t)extended_panid);
199 thread_network_s *current_network = network;
200 current_network->extended_panid = extended_panid;
203 return THREAD_ERROR_NONE;
206 int thread_network_set_panid(thread_network_h network, uint16_t panid)
209 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
210 THREAD_CHECK_INIT_STATUS();
211 THREAD_VALIDATE_INPUT_PARAMETER(network);
213 THREAD_DBG("Network panid: %u", panid);
215 thread_network_s *current_network = network;
216 current_network->panid = panid;
219 return THREAD_ERROR_NONE;
222 int thread_set_operational_network(thread_instance_h instance, thread_network_h network)
225 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
226 THREAD_CHECK_INIT_STATUS();
227 THREAD_VALIDATE_INPUT_PARAMETER(instance);
228 THREAD_VALIDATE_INPUT_PARAMETER(network);
230 thread_instance_s *current_instance = instance;
231 thread_network_s *current_network = network;
232 current_instance->network = network;
233 current_network->is_operational_network_set = TRUE;
236 return THREAD_ERROR_NONE;
239 int thread_unset_operational_network(thread_instance_h instance)
242 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
243 THREAD_CHECK_INIT_STATUS();
244 THREAD_VALIDATE_INPUT_PARAMETER(instance);
246 thread_instance_s *current_instance = instance;
247 thread_network_s *current_network = current_instance->network;
249 if (!current_network)
252 if (current_network->is_network_active) {
253 THREAD_DBG("Thread network active, can't be destroyed:: \
254 first reset the network");
255 return THREAD_ERROR_OPERATION_FAILED;
258 current_network->is_operational_network_set = FALSE;
259 current_instance->network = NULL;
263 return THREAD_ERROR_NONE;
266 int thread_network_set_active_dataset_tlvs(thread_instance_h instance,
267 const uint8_t *tlvs_buffer, int buf_length)
270 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
271 THREAD_CHECK_INIT_STATUS();
272 THREAD_VALIDATE_INPUT_PARAMETER(instance);
273 THREAD_VALIDATE_INPUT_PARAMETER(tlvs_buffer);
275 int ret = THREAD_ERROR_NONE;
276 GBytes *bytes = NULL;
277 GVariant *value = NULL;
279 /* Print input data */
280 char buf[THREAD_MAX_BUFFER_SIZE];
281 for (int i = 0; i < buf_length; i++)
282 snprintf(buf + i*2, 3, "%2.2x", tlvs_buffer[i]);
283 THREAD_DBG("Active dataset tlvs size: %d :: %s", buf_length, buf);
285 bytes = g_bytes_new(tlvs_buffer, buf_length);
287 ret = THREAD_ERROR_OPERATION_FAILED;
291 value = g_variant_new_from_bytes(G_VARIANT_TYPE_BYTESTRING, bytes, true);
293 ret = THREAD_ERROR_OPERATION_FAILED;
297 /* set "ActiveDatasetTlvs" dbus property */
298 ret = _thread_dbus_set_property(
299 THREAD_DBUS_PROPERTY_ACTIVE_DATASET_TLVS, value);
300 if (ret != THREAD_ERROR_NONE) {
301 ret = THREAD_ERROR_OPERATION_FAILED;
304 THREAD_DBG("Thread set active dataset tlvs successful");
308 g_variant_unref(value);
310 g_bytes_unref(bytes);
316 int thread_network_get_active_dataset_tlvs(thread_instance_h instance,
317 uint8_t **tlvs_buffer, int *buf_len)
320 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
321 THREAD_CHECK_INIT_STATUS();
322 THREAD_VALIDATE_INPUT_PARAMETER(instance);
323 THREAD_VALIDATE_INPUT_PARAMETER(tlvs_buffer);
324 THREAD_VALIDATE_INPUT_PARAMETER(buf_len);
326 /* get "ActiveDatasetTlvs" */
327 int ret = THREAD_ERROR_NONE;
328 char buffer[THREAD_MAX_BUFFER_SIZE];
330 int session_fd = _thread_get_socket_fd();
331 char cmd_buffer[THREAD_NETWORK_BUFFER_MAX];
334 snprintf(cmd_buffer, THREAD_NETWORK_BUFFER_MAX, "dataset active -x");
336 THREAD_DBG("DEBUG: NETWORK MESSAGE -> [%s]", cmd_buffer);
338 ret = _thread_socket_client_write(session_fd, cmd_buffer, strlen(cmd_buffer));
339 if (ret != THREAD_ERROR_NONE) {
340 THREAD_DBG("Failed to execute command %s", cmd_buffer);
343 THREAD_DBG("Executed command '%s' with size %zu", cmd_buffer, strlen(cmd_buffer));
346 ret = _thread_socket_client_read(session_fd, buffer);
347 if (ret != THREAD_ERROR_NONE && ret != THREAD_ERROR_ALREADY_DONE) {
348 THREAD_DBG("Socket response failed..");
352 *tlvs_buffer = g_malloc0(THREAD_MAX_BUFFER_SIZE*sizeof(uint8_t));
353 if (!(*tlvs_buffer)) {
354 /* LCOV_EXCL_START */
355 THREAD_ERR("g_malloc0 failed");
356 return THREAD_ERROR_OUT_OF_MEMORY;
360 while (index < THREAD_MAX_BUFFER_SIZE) {
361 if (buffer[index] == 'D')
364 (*tlvs_buffer)[index] = (uint8_t)buffer[index];
373 int thread_network_get_panid(thread_instance_h instance, uint16_t *panid)
376 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
377 THREAD_CHECK_INIT_STATUS();
378 THREAD_VALIDATE_INPUT_PARAMETER(instance);
379 THREAD_VALIDATE_INPUT_PARAMETER(panid);
381 int ret = THREAD_ERROR_NONE;
382 GVariant *out = NULL;
384 /* get "PanId" dbus property */
385 ret = _thread_dbus_get_property(
386 THREAD_DBUS_PROPERTY_PANID, &out);
387 retv_if(ret != THREAD_ERROR_NONE, ret);
389 g_variant_get(out, "q", panid);
390 THREAD_DBG("Thread PanId: %zu", (size_t)*panid);
391 g_variant_unref(out);
394 return THREAD_ERROR_NONE;
397 static int __thread_attach_active_network()
400 int ret = THREAD_ERROR_NONE;
402 THREAD_DBG("Attach current active network dataset");
403 ret = _thread_dbus_sync_method_call(THREAD_DBUS_ATTACH_METHOD,
404 g_variant_new("()"));
405 if (ret != THREAD_ERROR_NONE)
406 THREAD_ERR("Thread Attach failed");
408 THREAD_DBG("Thread Attach successful");
415 int thread_network_attach(thread_instance_h instance)
418 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
419 THREAD_CHECK_INIT_STATUS();
420 THREAD_VALIDATE_INPUT_PARAMETER(instance);
421 int ret = THREAD_ERROR_NONE;
423 thread_instance_s *current_instance = instance;
424 thread_network_s *network = current_instance->network;
427 ret = __thread_attach_active_network();
432 THREAD_DBG("Network Name: %s", network->name);
433 THREAD_DBG("Network key: %s", network->key);
434 THREAD_DBG("Network pskc: %s", network->pskc);
435 THREAD_DBG("Network channel: 0x%8.8x", network->channel);
437 THREAD_DBG("Network extended_panid: %zu", (size_t)network->extended_panid);
438 if (network->extended_panid == UINT64_MAX)
439 THREAD_DBG("extended_panid is UINT64_MAX, "\
440 "Random extended_panid will be used");
442 THREAD_DBG("Network panid: %u", network->panid);
443 if (network->panid == UINT16_MAX)
444 THREAD_DBG("panid is UINT16_MAX, Random panid will be used");
446 THREAD_DBG("Network is_active: %s",
447 network->is_network_active ? "Active" : "Not Active");
449 if (network->is_network_active) {
450 ret = __thread_attach_active_network();
454 THREAD_DBG("Attach the current device to Thread Network");
455 /* Network key builder */
456 GVariantBuilder *key_builder;
457 key_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
458 THREAD_DBG("key str length: %zu", strlen(network->key));
459 for (int i = 0; i < strlen(network->key); i++) {
460 g_variant_builder_add(key_builder, "y",
461 (unsigned char)network->key[i]);
465 GVariantBuilder *pskc_builder;
466 pskc_builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
467 THREAD_DBG("pskc str length: %zu", strlen(network->pskc));
468 for (int i = 0; i < strlen(network->pskc); i++) {
469 g_variant_builder_add(pskc_builder, "y",
470 (unsigned char)network->pskc[i]);
473 THREAD_DBG("Thread dbus sync call...");
474 ret = _thread_dbus_sync_method_call(THREAD_DBUS_ATTACH_METHOD,
475 g_variant_new("(ayqstayu)", key_builder, network->panid,
476 network->name, network->extended_panid, pskc_builder, network->channel));
478 g_variant_builder_unref(key_builder);
479 g_variant_builder_unref(pskc_builder);
481 if (ret != THREAD_ERROR_NONE) {
482 THREAD_ERR("Thread Attach failed");
485 network->is_network_active = TRUE;
487 THREAD_DBG("Thread Attach successful");
494 static int __thread_detach_active_network()
497 int ret = THREAD_ERROR_NONE;
499 THREAD_DBG("Detach current active network dataset");
500 ret = _thread_dbus_sync_method_call(THREAD_DBUS_DETACH_METHOD,
501 g_variant_new("()"));
502 if (ret != THREAD_ERROR_NONE)
503 THREAD_ERR("Thread Detach failed");
505 THREAD_DBG("Thread Detach successful");
511 int thread_network_detach(thread_instance_h instance)
514 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
515 THREAD_CHECK_INIT_STATUS();
516 THREAD_VALIDATE_INPUT_PARAMETER(instance);
517 int ret = THREAD_ERROR_NONE;
519 thread_instance_s *current_instance = instance;
520 thread_network_s *network = current_instance->network;
523 return THREAD_ERROR_INVALID_PARAMETER;
525 if (network->is_network_active == TRUE)
526 ret = __thread_detach_active_network();
528 if (ret != THREAD_ERROR_NONE) {
529 THREAD_ERR("Thread Detach failed");
532 network->is_network_active = FALSE;
533 THREAD_DBG("Thread Detach successful");
540 int thread_get_ipaddr(thread_instance_h instance, thread_ipaddr_foreach_cb callback,
541 thread_ipaddr_type_e ipaddr_type, void *user_data)
544 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
545 THREAD_CHECK_INIT_STATUS();
546 THREAD_VALIDATE_INPUT_PARAMETER(instance);
548 int ret = THREAD_ERROR_NONE;
549 char buffer[THREAD_MAX_BUFFER_SIZE];
553 char ipaddr[THREAD_IPV6_ADDRESS_LEN];
555 int session_fd = _thread_get_socket_fd();
556 char cmd_buffer[THREAD_NETWORK_BUFFER_MAX];
558 switch (ipaddr_type) {
559 case THREAD_IPADDR_TYPE_LINK_LOCAL:
560 snprintf(cmd_buffer, THREAD_NETWORK_BUFFER_MAX, "ipaddr linklocal");
562 case THREAD_IPADDR_TYPE_RLOC:
563 snprintf(cmd_buffer, THREAD_NETWORK_BUFFER_MAX, "ipaddr rloc");
565 case THREAD_IPADDR_TYPE_MLEID:
566 snprintf(cmd_buffer, THREAD_NETWORK_BUFFER_MAX, "ipaddr mleid");
569 snprintf(cmd_buffer, THREAD_NETWORK_BUFFER_MAX, "ipaddr");
572 size_t buf_size = strlen(cmd_buffer);
574 THREAD_DBG("DEBUG: NETWORK MESSAGE -> [%s]", cmd_buffer);
576 ret = _thread_socket_client_write(session_fd, cmd_buffer, buf_size);
577 if (ret != THREAD_ERROR_NONE) {
578 THREAD_DBG("Failed to execute command %s", cmd_buffer);
581 THREAD_DBG("Executed command '%s' with size %zu", cmd_buffer, buf_size);
584 ret = _thread_socket_client_read(session_fd, buffer);
585 if (ret != THREAD_ERROR_NONE && ret != THREAD_ERROR_ALREADY_DONE) {
586 THREAD_DBG("Socket response failed..");
591 if ((buffer[index] >= 'a' && buffer[index] <= 'f') || buffer[index] == ':'
592 || (buffer[index] >= '0' && buffer[index] <= '9')) {
593 ipaddr[pos++] = buffer[index];
594 } else if (buffer[index] == 'D') {
595 THREAD_DBG("Socket read response buffer: Done");
600 THREAD_DBG("IP address: %s, length: %zu", ipaddr,
602 callback(++count, ipaddr, ipaddr_type, user_data);
613 static bool __is_valid_ipv6(const uint8_t* ipv6_address)
618 while (index < THREAD_IPV6_ADDRESS_SIZE) {
619 char buffer[THREAD_NETWORK_BUFFER_MAX];
620 snprintf(buffer, THREAD_NETWORK_BUFFER_MAX, "%02x", ipv6_address[index]);
621 if ((buffer[0] < '0' || buffer[0] > '9') &&
622 (buffer[0] < 'a' || buffer[0] > 'f'))
624 if ((buffer[1] < '0' || buffer[1] > '9') &&
625 (buffer[1] < 'a' || buffer[1] > 'f'))
630 THREAD_DBG("DEBUG: NETWORK MESSAGE -> return true");
636 int thread_add_ipaddr(thread_instance_h instance, const uint8_t *ipv6_address)
639 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
640 THREAD_CHECK_INIT_STATUS();
641 THREAD_VALIDATE_INPUT_PARAMETER(instance);
642 THREAD_VALIDATE_INPUT_PARAMETER(ipv6_address);
644 int ret = THREAD_ERROR_NONE;
645 char msg[THREAD_NETWORK_BUFFER_MAX];
647 retv_if(!__is_valid_ipv6(ipv6_address), THREAD_ERROR_INVALID_PARAMETER);
649 snprintf(msg, THREAD_NETWORK_BUFFER_MAX,
650 "ipaddr add %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
651 ipv6_address[0], ipv6_address[1], ipv6_address[2], ipv6_address[3],
652 ipv6_address[4], ipv6_address[5], ipv6_address[6], ipv6_address[7],
653 ipv6_address[8], ipv6_address[9], ipv6_address[10], ipv6_address[11],
654 ipv6_address[12], ipv6_address[13], ipv6_address[14], ipv6_address[15]);
656 ret = _thread_socket_client_execute(_thread_get_socket_fd(), msg, strlen(msg));
657 retv_if(ret != THREAD_ERROR_NONE, ret);
658 THREAD_DBG("Successfully added address");
664 int thread_remove_ipaddr(thread_instance_h instance, const uint8_t *ipv6_address)
667 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
668 THREAD_CHECK_INIT_STATUS();
669 THREAD_VALIDATE_INPUT_PARAMETER(instance);
670 THREAD_VALIDATE_INPUT_PARAMETER(ipv6_address);
672 int ret = THREAD_ERROR_NONE;
673 char msg[THREAD_NETWORK_BUFFER_MAX];
675 retv_if(!__is_valid_ipv6(ipv6_address), THREAD_ERROR_INVALID_PARAMETER);
677 snprintf(msg, THREAD_BORDER_ROUTER_BUFFER_MAX,
678 "ipaddr del %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
679 ipv6_address[0], ipv6_address[1], ipv6_address[2], ipv6_address[3],
680 ipv6_address[4], ipv6_address[5], ipv6_address[6], ipv6_address[7],
681 ipv6_address[8], ipv6_address[9], ipv6_address[10], ipv6_address[11],
682 ipv6_address[12], ipv6_address[13], ipv6_address[14], ipv6_address[15]);
684 ret = _thread_socket_client_execute(_thread_get_socket_fd(), msg, strlen(msg));
685 retv_if(ret != THREAD_ERROR_NONE, ret);
686 THREAD_DBG("Successfully removed address");
692 int thread_get_global_ipaddr(thread_instance_h instance, const char **ipaddr)
695 THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
696 THREAD_CHECK_INIT_STATUS();
697 THREAD_VALIDATE_INPUT_PARAMETER(instance);
699 int ret = THREAD_ERROR_NONE;
700 char buffer[THREAD_MAX_BUFFER_SIZE];
701 int session_fd = _thread_get_socket_fd();
702 const char *msg = THREAD_IPADDR_V;
703 char *ret_ptr, *next_ptr;
705 ret = _thread_socket_client_write(session_fd, msg, strlen(msg));
706 if (ret != THREAD_ERROR_NONE) {
707 THREAD_DBG("Failed to execute command %s", msg);
710 THREAD_DBG("Executed command '%s' with size %zu", msg, strlen(msg));
713 ret = _thread_socket_client_read(session_fd, buffer);
714 if (ret != THREAD_ERROR_NONE && ret != THREAD_ERROR_ALREADY_DONE) {
715 THREAD_DBG("Socket response failed..");
719 /* result is like below:
721 * fdd6:54c2:ee47:f2d2:0:ff:fe00:9400 origin:thread
722 * fd0b:8d9c:ac8c:1:2c82:12dd:825b:70c4 origin:slaac
723 * fdd6:54c2:ee47:f2d2:b267:e8fa:5bd6:2891 origin:thread
724 * fe80:0:0:0:5857:6a63:d5f1:91b6 origin:thread
727 ret_ptr = strtok_r(buffer, "\n", &next_ptr);
729 if (strstr(ret_ptr, "origin:slaac")) {
730 strtok_r(ret_ptr, " ", &next_ptr);
731 THREAD_DBG("Global Ipaddr: %s", ret_ptr);
732 *ipaddr = g_strdup(ret_ptr);
733 return THREAD_ERROR_NONE;
735 ret_ptr = strtok_r(NULL, "\n", &next_ptr);