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