+ if (cbitem && cbitem->adapter)
+ {
+ cbitem->callback(cbitem->adapter, status);
+ }
+ }
+}
+
+CAResult_t CAIPSetNetworkMonitorCallback(CAIPAdapterStateChangeCallback callback,
+ CATransportAdapter_t adapter)
+{
+ if (!callback)
+ {
+ OIC_LOG(ERROR, TAG, "callback is null");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ CAIPCBData_t *cbitem = NULL;
+ LL_FOREACH(g_adapterCallbackList, cbitem)
+ {
+ if (cbitem && adapter == cbitem->adapter && callback == cbitem->callback)
+ {
+ OIC_LOG(DEBUG, TAG, "this callback is already added");
+ return CA_STATUS_OK;
+ }
+ }
+
+ cbitem = (CAIPCBData_t *)OICCalloc(1, sizeof(*cbitem));
+ if (!cbitem)
+ {
+ OIC_LOG(ERROR, TAG, "Malloc failed");
+ return CA_STATUS_FAILED;
+ }
+
+ cbitem->adapter = adapter;
+ cbitem->callback = callback;
+ LL_APPEND(g_adapterCallbackList, cbitem);
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAIPUnSetNetworkMonitorCallback(CATransportAdapter_t adapter)
+{
+ CAIPCBData_t *cbitem = NULL;
+ CAIPCBData_t *tmpCbitem = NULL;
+ LL_FOREACH_SAFE(g_adapterCallbackList, cbitem, tmpCbitem)
+ {
+ if (cbitem && adapter == cbitem->adapter)
+ {
+ OIC_LOG(DEBUG, TAG, "remove specific callback");
+ LL_DELETE(g_adapterCallbackList, cbitem);
+ OICFree(cbitem);
+ return CA_STATUS_OK;
+ }
+ }
+ return CA_STATUS_OK;
+}
+
+u_arraylist_t *CAFindInterfaceChange()
+{
+ u_arraylist_t *iflist = NULL;
+ char buf[NETLINK_MESSAGE_LENGTH] = { 0 };
+ struct sockaddr_nl sa = { 0 };
+ struct iovec iov = { .iov_base = buf,
+ .iov_len = sizeof (buf) };
+ struct msghdr msg = { .msg_name = (void *)&sa,
+ .msg_namelen = sizeof (sa),
+ .msg_iov = &iov,
+ .msg_iovlen = 1 };
+
+ ssize_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
+
+ for (struct nlmsghdr *nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len))
+ {
+ if (nh != NULL && nh->nlmsg_type != RTM_NEWLINK)
+ {
+ continue;
+ }
+ struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
+
+ if ((!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)))
+ {
+ continue;
+ }
+
+ int ifiIndex = ifi->ifi_index;
+
+ iflist = CAIPGetInterfaceInformation(ifiIndex);
+
+ if (!iflist)
+ {
+ OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+ return NULL;
+ }
+ }
+ return iflist;
+}
+
+CAResult_t CAIPStartNetworkMonitor(CAIPAdapterStateChangeCallback callback,
+ CATransportAdapter_t adapter)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ if (!g_adapterCallbackList)
+ {
+ // Initialize Wifi service.
+ if (WIFI_ERROR_NONE != wifi_initialize())
+ {
+ OIC_LOG(ERROR, TAG, "wifi_initialize failed");
+ }
+
+ // Initialize Connections.
+ connection_error_e ret = connection_create(&connection);
+ if (CONNECTION_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "connection_create failed");
+ return CA_STATUS_FAILED;
+ }
+
+ // Set callback for receiving state changes.
+ ret = connection_set_type_changed_cb(connection, CAIPConnectionStateChangedCb, NULL);
+ if (CONNECTION_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "connection_set_type_changed_cb failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ return CAIPSetNetworkMonitorCallback(callback, adapter);
+}
+
+CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ CAIPUnSetNetworkMonitorCallback(adapter);
+ if (!g_adapterCallbackList)
+ {
+ // Deinitialize Wifi service.
+ if (WIFI_ERROR_NONE != wifi_deinitialize())
+ {
+ OIC_LOG(ERROR, TAG, "wifi_deinitialize failed");
+ }
+
+ // Reset callback for receiving state changes.
+ if (connection)
+ {
+ connection_error_e ret = connection_unset_type_changed_cb(connection);
+ if (CONNECTION_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "connection_unset_type_changed_cb failed");
+ }
+
+ // Deinitialize Wifi service.
+ ret = connection_destroy(connection);
+ if (CONNECTION_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "connection_destroy failed");
+ }
+ connection = NULL;
+ }
+ }
+
+ return CA_STATUS_OK;
+}
+
+/**
+ * Used to send netlink query to kernel and recv response from kernel.
+ *
+ * @param[in] idx desired network interface index, 0 means all interfaces.
+ * @param[out] iflist linked list.
+ *
+ */
+static bool CAIPGetAddrInfo(int idx, u_arraylist_t *iflist)
+{
+ if ((idx < 0) || (iflist == NULL))
+ {
+ return false;