[CA] Patch to make Tizen IP work on 0.9.2 branch for RC3 tag
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / tizen / caipnwmonitor.c
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
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
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 ******************************************************************/
20
21 #include "caipinterface.h"
22
23 #include <sys/types.h>
24 #include <ifaddrs.h>
25 #include <net/if.h>
26 #include <sys/socket.h>
27 #include <netdb.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <sys/ioctl.h>
32 #include <wifi.h>
33
34 #include "caadapterutils.h"
35 #include "logger.h"
36 #include "oic_malloc.h"
37 #include "oic_string.h"
38
39 #define TAG "IP_MONITOR"
40 #define MAX_INTERFACE_INFO_LENGTH (1024)
41
42 static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
43                                          uint32_t addr, int flags);
44
45 static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
46                                      char *name, int family, uint32_t addr, int flags);
47
48 static void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
49                                            void *userData);
50
51 static void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData);
52
53 int CAGetPollingInterval(int interval)
54 {
55         return interval;
56 }
57
58 CAInterface_t *CAFindInterfaceChange()
59 {
60         return NULL;
61 }
62
63 CAResult_t CAIPInitializeNetworkMonitor()
64 {
65     OIC_LOG(DEBUG, TAG, "IN");
66
67      // Initialize Wifi service
68     wifi_error_e ret = wifi_initialize();
69     if (WIFI_ERROR_NONE != ret)
70     {
71         OIC_LOG(ERROR, TAG, "wifi_initialize failed");
72         return CA_STATUS_FAILED;
73     }
74
75     // Set callback for receiving state changes
76     ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
77     if (WIFI_ERROR_NONE != ret)
78     {
79         OIC_LOG(ERROR, TAG, "wifi_set_device_state_changed_cb failed");
80         return CA_STATUS_FAILED;
81     }
82
83     // Set callback for receiving connection state changes
84     ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL);
85     if (WIFI_ERROR_NONE != ret)
86     {
87         OIC_LOG(ERROR, TAG, "wifi_set_connection_state_changed_cb failed");
88         return CA_STATUS_FAILED;
89     }
90
91     OIC_LOG(DEBUG, TAG, "OUT");
92     return CA_STATUS_OK;
93 }
94
95 CAResult_t CAIPTerminateNetworkMonitor()
96 {
97     OIC_LOG(DEBUG, TAG, "IN");
98
99      // Reset callback for receiving state changes
100     wifi_error_e ret = wifi_unset_device_state_changed_cb();
101     if (WIFI_ERROR_NONE != ret)
102     {
103         OIC_LOG(ERROR, TAG, "wifi_unset_device_state_changed_cb failed");
104     }
105
106     // Reset callback for receiving connection state changes
107     ret = wifi_unset_connection_state_changed_cb();
108     if (WIFI_ERROR_NONE != ret)
109     {
110         OIC_LOG(ERROR, TAG, "wifi_unset_connection_state_changed_cb failed");
111     }
112
113     // Deinitialize Wifi service
114     ret = wifi_deinitialize();
115     if (WIFI_ERROR_NONE != ret)
116     {
117         OIC_LOG(ERROR, TAG, "wifi_deinitialize failed");
118     }
119
120     OIC_LOG(DEBUG, TAG, "OUT");
121     return CA_STATUS_OK;
122 }
123
124 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
125 {
126     u_arraylist_t *iflist = u_arraylist_create();
127     if (!iflist)
128     {
129         OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
130         return NULL;
131     }
132
133     char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
134     struct ifconf ifc;
135     ifc.ifc_len = MAX_INTERFACE_INFO_LENGTH;
136     ifc.ifc_buf = buf;
137
138     int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
139     if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
140     {
141         OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
142         u_arraylist_destroy(iflist);
143         return NULL;
144     }
145
146     struct ifreq* ifr = ifc.ifc_req;
147     int32_t interfaces = ifc.ifc_len / sizeof (struct ifreq);
148
149     if (interfaces > caglobals.ip.nm.numifitems)
150     {
151         int ifreqsiz = interfaces * sizeof (struct ifreq);
152         caglobals.ip.nm.numifitems = interfaces;
153         caglobals.ip.nm.ifitems = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifitems, ifreqsiz);
154     }
155
156     for (int i = 0; i < interfaces; i++)
157     {
158         CAResult_t result = CA_STATUS_OK;
159         struct ifreq* item = &ifr[i];
160         char *name = item->ifr_name;
161         struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
162         uint32_t ipv4addr = sa4->sin_addr.s_addr;
163
164         if (ioctl(s, SIOCGIFFLAGS, item) < 0)
165         {
166             OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
167             continue;
168         }
169         int16_t flags = item->ifr_flags;
170         if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
171         {
172             continue;
173         }
174         if (ioctl(s, SIOCGIFINDEX, item) < 0)
175         {
176             OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
177             continue;
178         }
179         int ifindex = item->ifr_ifindex;
180         if (desiredIndex && (ifindex != desiredIndex))
181         {
182             continue;
183         }
184         caglobals.ip.nm.ifitems[i].ifindex = ifindex;
185
186         // Add IPv4 interface
187         result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags);
188         if (CA_STATUS_OK != result)
189         {
190             goto exit;
191         }
192
193         // Add IPv6 interface
194         result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags);
195         if (CA_STATUS_OK != result)
196         {
197             goto exit;
198         }
199     }
200     return iflist;
201
202 exit:
203     u_arraylist_destroy(iflist);
204     return NULL;
205 }
206
207 static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
208                             char *name, int family, uint32_t addr, int flags)
209 {
210     CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags);
211     if (!ifitem)
212     {
213         return CA_STATUS_FAILED;
214     }
215     CAResult_t result = u_arraylist_add(iflist, ifitem);
216     if (CA_STATUS_OK != result)
217     {
218         OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
219         OICFree(ifitem);
220         return CA_STATUS_FAILED;
221     }
222
223     return CA_STATUS_OK;
224 }
225
226 static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
227                                          uint32_t addr, int flags)
228 {
229     CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
230     if (!ifitem)
231     {
232         OIC_LOG(ERROR, TAG, "Malloc failed");
233         return NULL;
234     }
235
236     OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name);
237     ifitem->index = index;
238     ifitem->family = family;
239     ifitem->ipv4addr = addr;
240     ifitem->flags = flags;
241
242     return ifitem;
243 }
244
245 void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
246                                     void *userData)
247 {
248     OIC_LOG(DEBUG, TAG, "IN");
249
250     if (WIFI_CONNECTION_STATE_ASSOCIATION == state
251         || WIFI_CONNECTION_STATE_CONFIGURATION == state)
252     {
253         OIC_LOG(DEBUG, TAG, "Connection is in Association State");
254         return;
255     }
256
257     // If Wifi is connected, then get the latest IP from the WIFI Interface
258     if (WIFI_CONNECTION_STATE_CONNECTED == state)
259     {
260         CAWakeUpForChange();
261     }
262     else
263     {
264         // TODO : Remove Ip intercase case
265     }
266
267     OIC_LOG(DEBUG, TAG, "OUT");
268 }
269
270 void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
271 {
272     OIC_LOG(DEBUG, TAG, "IN");
273
274     if (WIFI_DEVICE_STATE_ACTIVATED == state)
275     {
276         OIC_LOG(DEBUG, TAG, "Wifi is in Activated State");
277     }
278     else
279     {
280         CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
281         OIC_LOG(DEBUG, TAG, "Wifi is in Deactivated State");
282     }
283
284     OIC_LOG(DEBUG, TAG, "OUT");
285 }