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>
25 #include <sys/socket.h>
31 #include <arpa/inet.h>
34 #include "caadapterutils.h"
36 #include "oic_malloc.h"
37 #include "oic_string.h"
38 #include "org_iotivity_ca_CaIpInterface.h"
40 #define TAG "IP_MONITOR"
42 static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
43 uint32_t addr, int flags);
45 static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
46 const char *name, int family, uint32_t addr, int flags);
48 CAResult_t CAIPJniInit();
50 #define MAX_INTERFACE_INFO_LENGTH 1024 // allows 32 interfaces from SIOCGIFCONF
52 CAResult_t CAIPStartNetworkMonitor()
57 CAResult_t CAIPStopNetworkMonitor()
62 int CAGetPollingInterval(int interval)
67 CAInterface_t *CAFindInterfaceChange()
69 char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
70 struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
72 int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
73 if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
75 OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
79 CAInterface_t *foundNewInterface = NULL;
81 struct ifreq* ifr = ifc.ifc_req;
82 size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
83 size_t ifreqsize = ifc.ifc_len;
85 CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize);
88 OIC_LOG(ERROR, TAG, "OICMalloc failed");
92 memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize);
93 size_t numprevious = caglobals.ip.nm.numIfItems;
95 if (ifreqsize > caglobals.ip.nm.sizeIfItems)
98 CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
101 OIC_LOG(ERROR, TAG, "OICRealloc failed");
105 caglobals.ip.nm.ifItems = items;
106 caglobals.ip.nm.sizeIfItems = ifreqsize;
109 caglobals.ip.nm.numIfItems = 0;
110 for (size_t i = 0; i < interfaces; i++)
112 struct ifreq* item = &ifr[i];
113 char *name = item->ifr_name;
114 struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
115 uint32_t ipv4addr = sa4->sin_addr.s_addr;
117 if (ioctl(s, SIOCGIFFLAGS, item) < 0)
119 OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
122 int16_t flags = item->ifr_flags;
123 if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
127 if (ioctl(s, SIOCGIFINDEX, item) < 0)
129 OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
133 int ifIndex = item->ifr_ifindex;
134 caglobals.ip.nm.ifItems[i].ifIndex = ifIndex; // refill interface list
135 caglobals.ip.nm.numIfItems++;
137 if (foundNewInterface)
139 continue; // continue updating interface list
142 // see if this interface didn't previously exist
144 for (size_t j = 0; j < numprevious; j++)
146 if (ifIndex == previous[j].ifIndex)
154 OIC_LOG_V(INFO, TAG, "Interface found: %s", name);
158 foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags);
162 return foundNewInterface;
165 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
167 u_arraylist_t *iflist = u_arraylist_create();
170 OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
174 char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
175 struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
177 int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
178 if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
180 OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
181 u_arraylist_destroy(iflist);
185 struct ifreq* ifr = ifc.ifc_req;
186 size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
187 size_t ifreqsize = ifc.ifc_len;
189 if (ifreqsize > caglobals.ip.nm.sizeIfItems)
191 CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
194 OIC_LOG(ERROR, TAG, "OICRealloc failed");
197 caglobals.ip.nm.ifItems = items;
198 caglobals.ip.nm.sizeIfItems = ifreqsize;
201 caglobals.ip.nm.numIfItems = 0;
202 for (size_t i = 0; i < interfaces; i++)
204 CAResult_t result = CA_STATUS_OK;
205 struct ifreq* item = &ifr[i];
206 char *name = item->ifr_name;
207 struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
208 uint32_t ipv4addr = sa4->sin_addr.s_addr;
210 if (ioctl(s, SIOCGIFFLAGS, item) < 0)
212 OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
215 int16_t flags = item->ifr_flags;
216 if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
220 if (ioctl(s, SIOCGIFINDEX, item) < 0)
222 OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
226 int ifindex = item->ifr_ifindex;
227 caglobals.ip.nm.ifItems[i].ifIndex = ifindex;
228 caglobals.ip.nm.numIfItems++;
230 if (desiredIndex && (ifindex != desiredIndex))
235 // Add IPv4 interface
236 result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags);
237 if (CA_STATUS_OK != result)
242 // Add IPv6 interface
243 result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags);
244 if (CA_STATUS_OK != result)
252 u_arraylist_destroy(iflist);
256 static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
257 const char *name, int family, uint32_t addr, int flags)
259 CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags);
262 return CA_STATUS_FAILED;
264 bool result = u_arraylist_add(iflist, ifitem);
267 OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
269 return CA_STATUS_FAILED;
275 static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
276 uint32_t addr, int flags)
278 CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
281 OIC_LOG(ERROR, TAG, "Malloc failed");
285 OICStrcpy(ifitem->name, sizeof (ifitem->name), name);
286 ifitem->index = index;
287 ifitem->family = family;
288 ifitem->ipv4addr = addr;
289 ifitem->flags = flags;
294 CAResult_t CAIPJniInit()
296 OIC_LOG(DEBUG, TAG, "CAIPJniInit_IN");
298 JavaVM *jvm = CANativeJNIGetJavaVM();
301 OIC_LOG(ERROR, TAG, "Could not get JavaVM pointer");
302 return CA_STATUS_FAILED;
305 jobject context = CANativeJNIGetContext();
308 OIC_LOG(ERROR, TAG, "unable to get application context");
309 return CA_STATUS_FAILED;
313 if ((*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
315 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
316 return CA_STATUS_FAILED;
319 jclass cls_Context = (*env)->FindClass(env, "android/content/Context");
322 OIC_LOG(ERROR, TAG, "Could not get context object class");
323 return CA_STATUS_FAILED;
326 jmethodID mid_getApplicationContext = (*env)->GetMethodID(env, cls_Context,
327 "getApplicationContext",
328 "()Landroid/content/Context;");
329 if (!mid_getApplicationContext)
331 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
332 return CA_STATUS_FAILED;
335 jobject jApplicationContext = (*env)->CallObjectMethod(env, context,
336 mid_getApplicationContext);
337 if (!jApplicationContext)
339 OIC_LOG(ERROR, TAG, "Could not get application context");
340 return CA_STATUS_FAILED;
343 jclass cls_CaIpInterface = (*env)->FindClass(env, "org/iotivity/ca/CaIpInterface");
344 if (!cls_CaIpInterface)
346 OIC_LOG(ERROR, TAG, "Could not get CaIpInterface class");
347 return CA_STATUS_FAILED;
350 jmethodID mid_CaIpInterface_ctor = (*env)->GetMethodID(env, cls_CaIpInterface, "<init>",
351 "(Landroid/content/Context;)V");
352 if (!mid_CaIpInterface_ctor)
354 OIC_LOG(ERROR, TAG, "Could not get CaIpInterface constructor method");
355 return CA_STATUS_FAILED;
358 (*env)->NewObject(env, cls_CaIpInterface, mid_CaIpInterface_ctor, jApplicationContext);
359 OIC_LOG(DEBUG, TAG, "Create CaIpInterface instance, success");
361 OIC_LOG(DEBUG, TAG, "CAIPJniInit_OUT");
365 JNIEXPORT void JNICALL
366 Java_org_iotivity_ca_CaIpInterface_caIpStateEnabled(JNIEnv *env, jclass class)
370 OIC_LOG(DEBUG, TAG, "caIpStateEnabled");
375 JNIEXPORT void JNICALL
376 Java_org_iotivity_ca_CaIpInterface_caIpStateDisabled(JNIEnv *env, jclass class)
380 OIC_LOG(DEBUG, TAG, "caIpStateDisabled");
382 CAIPGetInterfaceInformation(0);