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 // Defining _POSIX_C_SOURCE macro with 200809L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2008 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2008 base specification,
26 // Refer http://pubs.opengroup.org/stage7tc1/
28 // For this specific file, see use of strndup,
29 // Refer http://man7.org/linux/man-pages/man3/strdup.3.html
30 #ifndef _POSIX_C_SOURCE
31 #define _POSIX_C_SOURCE 200809L
34 // Defining _BSD_SOURCE or _DEFAULT_SOURCE causes header files to expose
35 // definitions that may otherwise be skipped. Skipping can cause implicit
36 // declaration warnings and/or bugs and subtle problems in code execution.
37 // For glibc information on feature test macros,
38 // Refer http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
40 // This file requires #define use due to IFF_LOOPBACK
41 #define _DEFAULT_SOURCE
45 #include "caethernetinterface.h"
47 #include <sys/types.h>
49 #include <sys/socket.h>
55 #include "caadapterutils.h"
58 #include "oic_malloc.h"
59 #include "oic_string.h"
61 #define ETHERNET_MONITOR_TAG "ETHERNET_MONITOR"
64 #define ETHERNET_INF_PREFIX "en"
66 #define ETHERNET_INF_PREFIX "eth"
70 * @var nwConnectivityStatus
71 * @brief Maintains network status.
73 static CANetworkStatus_t nwConnectivityStatus;
76 * @var g_ethernetNetInfoMutex
77 * @brief Mutex for synchronizing access to cached interface and IP address information.
79 static ca_mutex g_ethernetNetInfoMutex = NULL;
82 * @var g_ethernetInterfaceName
83 * @brief Maintains interface name.
85 static char *g_ethernetInterfaceName = NULL;
88 * @var g_ethernetIPAddress
89 * @brief Maintains interface IP address.
91 static char *g_ethernetIPAddress = NULL;
94 * @var g_ethernetSubnetMask
95 * @brief Maintains interface subnetmask.
97 static char *g_ethernetSubnetMask = NULL;
101 * @brief ThreadPool for storing ca_thread_pool_t handle passed from adapter
103 static ca_thread_pool_t g_threadPool = NULL;
106 * @var g_stopNetworkMonitor
107 * @brief Flag to control the Network Monitor Thread
109 static bool g_stopNetworkMonitor = false;
112 * @var g_networkChangeCb
113 * @brief Maintains network connection state change callback.
115 static CAEthernetConnectionStateChangeCallback g_networkChangeCb = NULL;
118 * @fn CAEthernetGetInterfaceInformation
119 * @brief This methods gets local interface name and IP address information.
121 static void CAEthernetGetInterfaceInformation(const char *interfacePrefix,
122 char **interfaceName, char **ipAddress,char **subnetMask);
124 static void CANetworkMonitorThread(void *threadData);
126 CAResult_t CAEthernetInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
128 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
130 g_threadPool = threadPool;
132 if (!g_ethernetNetInfoMutex)
134 g_ethernetNetInfoMutex = ca_mutex_new();
137 ca_mutex_lock(g_ethernetNetInfoMutex);
138 CAEthernetGetInterfaceInformation(ETHERNET_INF_PREFIX,&g_ethernetInterfaceName, &g_ethernetIPAddress,
139 &g_ethernetSubnetMask);
140 ca_mutex_unlock(g_ethernetNetInfoMutex);
142 nwConnectivityStatus = (g_ethernetIPAddress) ? CA_INTERFACE_UP : CA_INTERFACE_DOWN;
144 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
148 void CAEthernetTerminateNetworkMonitor(void)
150 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
154 if (g_ethernetInterfaceName)
156 OICFree(g_ethernetInterfaceName);
157 g_ethernetInterfaceName = NULL;
160 if (g_ethernetIPAddress)
162 OICFree(g_ethernetIPAddress);
163 g_ethernetIPAddress = NULL;
166 if (g_ethernetSubnetMask)
168 OICFree(g_ethernetSubnetMask);
169 g_ethernetSubnetMask = NULL;
172 if (g_ethernetNetInfoMutex)
174 ca_mutex_free(g_ethernetNetInfoMutex);
175 g_ethernetNetInfoMutex = NULL;
178 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
181 CAResult_t CAEthernetStartNetworkMonitor(void)
183 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
185 g_stopNetworkMonitor = false;
187 if (g_stopNetworkMonitor)
189 OIC_LOG(ERROR, ETHERNET_MONITOR_TAG, "Stop network monitor requested");
190 return CA_STATUS_FAILED;
193 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPool, (void *) CANetworkMonitorThread,
196 OIC_LOG(ERROR, ETHERNET_MONITOR_TAG, "[ThreadPool] thread_pool_add_task failed!");
197 return CA_STATUS_FAILED;
200 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
204 CAResult_t CAEthernetStopNetworkMonitor(void)
206 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
208 if (g_stopNetworkMonitor)
210 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "CAEthernetStopNetworkMonitor, already stopped!");
214 g_stopNetworkMonitor = true;
216 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
220 CAResult_t CAEthernetGetInterfaceInfo(char **interfaceName, char **ipAddress)
222 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
224 VERIFY_NON_NULL(interfaceName, ETHERNET_MONITOR_TAG, "interface name");
225 VERIFY_NON_NULL(ipAddress, ETHERNET_MONITOR_TAG, "ip address");
227 // Get the interface and ipaddress information from cache
228 ca_mutex_lock(g_ethernetNetInfoMutex);
229 if (g_ethernetInterfaceName == NULL || g_ethernetIPAddress == NULL)
231 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "Network not enabled");
233 ca_mutex_unlock(g_ethernetNetInfoMutex);
234 return CA_ADAPTER_NOT_ENABLED;
237 *interfaceName = (g_ethernetInterfaceName) ? strndup(g_ethernetInterfaceName,
238 strlen(g_ethernetInterfaceName)) : NULL;
239 *ipAddress = (g_ethernetIPAddress) ? OICStrdup((const char *)g_ethernetIPAddress)
242 ca_mutex_unlock(g_ethernetNetInfoMutex);
244 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
248 CAResult_t CAEthernetGetInterfaceSubnetMask(char **subnetMask)
250 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
252 VERIFY_NON_NULL(subnetMask, ETHERNET_MONITOR_TAG, "subnet mask");
254 ca_mutex_lock(g_ethernetNetInfoMutex);
255 if (NULL == g_ethernetSubnetMask)
257 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "There is no subnet mask information!");
259 ca_mutex_unlock(g_ethernetNetInfoMutex);
260 return CA_STATUS_FAILED;
263 *subnetMask = (g_ethernetSubnetMask) ?
264 strndup(g_ethernetSubnetMask, strlen(g_ethernetSubnetMask))
266 ca_mutex_unlock(g_ethernetNetInfoMutex);
268 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
272 bool CAEthernetIsConnected(void)
274 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
276 if (CA_INTERFACE_DOWN == nwConnectivityStatus) {
277 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
282 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
287 void CAEthernetSetConnectionStateChangeCallback
288 (CAEthernetConnectionStateChangeCallback callback)
290 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
291 g_networkChangeCb = callback;
293 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");
296 void CAEthernetGetInterfaceInformation(const char *interfaceNamePrefix,char **interfaceName,
297 char **ipAddress, char **subnetMask)
299 if (!interfaceName || !ipAddress || !subnetMask)
301 OIC_LOG(ERROR, ETHERNET_MONITOR_TAG, "Invalid input: interface/ipaddress/subnet mask holder is NULL!");
305 struct ifaddrs *ifp = NULL;
306 if (-1 == getifaddrs(&ifp))
308 OIC_LOG_V(ERROR, ETHERNET_MONITOR_TAG, "Failed to get interface list!, Error code: %s",
313 struct ifaddrs *ifa = NULL;
314 for (ifa = ifp; ifa; ifa = ifa->ifa_next)
316 char interfaceAddress[CA_IPADDR_SIZE];
317 char interfaceSubnetMask[CA_IPADDR_SIZE] = {0};
318 socklen_t len = sizeof(struct sockaddr_in);
320 if (NULL == ifa->ifa_addr)
325 int type = ifa->ifa_addr->sa_family;
326 if (ifa->ifa_flags & IFF_LOOPBACK
327 || !((ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_RUNNING)))
337 int matchNameLen = strlen(interfaceNamePrefix);
338 if (!strncasecmp(ifa->ifa_name, interfaceNamePrefix, matchNameLen))
340 // get the interface ip address
341 if (0 != getnameinfo(ifa->ifa_addr, len, interfaceAddress,
342 sizeof(interfaceAddress), NULL, 0, NI_NUMERICHOST))
344 OIC_LOG_V(ERROR, ETHERNET_MONITOR_TAG, "Failed to get IPAddress, Error code: %s",
349 // get the interface subnet mask
350 if (0 != getnameinfo(ifa->ifa_netmask, len, interfaceSubnetMask,
351 sizeof(interfaceSubnetMask), NULL, 0, NI_NUMERICHOST))
353 OIC_LOG_V(ERROR, ETHERNET_MONITOR_TAG, "Failed to get subnet mask, Error code: %s",
358 // set interface name
359 *interfaceName = strndup(ifa->ifa_name, strlen(ifa->ifa_name));
361 // set local ip address
362 *ipAddress = strndup(interfaceAddress, strlen(interfaceAddress));
365 *subnetMask = strndup(interfaceSubnetMask, strlen(interfaceSubnetMask));
373 void CANetworkMonitorThread(void *threadData)
375 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "IN");
377 while (!g_stopNetworkMonitor)
379 // Get network information
380 char *interfaceName = NULL;
381 char *ipAddress = NULL;
382 char *subnetMask = NULL;
383 CAEthernetGetInterfaceInformation(ETHERNET_INF_PREFIX,&interfaceName, &ipAddress, &subnetMask);
385 // check current network status
386 CANetworkStatus_t currNetworkStatus;
387 currNetworkStatus = (ipAddress) ? CA_INTERFACE_UP : CA_INTERFACE_DOWN;
389 // if network status is changed
390 if (currNetworkStatus != nwConnectivityStatus)
392 // set current network information
393 ca_mutex_lock(g_ethernetNetInfoMutex);
395 nwConnectivityStatus = currNetworkStatus;
397 OICFree(g_ethernetInterfaceName);
398 OICFree(g_ethernetIPAddress);
399 OICFree(g_ethernetSubnetMask);
400 g_ethernetInterfaceName =
401 (interfaceName) ? strndup(interfaceName, strlen(interfaceName)) : NULL;
402 g_ethernetIPAddress = (ipAddress) ? strndup(ipAddress, strlen(ipAddress)) : NULL;
403 g_ethernetSubnetMask = (subnetMask) ? strndup(subnetMask, strlen(subnetMask)) : NULL;
405 ca_mutex_unlock(g_ethernetNetInfoMutex);
407 if (g_networkChangeCb)
409 g_networkChangeCb(g_ethernetIPAddress, nwConnectivityStatus);
412 OICFree(interfaceName);
417 OIC_LOG(DEBUG, ETHERNET_MONITOR_TAG, "OUT");