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