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>
24 #include <sys/socket.h>
30 #include <arpa/inet.h>
33 #include "caadapterutils.h"
35 #include "oic_malloc.h"
36 #include "oic_string.h"
37 #include "org_iotivity_ca_CaIpInterface.h"
39 #define TAG "IP_MONITOR"
41 static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
42 uint32_t addr, int flags);
44 static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
45 const char *name, int family, uint32_t addr, int flags);
47 CAResult_t CAIPJniInit();
49 #define MAX_INTERFACE_INFO_LENGTH 1024 // allows 32 interfaces from SIOCGIFCONF
51 CAResult_t CAIPStartNetworkMonitor()
56 CAResult_t CAIPStopNetworkMonitor()
61 int CAGetPollingInterval(int interval)
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 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
166 u_arraylist_t *iflist = u_arraylist_create();
169 OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
173 char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
174 struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
176 int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
177 if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
179 OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
180 u_arraylist_destroy(iflist);
184 struct ifreq* ifr = ifc.ifc_req;
185 size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
186 size_t ifreqsize = ifc.ifc_len;
188 if (ifreqsize > caglobals.ip.nm.sizeIfItems)
190 CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
193 OIC_LOG(ERROR, TAG, "OICRealloc failed");
196 caglobals.ip.nm.ifItems = items;
197 caglobals.ip.nm.sizeIfItems = ifreqsize;
200 caglobals.ip.nm.numIfItems = 0;
201 for (size_t i = 0; i < interfaces; i++)
203 CAResult_t result = CA_STATUS_OK;
204 struct ifreq* item = &ifr[i];
205 char *name = item->ifr_name;
206 struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
207 uint32_t ipv4addr = sa4->sin_addr.s_addr;
209 if (ioctl(s, SIOCGIFFLAGS, item) < 0)
211 OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
214 int16_t flags = item->ifr_flags;
215 if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
219 if (ioctl(s, SIOCGIFINDEX, item) < 0)
221 OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
225 int ifindex = item->ifr_ifindex;
226 caglobals.ip.nm.ifItems[i].ifIndex = ifindex;
227 caglobals.ip.nm.numIfItems++;
229 if (desiredIndex && (ifindex != desiredIndex))
234 // Add IPv4 interface
235 result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags);
236 if (CA_STATUS_OK != result)
241 // Add IPv6 interface
242 result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags);
243 if (CA_STATUS_OK != result)
251 u_arraylist_destroy(iflist);
255 static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
256 const char *name, int family, uint32_t addr, int flags)
258 CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags);
261 return CA_STATUS_FAILED;
263 bool result = u_arraylist_add(iflist, ifitem);
266 OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
268 return CA_STATUS_FAILED;
274 static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
275 uint32_t addr, int flags)
277 CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
280 OIC_LOG(ERROR, TAG, "Malloc failed");
284 OICStrcpy(ifitem->name, sizeof (ifitem->name), name);
285 ifitem->index = index;
286 ifitem->family = family;
287 ifitem->ipv4addr = addr;
288 ifitem->flags = flags;
293 CAResult_t CAIPJniInit()
295 OIC_LOG(DEBUG, TAG, "CAIPJniInit_IN");
297 JavaVM *jvm = CANativeJNIGetJavaVM();
300 OIC_LOG(ERROR, TAG, "Could not get JavaVM pointer");
301 return CA_STATUS_FAILED;
304 jobject context = CANativeJNIGetContext();
307 OIC_LOG(ERROR, TAG, "unable to get application context");
308 return CA_STATUS_FAILED;
312 if ((*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
314 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
315 return CA_STATUS_FAILED;
318 jclass cls_Context = (*env)->FindClass(env, "android/content/Context");
321 OIC_LOG(ERROR, TAG, "Could not get context object class");
322 return CA_STATUS_FAILED;
325 jmethodID mid_getApplicationContext = (*env)->GetMethodID(env, cls_Context,
326 "getApplicationContext",
327 "()Landroid/content/Context;");
328 if (!mid_getApplicationContext)
330 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
331 return CA_STATUS_FAILED;
334 jobject jApplicationContext = (*env)->CallObjectMethod(env, context,
335 mid_getApplicationContext);
336 if (!jApplicationContext)
338 OIC_LOG(ERROR, TAG, "Could not get application context");
339 return CA_STATUS_FAILED;
342 jclass cls_CaIpInterface = (*env)->FindClass(env, "org/iotivity/ca/CaIpInterface");
343 if (!cls_CaIpInterface)
345 OIC_LOG(ERROR, TAG, "Could not get CaIpInterface class");
346 return CA_STATUS_FAILED;
349 jmethodID mid_CaIpInterface_ctor = (*env)->GetMethodID(env, cls_CaIpInterface, "<init>",
350 "(Landroid/content/Context;)V");
351 if (!mid_CaIpInterface_ctor)
353 OIC_LOG(ERROR, TAG, "Could not get CaIpInterface constructor method");
354 return CA_STATUS_FAILED;
357 (*env)->NewObject(env, cls_CaIpInterface, mid_CaIpInterface_ctor, jApplicationContext);
358 OIC_LOG(DEBUG, TAG, "Create CaIpInterface instance, success");
360 OIC_LOG(DEBUG, TAG, "CAIPJniInit_OUT");
364 JNIEXPORT void JNICALL
365 Java_org_iotivity_ca_CaIpInterface_caIpStateEnabled(JNIEnv *env, jclass class)
369 OIC_LOG(DEBUG, TAG, "caIpStateEnabled");
374 JNIEXPORT void JNICALL
375 Java_org_iotivity_ca_CaIpInterface_caIpStateDisabled(JNIEnv *env, jclass class)
379 OIC_LOG(DEBUG, TAG, "caIpStateDisabled");
381 u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
384 OIC_LOG_V(ERROR, TAG, "get interface info failed");
387 u_arraylist_destroy(iflist);