Merge branch 'tizen' into tizen_5.5
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / windows / caipnwmonitor.c
1 /* *****************************************************************
2 *
3 * Copyright 2016 Intel Corporation
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 <string.h>
25 #include <errno.h>
26 #include <winsock2.h>
27 #include <iphlpapi.h>
28 #include "platform_features.h"
29 #include <iptypes.h>
30 #include <stdbool.h>
31 #include "caadapterutils.h"
32 #include "logger.h"
33 #include "oic_malloc.h"
34 #include "oic_string.h"
35 #include "caipnwmonitor.h"
36
37 #define TAG "IP_MONITOR"
38
39 /**
40  * @todo Implement network interface monitoring in case the IP changes.
41  * Not critical for win32 bring-up.
42  */
43 CAResult_t CAIPStartNetworkMonitor(CAIPAdapterStateChangeCallback callback,
44                                    CATransportAdapter_t adapter)
45 {
46     return CA_STATUS_OK;
47 }
48
49 /**
50  * @todo Implement network interface monitoring in case the IP changes.
51  * Not critical for win32 bring-up.
52  */
53 CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter)
54
55 {
56     return CA_STATUS_OK;
57 }
58
59 /**
60  * @todo Implement network interface monitoring.
61  * Not used in win32, but caipserver currently requires this function
62  * be defined. not critical.
63  */
64 u_arraylist_t *CAFindInterfaceChange()
65 {
66     u_arraylist_t *iflist = NULL;
67     return iflist;
68 }
69
70 /**
71  * @todo Implement network interface monitoring.
72  * Not critical for win32 bring-up.
73  */
74 CAResult_t CAIPSetNetworkMonitorCallback(CAIPAdapterStateChangeCallback callback,
75                                          CATransportAdapter_t adapter)
76 {
77     return CA_NOT_SUPPORTED;
78 }
79
80 bool IsValidAdapter(PIP_ADAPTER_ADDRESSES pAdapterAddr, int desiredIndex, uint16_t family)
81 {
82     bool valid = true;
83
84     // If desiredIndex is non-zero, then only retrieve adapter corresponding to desiredIndex.
85     // If desiredIndex is zero, then retrieve all adapters.
86     if (desiredIndex && (pAdapterAddr->IfIndex != desiredIndex))
87     {
88         OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i not interesting.", pAdapterAddr->IfIndex);
89         valid = false;
90     }
91
92     if (pAdapterAddr->IfType & IF_TYPE_SOFTWARE_LOOPBACK)
93     {
94         OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i is loopback.", pAdapterAddr->IfIndex);
95         valid = false;
96     }
97
98     // If the adapter must support the requested family
99     if ((family == AF_INET6) && ((pAdapterAddr->Flags & IP_ADAPTER_IPV6_ENABLED) == 0))
100     {
101         OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i does not support IPv6", pAdapterAddr->IfIndex);
102         valid = false;
103     }
104     else if ((family == AF_INET) && ((pAdapterAddr->Flags & IP_ADAPTER_IPV4_ENABLED) == 0))
105     {
106         OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i does not support IPv4", pAdapterAddr->IfIndex);
107         valid = false;
108     }
109
110     if ((pAdapterAddr->OperStatus & IfOperStatusUp) == 0)
111     {
112         OIC_LOG_V(DEBUG, TAG, "\t\tInterface %i is not operational.", pAdapterAddr->IfIndex);
113         valid = false;
114     }
115     return valid;
116
117 }
118
119
120 bool AddCAInterface(u_arraylist_t *iflist, const char * name, uint32_t index, uint16_t family)
121 {
122     bool bSucceeded = false;
123     CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(*ifitem));
124     if (ifitem)
125     {
126         OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name);
127         ifitem->index = index;
128         ifitem->family = family;
129         ifitem->flags |= IFF_UP;// IsValidAddress() will have filtered out non-operational addresses already.
130
131         if (u_arraylist_add(iflist, ifitem))
132         {
133             bSucceeded = true;
134         }
135         else
136         {
137             OIC_LOG(ERROR, TAG, "u_arraylist_add failed");
138             OICFree(ifitem);
139         }
140     }
141     else
142     {
143         OIC_LOG(ERROR, TAG, "Allocating memory for a CAInterface_t failed");
144     }
145     return bSucceeded;
146 }
147
148 bool AddInterfaces(PIP_ADAPTER_ADDRESSES pAdapterAddr, u_arraylist_t *iflist, int desiredIndex)
149 {
150     bool bSucceeded = false;
151     for (PIP_ADAPTER_ADDRESSES pCurAdapterAddr = pAdapterAddr;
152          pCurAdapterAddr != NULL; pCurAdapterAddr = pCurAdapterAddr->Next)
153     {
154         OIC_LOG_V(DEBUG, TAG, "\tInterface Index: %u", pCurAdapterAddr->IfIndex);
155         OIC_LOG_V(DEBUG, TAG, "\tInterface  name: %s", pCurAdapterAddr->AdapterName);
156
157         // Prefer IPv6 over IPv4.
158         if (pCurAdapterAddr->Flags & IP_ADAPTER_IPV6_ENABLED)
159         {
160             // Do not add loopback, duplicate, or non-operational adapters
161             if (IsValidAdapter(pCurAdapterAddr, desiredIndex, AF_INET6))
162             {
163                 if (AddCAInterface(iflist, pCurAdapterAddr->AdapterName, pCurAdapterAddr->IfIndex, AF_INET6))
164                 {
165                     OIC_LOG_V(DEBUG, TAG, "\t\tAdded IPv6 interface %i", pCurAdapterAddr->IfIndex);
166                     bSucceeded = true;
167                 }
168                 else
169                 {
170                     OIC_LOG_V(ERROR, TAG, "\tAdding IPv6 interface %i failed", pCurAdapterAddr->IfIndex);
171                     break;
172                 }
173             }
174             else
175             {
176                 OIC_LOG_V(DEBUG, TAG, "\t\tIPv6 interface %i not valid, skipping...", pCurAdapterAddr->IfIndex);
177             }
178         }
179
180         if (pCurAdapterAddr->Flags & IP_ADAPTER_IPV4_ENABLED)
181         {
182             // Do not add loopback, duplicate, or non-operational adapters
183             if (IsValidAdapter(pCurAdapterAddr, desiredIndex, AF_INET))
184             {
185                 if (AddCAInterface(iflist, pCurAdapterAddr->AdapterName, pCurAdapterAddr->IfIndex, AF_INET))
186                 {
187                     OIC_LOG_V(DEBUG, TAG, "\t\tAdded IPv4 interface %i", pCurAdapterAddr->IfIndex);
188                     bSucceeded = true;
189                 }
190                 else
191                 {
192                     OIC_LOG_V(ERROR, TAG, "\tAdding IPv4 interface %i failed", pCurAdapterAddr->IfIndex);
193                     break;
194                 }
195             }
196             else
197             {
198                 OIC_LOG_V(DEBUG, TAG, "\t\tIPv6 interface %i not valid, skipping...", pCurAdapterAddr->IfIndex);
199             }
200
201         }
202     }
203     return bSucceeded;
204 }
205
206 PIP_ADAPTER_ADDRESSES GetAdapters()
207 {
208     ULONG ulOutBufLen = sizeof(IP_ADAPTER_ADDRESSES);
209     PIP_ADAPTER_ADDRESSES pAdapterAddr = (IP_ADAPTER_ADDRESSES *) OICMalloc(ulOutBufLen);
210     if (pAdapterAddr != NULL)
211     {
212         ULONG flags = 0;
213         ULONG ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapterAddr, &ulOutBufLen);
214         if (ERROR_BUFFER_OVERFLOW == ret)
215         {
216             // Redo with updated length
217             OICFree(pAdapterAddr);
218             pAdapterAddr = (PIP_ADAPTER_ADDRESSES) OICMalloc(ulOutBufLen);
219             if (pAdapterAddr != NULL) {
220                 ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapterAddr, &ulOutBufLen);
221                 if (NO_ERROR != ret)
222                 {
223                     OIC_LOG(ERROR, TAG, "GetAdaptersAddresses() failed");
224                     OICFree(pAdapterAddr);
225                     pAdapterAddr = NULL;
226                 }
227                 else
228                 {
229                     // Succeeded getting adapters
230                 }
231             }
232             else
233             {
234                 OIC_LOG(ERROR, TAG, "Second time allocating memory for GetAdaptersAddresses() failed");
235             }
236         }
237         else
238         {
239             OIC_LOG(ERROR, TAG, "Expected GetAdaptersAddresses() to fail on first try, but it didn't.");
240         }
241     }
242     else
243     {
244         OIC_LOG(ERROR, TAG, "First time allocating memory for GetAdaptersAddresses() failed");
245     }
246     return pAdapterAddr;
247 }
248
249 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
250 {
251     u_arraylist_t *iflist = u_arraylist_create();
252     if (iflist)
253     {
254         PIP_ADAPTER_ADDRESSES pAdapterAddr = NULL;
255         pAdapterAddr = GetAdapters();
256         if (pAdapterAddr)
257         {
258             // Cycle through adapters
259             // Add valid adapters to the interface list.
260             bool ret = AddInterfaces(pAdapterAddr, iflist, desiredIndex);
261             if (false == ret)
262             {
263                 OIC_LOG(ERROR, TAG, "AddInterfaces() failed");
264                 u_arraylist_destroy(iflist);
265                 iflist = NULL;
266             }
267
268             // Finished with Adapter List
269             OICFree(pAdapterAddr);
270         }
271         else
272         {
273             OIC_LOG(ERROR, TAG, "Enumerating Adapters failed");
274             u_arraylist_destroy(iflist);
275             iflist = NULL;
276         }
277     }
278     else
279     {
280         OIC_LOG(ERROR, TAG, "Failed to create iflist");
281     }
282     return iflist;
283 }