Merge branch 'windows-port'
[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         else if (pCurAdapterAddr->Flags & IP_ADAPTER_IPV4_ENABLED)
186         {
187             // Do not add loopback, duplicate, or non-operational adapters
188             if (IsValidAdapter(pCurAdapterAddr, desiredIndex, AF_INET))
189             {
190                 if (AddCAInterface(iflist, pCurAdapterAddr->AdapterName, pCurAdapterAddr->IfIndex, AF_INET))
191                 {
192                     OIC_LOG_V(DEBUG, TAG, "\t\tAdded IPv4 interface %i", pCurAdapterAddr->IfIndex);
193                     bSucceeded = true;
194                 }
195                 else
196                 {
197                     OIC_LOG_V(ERROR, TAG, "\tAdding IPv4 interface %i failed", pCurAdapterAddr->IfIndex);
198                     break;
199                 }
200             }
201             else
202             {
203                 OIC_LOG_V(DEBUG, TAG, "\t\tIPv6 interface %i not valid, skipping...", pCurAdapterAddr->IfIndex);
204             }
205
206         }
207     }
208     return bSucceeded;
209 }
210
211 PIP_ADAPTER_ADDRESSES GetAdapters()
212 {
213     ULONG ulOutBufLen = sizeof(IP_ADAPTER_ADDRESSES);
214     PIP_ADAPTER_ADDRESSES pAdapterAddr = (IP_ADAPTER_ADDRESSES *) OICMalloc(ulOutBufLen);
215     if (pAdapterAddr != NULL)
216     {
217         ULONG flags = 0;
218         ULONG ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapterAddr, &ulOutBufLen);
219         if (ERROR_BUFFER_OVERFLOW == ret)
220         {
221             // Redo with updated length
222             OICFree(pAdapterAddr);
223             pAdapterAddr = (PIP_ADAPTER_ADDRESSES) OICMalloc(ulOutBufLen);
224             if (pAdapterAddr != NULL) {
225                 ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapterAddr, &ulOutBufLen);
226                 if (NO_ERROR != ret)
227                 {
228                     OIC_LOG(ERROR, TAG, "GetAdaptersAddresses() failed");
229                     OICFree(pAdapterAddr);
230                     pAdapterAddr = NULL;
231                 }
232                 else
233                 {
234                     // Succeeded getting adapters
235                 }
236             }
237             else
238             {
239                 OIC_LOG(ERROR, TAG, "Second time allocating memory for GetAdaptersAddresses() failed");
240             }
241         }
242         else
243         {
244             OIC_LOG(ERROR, TAG, "Expected GetAdaptersAddresses() to fail on first try, but it didn't.");
245         }
246     }
247     else
248     {
249         OIC_LOG(ERROR, TAG, "First time allocating memory for GetAdaptersAddresses() failed");
250     }
251     return pAdapterAddr;
252 }
253
254 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
255 {
256     u_arraylist_t *iflist = u_arraylist_create();
257     if (iflist)
258     {
259         PIP_ADAPTER_ADDRESSES pAdapterAddr = NULL;
260         pAdapterAddr = GetAdapters();
261         if (pAdapterAddr)
262         {
263             // Cycle through adapters
264             // Add valid adapters to the interface list.
265             bool ret = AddInterfaces(pAdapterAddr, iflist, desiredIndex);
266             if (false == ret)
267             {
268                 OIC_LOG(ERROR, TAG, "AddInterfaces() failed");
269                 u_arraylist_destroy(iflist);
270                 iflist = NULL;
271             }
272
273             // Finished with Adapter List
274             OICFree(pAdapterAddr);
275         }
276         else
277         {
278             OIC_LOG(ERROR, TAG, "Enumerating Adapters failed");
279             u_arraylist_destroy(iflist);
280             iflist = NULL;
281         }
282     }
283     else
284     {
285         OIC_LOG(ERROR, TAG, "Failed to create iflist");
286     }
287     return iflist;
288 }