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 "caipinterface.h"
23 #include <sys/types.h>
26 #include <sys/socket.h>
31 #include <sys/ioctl.h>
34 #include "caadapterutils.h"
36 #include "oic_malloc.h"
37 #include "oic_string.h"
39 #define TAG "IP_MONITOR"
40 #define MAX_INTERFACE_INFO_LENGTH (1024)
42 static CAIPConnectionStateChangeCallback g_networkChangeCallback;
44 static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
45 uint32_t addr, int flags);
47 static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
48 char *name, int family, uint32_t addr, int flags);
50 static void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
53 static void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData);
56 int CAGetPollingInterval(int interval)
61 void CAIPSetNetworkMonitorCallback(CAIPConnectionStateChangeCallback callback)
63 g_networkChangeCallback = callback;
66 CAInterface_t *CAFindInterfaceChange()
68 char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
69 struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
71 int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
72 if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
74 OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
78 CAInterface_t *foundNewInterface = NULL;
80 struct ifreq* ifr = ifc.ifc_req;
81 size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
82 size_t ifreqsize = ifc.ifc_len;
84 CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize);
87 OIC_LOG(ERROR, TAG, "OICMalloc failed");
91 memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize);
92 size_t numprevious = caglobals.ip.nm.numIfItems;
94 if (ifreqsize > caglobals.ip.nm.sizeIfItems)
97 CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
100 OIC_LOG(ERROR, TAG, "OICRealloc failed");
104 caglobals.ip.nm.ifItems = items;
105 caglobals.ip.nm.sizeIfItems = ifreqsize;
108 caglobals.ip.nm.numIfItems = 0;
109 for (size_t i = 0; i < interfaces; i++)
111 struct ifreq* item = &ifr[i];
112 char *name = item->ifr_name;
113 struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
114 uint32_t ipv4addr = sa4->sin_addr.s_addr;
116 if (ioctl(s, SIOCGIFFLAGS, item) < 0)
118 OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
121 int16_t flags = item->ifr_flags;
122 if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
126 if (ioctl(s, SIOCGIFINDEX, item) < 0)
128 OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
132 int ifIndex = item->ifr_ifindex;
133 caglobals.ip.nm.ifItems[i].ifIndex = ifIndex; // refill interface list
134 caglobals.ip.nm.numIfItems++;
136 if (foundNewInterface)
138 continue; // continue updating interface list
141 // see if this interface didn't previously exist
143 for (size_t j = 0; j < numprevious; j++)
145 if (ifIndex == previous[j].ifIndex)
153 OIC_LOG_V(INFO, TAG, "Interface found: %s", name);
157 foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags);
161 return foundNewInterface;
164 CAResult_t CAIPStartNetworkMonitor()
166 OIC_LOG(DEBUG, TAG, "IN");
168 // Initialize Wifi service
169 wifi_error_e ret = wifi_initialize();
170 if (WIFI_ERROR_NONE != ret)
172 OIC_LOG(ERROR, TAG, "wifi_initialize failed");
173 return CA_STATUS_FAILED;
176 // Set callback for receiving state changes
177 ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
178 if (WIFI_ERROR_NONE != ret)
180 OIC_LOG(ERROR, TAG, "wifi_set_device_state_changed_cb failed");
181 return CA_STATUS_FAILED;
184 // Set callback for receiving connection state changes
185 ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL);
186 if (WIFI_ERROR_NONE != ret)
188 OIC_LOG(ERROR, TAG, "wifi_set_connection_state_changed_cb failed");
189 return CA_STATUS_FAILED;
192 OIC_LOG(DEBUG, TAG, "OUT");
196 CAResult_t CAIPStopNetworkMonitor()
198 OIC_LOG(DEBUG, TAG, "IN");
200 // Reset callback for receiving state changes
201 wifi_error_e ret = wifi_unset_device_state_changed_cb();
202 if (WIFI_ERROR_NONE != ret)
204 OIC_LOG(ERROR, TAG, "wifi_unset_device_state_changed_cb failed");
207 // Reset callback for receiving connection state changes
208 ret = wifi_unset_connection_state_changed_cb();
209 if (WIFI_ERROR_NONE != ret)
211 OIC_LOG(ERROR, TAG, "wifi_unset_connection_state_changed_cb failed");
214 // Deinitialize Wifi service
215 ret = wifi_deinitialize();
216 if (WIFI_ERROR_NONE != ret)
218 OIC_LOG(ERROR, TAG, "wifi_deinitialize failed");
221 OIC_LOG(DEBUG, TAG, "OUT");
225 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
227 u_arraylist_t *iflist = u_arraylist_create();
230 OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
234 char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
235 struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
237 int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
238 if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
240 OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
241 u_arraylist_destroy(iflist);
245 struct ifreq* ifr = ifc.ifc_req;
246 size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
247 size_t ifreqsize = ifc.ifc_len;
249 if (ifreqsize > caglobals.ip.nm.sizeIfItems)
251 CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
254 OIC_LOG(ERROR, TAG, "OICRealloc failed");
257 caglobals.ip.nm.ifItems = items;
258 caglobals.ip.nm.sizeIfItems = ifreqsize;
261 caglobals.ip.nm.numIfItems = 0;
262 for (size_t i = 0; i < interfaces; i++)
264 struct ifreq* item = &ifr[i];
265 char *name = item->ifr_name;
266 struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
267 uint32_t ipv4addr = sa4->sin_addr.s_addr;
269 if (ioctl(s, SIOCGIFFLAGS, item) < 0)
271 OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
274 int16_t flags = item->ifr_flags;
275 if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
279 if (ioctl(s, SIOCGIFINDEX, item) < 0)
281 OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
285 int ifindex = item->ifr_ifindex;
286 caglobals.ip.nm.ifItems[i].ifIndex = ifindex;
287 caglobals.ip.nm.numIfItems++;
289 if (desiredIndex && (ifindex != desiredIndex))
294 // Add IPv4 interface
295 CAResult_t result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags);
296 if (CA_STATUS_OK != result)
301 // Add IPv6 interface
302 result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags);
303 if (CA_STATUS_OK != result)
311 u_arraylist_destroy(iflist);
315 static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
316 char *name, int family, uint32_t addr, int flags)
318 CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags);
321 return CA_STATUS_FAILED;
323 bool result = u_arraylist_add(iflist, ifitem);
326 OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
328 return CA_STATUS_FAILED;
334 static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
335 uint32_t addr, int flags)
337 CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
340 OIC_LOG(ERROR, TAG, "Malloc failed");
344 OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name);
345 ifitem->index = index;
346 ifitem->family = family;
347 ifitem->ipv4addr = addr;
348 ifitem->flags = flags;
353 void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
356 OIC_LOG(DEBUG, TAG, "IN");
358 if (WIFI_CONNECTION_STATE_ASSOCIATION == state
359 || WIFI_CONNECTION_STATE_CONFIGURATION == state)
361 OIC_LOG(DEBUG, TAG, "Connection is in Association State");
365 if (WIFI_CONNECTION_STATE_CONNECTED == state)
367 g_networkChangeCallback(CA_ADAPTER_IP, CA_INTERFACE_UP);
371 g_networkChangeCallback(CA_ADAPTER_IP, CA_INTERFACE_DOWN);
374 OIC_LOG(DEBUG, TAG, "OUT");
377 void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
379 OIC_LOG(DEBUG, TAG, "IN");
381 if (WIFI_DEVICE_STATE_ACTIVATED == state)
383 OIC_LOG(DEBUG, TAG, "Wifi is in Activated State");
387 CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
388 OIC_LOG(DEBUG, TAG, "Wifi is in Deactivated State");
391 OIC_LOG(DEBUG, TAG, "OUT");