1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
21 #include "caethernetinterface.h"
23 #include <sys/types.h>
26 #include <sys/socket.h>
31 #include "caadapterutils.h"
34 #include "oic_malloc.h"
36 #define ETHERNET_MONITOR_TAG "ETHERNET_MONITOR"
39 * @var nwConnectivityStatus
40 * @brief Maintains network status.
42 static CANetworkStatus_t nwConnectivityStatus;
45 * @var gEthernetNetInfoMutex
46 * @brief Mutex for synchronizing access to cached interface and IP address information.
48 static u_mutex gEthernetNetInfoMutex = NULL;
51 * @var gEthernetInterfaceName
52 * @brief Maintains interface name.
54 static char *gEthernetInterfaceName = NULL;
57 * @var gEthernetIPAddress
58 * @brief Maintains interface IP address.
60 static char *gEthernetIPAddress = NULL;
63 * @var gEthernetSubnetMask
64 * @brief Maintains interface subnetmask.
66 static char *gEthernetSubnetMask = NULL;
70 * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
72 static u_thread_pool_t gThreadPool = NULL;
75 * @var gStopNetworkMonitor
76 * @brief Flag to control the Network Monitor Thread
78 static bool gStopNetworkMonitor = false;
81 * @var gNetworkChangeCb
82 * @brief Maintains network connection state change callback.
84 static CAEthernetConnectionStateChangeCallback gNetworkChangeCb = NULL;
87 * @fn CAEthernetGetInterfaceInformation
88 * @brief This methods gets local interface name and IP address information.
90 static void CAEthernetGetInterfaceInformation(char **interfaceName, char **ipAddress,
93 static void CANetworkMonitorThread(void *threadData);
95 CAResult_t CAEthernetInitializeNetworkMonitor(const u_thread_pool_t threadPool)
97 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
99 gThreadPool = threadPool;
101 if (!gEthernetNetInfoMutex)
103 gEthernetNetInfoMutex = u_mutex_new();
106 u_mutex_lock(gEthernetNetInfoMutex);
107 CAEthernetGetInterfaceInformation(&gEthernetInterfaceName, &gEthernetIPAddress,
108 &gEthernetSubnetMask);
109 u_mutex_unlock(gEthernetNetInfoMutex);
111 nwConnectivityStatus = (gEthernetIPAddress) ? CA_INTERFACE_UP : CA_INTERFACE_DOWN;
113 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
117 void CAEthernetTerminateNetworkMonitor(void)
119 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
123 if (gEthernetInterfaceName)
125 OICFree(gEthernetInterfaceName);
126 gEthernetInterfaceName = NULL;
129 if (gEthernetIPAddress)
131 OICFree(gEthernetIPAddress);
132 gEthernetIPAddress = NULL;
135 if (gEthernetNetInfoMutex)
137 u_mutex_free(gEthernetNetInfoMutex);
138 gEthernetNetInfoMutex = NULL;
141 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
144 CAResult_t CAEthernetStartNetworkMonitor(void)
146 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
148 u_mutex_lock(gEthernetNetInfoMutex);
149 gStopNetworkMonitor = false;
150 u_mutex_unlock(gEthernetNetInfoMutex);
152 if (gStopNetworkMonitor)
154 OIC_LOG_V(ERROR, ETHERNET_MONITOR_TAG, "Stop network monitor requested");
155 return CA_STATUS_FAILED;
158 if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, (void *) CANetworkMonitorThread,
161 OIC_LOG(ERROR, ETHERNET_MONITOR_TAG, "[ThreadPool] thread_pool_add_task failed!");
162 return CA_STATUS_FAILED;
165 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
169 CAResult_t CAEthernetStopNetworkMonitor(void)
171 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
173 if (gStopNetworkMonitor)
175 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "CAEthernetStopNetworkMonitor, already stopped!");
179 u_mutex_lock(gEthernetNetInfoMutex);
180 gStopNetworkMonitor = true;
181 u_mutex_unlock(gEthernetNetInfoMutex);
183 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
187 CAResult_t CAEthernetGetInterfaceInfo(char **interfaceName, char **ipAddress)
189 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
191 VERIFY_NON_NULL(interfaceName, ETHERNET_MONITOR_TAG, "interface name");
192 VERIFY_NON_NULL(ipAddress, ETHERNET_MONITOR_TAG, "ip address");
194 // Get the interface and ipaddress information from cache
195 u_mutex_lock(gEthernetNetInfoMutex);
196 if (gEthernetInterfaceName == NULL || gEthernetIPAddress == NULL)
198 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "Network not enabled");
199 return CA_ADAPTER_NOT_ENABLED;
202 *interfaceName = (gEthernetInterfaceName) ? strndup(gEthernetInterfaceName,
203 strlen(gEthernetInterfaceName)) : NULL;
204 *ipAddress = (gEthernetIPAddress) ? strndup(gEthernetIPAddress, strlen(gEthernetIPAddress))
207 u_mutex_unlock(gEthernetNetInfoMutex);
209 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
213 CAResult_t CAEthernetGetInterfaceSubnetMask(char **subnetMask)
215 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
217 VERIFY_NON_NULL(subnetMask, ETHERNET_MONITOR_TAG, "subnet mask");
219 u_mutex_lock(gEthernetNetInfoMutex);
220 if (NULL == gEthernetSubnetMask)
222 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "There is no subnet mask information!");
223 return CA_STATUS_FAILED;
226 *subnetMask = (gEthernetSubnetMask) ? strndup(gEthernetSubnetMask, strlen(gEthernetSubnetMask))
228 u_mutex_unlock(gEthernetNetInfoMutex);
230 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
234 bool CAEthernetIsConnected(void)
236 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
238 if (CA_INTERFACE_DOWN == nwConnectivityStatus)
244 void CAEthernetSetConnectionStateChangeCallback(CAEthernetConnectionStateChangeCallback callback)
246 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
247 gNetworkChangeCb = callback;
250 void CAEthernetGetInterfaceInformation(char **interfaceName, char **ipAddress, char **subnetMask)
252 struct ifaddrs *ifa = NULL;
253 struct ifaddrs *ifp = NULL;
254 const char *matchName = "eth";
256 if (!interfaceName || !ipAddress || !subnetMask)
258 OIC_LOG(ERROR, ETHERNET_MONITOR_TAG, "Invalid input: interface/ipaddress holder is NULL!");
262 if (-1 == getifaddrs(&ifp))
264 OIC_LOG_V(ERROR, ETHERNET_MONITOR_TAG, "Failed to get interface list!, Error code: %s",
269 for (ifa = ifp; ifa; ifa = ifa->ifa_next)
271 char interfaceAddress[CA_IPADDR_SIZE];
272 char interfaceSubnetMask[CA_IPADDR_SIZE] = {0};
273 socklen_t len = sizeof(struct sockaddr_in);
275 if (NULL == ifa->ifa_addr)
280 int type = ifa->ifa_addr->sa_family;
281 if (ifa->ifa_flags & IFF_LOOPBACK
282 || !((ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_RUNNING)))
292 if (!strncasecmp(ifa->ifa_name, matchName, strlen(matchName)))
294 // get the interface ip address
295 if (0 != getnameinfo(ifa->ifa_addr, len, interfaceAddress,
296 sizeof(interfaceAddress), NULL, 0, NI_NUMERICHOST))
298 OIC_LOG_V(ERROR, ETHERNET_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
303 // get the interface subnet mask
304 if (0 != getnameinfo(ifa->ifa_netmask, len, interfaceSubnetMask,
305 sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST))
307 OIC_LOG_V(ERROR, ETHERNET_MONITOR_TAG, "Failed to get subnet mask, Error code: %s",
312 // set interface name
313 *interfaceName = strndup(ifa->ifa_name, strlen(ifa->ifa_name));
315 // set local ip address
316 *ipAddress = strndup(interfaceAddress, strlen(interfaceAddress));
319 *subnetMask = strndup(interfaceSubnetMask, strlen(interfaceSubnetMask));
327 void CANetworkMonitorThread(void *threadData)
329 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "IN");
331 while (!gStopNetworkMonitor)
333 // Get network information
334 CANetworkStatus_t currNetworkStatus;
335 char *interfaceName = NULL;
336 char *ipAddress = NULL;
337 char *subnetMask = NULL;
338 CAEthernetGetInterfaceInformation(&interfaceName, &ipAddress, &subnetMask);
340 // check current network status
341 currNetworkStatus = (ipAddress) ? CA_INTERFACE_UP : CA_INTERFACE_DOWN;
343 // if network status is changed
344 if (currNetworkStatus != nwConnectivityStatus)
346 // set current network information
347 u_mutex_lock(gEthernetNetInfoMutex);
349 nwConnectivityStatus = currNetworkStatus;
351 OICFree(gEthernetInterfaceName);
352 OICFree(gEthernetIPAddress);
353 OICFree(gEthernetSubnetMask);
354 gEthernetInterfaceName = (interfaceName) ? strndup(interfaceName, strlen(interfaceName)) : NULL;
355 gEthernetIPAddress = (ipAddress) ? strndup(ipAddress, strlen(ipAddress)) : NULL;
356 gEthernetSubnetMask = (subnetMask) ? strndup(subnetMask, strlen(subnetMask)) : NULL;
358 u_mutex_unlock(gEthernetNetInfoMutex);
360 if (gNetworkChangeCb)
362 gNetworkChangeCb(gEthernetIPAddress, nwConnectivityStatus);
365 OICFree(interfaceName);
370 OIC_LOG_V(DEBUG, ETHERNET_MONITOR_TAG, "OUT");