dac21f937e6bb4b94e2ebff3197e711a3cca9f58
[olsrd.git] / src / win32 / ifnet.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include <winsock2.h>
43
44 #include "olsr.h"
45 #include "olsr_cfg.h"
46 #include "interfaces.h"
47 #include "parser.h"
48 #include "defs.h"
49 #include "os_net.h"
50 #include "olsr_timer.h"
51 #include "olsr_socket.h"
52 #include "olsr_time.h"
53 #include "lq_packet.h"
54 #include "net_olsr.h"
55 #include "common/string.h"
56 #include "olsr_logging.h"
57 #include "mid_set.h"
58 #include "hna_set.h"
59 #include "olsr_logging.h"
60 #include "link_set.h"
61
62 #include <iphlpapi.h>
63 #include <iprtrmib.h>
64
65 #include <arpa/inet.h>
66
67 struct MibIpInterfaceRow {
68   USHORT Family;
69   ULONG64 InterfaceLuid;
70   ULONG InterfaceIndex;
71   ULONG MaxReassemblySize;
72   ULONG64 InterfaceIdentifier;
73   ULONG MinRouterAdvertisementInterval;
74   ULONG MaxRouterAdvertisementInterval;
75   BOOLEAN AdvertisingEnabled;
76   BOOLEAN ForwardingEnabled;
77   BOOLEAN WeakHostSend;
78   BOOLEAN WeakHostReceive;
79   BOOLEAN UseAutomaticMetric;
80   BOOLEAN UseNeighborUnreachabilityDetection;
81   BOOLEAN ManagedAddressConfigurationSupported;
82   BOOLEAN OtherStatefulConfigurationSupported;
83   BOOLEAN AdvertiseDefaultRoute;
84   INT RouterDiscoveryBehavior;
85   ULONG DadTransmits;
86   ULONG BaseReachableTime;
87   ULONG RetransmitTime;
88   ULONG PathMtuDiscoveryTimeout;
89   INT LinkLocalAddressBehavior;
90   ULONG LinkLocalAddressTimeout;
91   ULONG ZoneIndices[16];
92   ULONG SitePrefixLength;
93   ULONG Metric;
94   ULONG NlMtu;
95   BOOLEAN Connected;
96   BOOLEAN SupportsWakeUpPatterns;
97   BOOLEAN SupportsNeighborDiscovery;
98   BOOLEAN SupportsRouterDiscovery;
99   ULONG ReachableTime;
100   BYTE TransmitOffload;
101   BYTE ReceiveOffload;
102   BOOLEAN DisableDefaultRoutes;
103 };
104
105 typedef DWORD(__stdcall * GETIPINTERFACEENTRY)
106   (struct MibIpInterfaceRow * Row);
107
108 typedef DWORD(__stdcall * GETADAPTERSADDRESSES)
109   (ULONG Family, DWORD Flags, PVOID Reserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen);
110
111 struct InterfaceInfo {
112   unsigned int Index;
113   int Mtu;
114   int Metric;
115   unsigned int Addr;
116   unsigned int Mask;
117   unsigned int Broad;
118   char Guid[39];
119 };
120
121 void WinSockPError(char *);
122 char *win32_strerror(unsigned int ErrNo);
123 int GetIntInfo(struct InterfaceInfo *Info, char *Name);
124
125 #define MAX_INTERFACES 100
126
127 static void
128 MiniIndexToIntName(char *String, int MiniIndex)
129 {
130   const char *HexDigits = "0123456789abcdef";
131
132   String[0] = 'i';
133   String[1] = 'f';
134
135   String[2] = HexDigits[(MiniIndex >> 4) & 15];
136   String[3] = HexDigits[MiniIndex & 15];
137
138   String[4] = 0;
139 }
140
141 static int
142 IntNameToMiniIndex(int *MiniIndex, char *String)
143 {
144   const char *HexDigits = "0123456789abcdef";
145   int i, k;
146   char ch;
147
148   if ((String[0] != 'i' && String[0] != 'I') || (String[1] != 'f' && String[1] != 'F'))
149     return -1;
150
151   *MiniIndex = 0;
152
153   for (i = 2; i < 4; i++) {
154     ch = String[i];
155
156     if (ch >= 'A' && ch <= 'F')
157       ch += 32;
158
159     for (k = 0; k < 16 && ch != HexDigits[k]; k++);
160
161     if (k == 16)
162       return -1;
163
164     *MiniIndex = (*MiniIndex << 4) | k;
165   }
166
167   return 0;
168 }
169
170 static int
171 FriendlyNameToMiniIndex(int *MiniIndex, char *String)
172 {
173   unsigned long BuffLen;
174   unsigned long Res;
175   IP_ADAPTER_ADDRESSES AdAddr[MAX_INTERFACES], *WalkerAddr;
176   char FriendlyName[MAX_INTERFACE_NAME_LEN];
177   HMODULE h;
178   GETADAPTERSADDRESSES pfGetAdaptersAddresses;
179
180   h = LoadLibrary("iphlpapi.dll");
181
182   if (h == NULL) {
183     OLSR_WARN(LOG_NETWORKING, "LoadLibrary() = %08lx", GetLastError());
184     return -1;
185   }
186
187   pfGetAdaptersAddresses = (GETADAPTERSADDRESSES) GetProcAddress(h, "GetAdaptersAddresses");
188
189   if (pfGetAdaptersAddresses == NULL) {
190     OLSR_WARN(LOG_NETWORKING, "Unable to use adapter friendly name (GetProcAddress() = %08lx)\n", GetLastError());
191     return -1;
192   }
193
194   BuffLen = sizeof(AdAddr);
195
196   Res = pfGetAdaptersAddresses(AF_INET, 0, NULL, AdAddr, &BuffLen);
197
198   if (Res != NO_ERROR) {
199     OLSR_WARN(LOG_NETWORKING, "GetAdaptersAddresses() = %08lx", GetLastError());
200     return -1;
201   }
202
203   for (WalkerAddr = AdAddr; WalkerAddr != NULL; WalkerAddr = WalkerAddr->Next) {
204     OLSR_DEBUG(LOG_NETWORKING, "Index = %08x - ", (int)WalkerAddr->IfIndex);
205
206     wcstombs(FriendlyName, WalkerAddr->FriendlyName, MAX_INTERFACE_NAME_LEN);
207
208     OLSR_DEBUG(LOG_NETWORKING, "Friendly name = %s\n", FriendlyName);
209
210     if (strncmp(FriendlyName, String, MAX_INTERFACE_NAME_LEN) == 0)
211       break;
212   }
213
214   if (WalkerAddr == NULL) {
215     OLSR_WARN(LOG_NETWORKING, "No such interface: %s!\n", String);
216     return -1;
217   }
218
219   *MiniIndex = WalkerAddr->IfIndex & 255;
220
221   return 0;
222 }
223
224 int
225 GetIntInfo(struct InterfaceInfo *Info, char *Name)
226 {
227   int MiniIndex;
228   unsigned char Buff[MAX_INTERFACES * sizeof(MIB_IFROW) + 4];
229   MIB_IFTABLE *IfTable;
230   unsigned long BuffLen;
231   unsigned long Res;
232   int TabIdx;
233   IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
234   HMODULE Lib;
235   struct MibIpInterfaceRow Row;
236   GETIPINTERFACEENTRY InterfaceEntry;
237
238   if (olsr_cnf->ip_version == AF_INET6) {
239     OLSR_WARN(LOG_NETWORKING, "IPv6 not supported by GetIntInfo()!\n");
240     return -1;
241   }
242
243   if ((Name[0] != 'i' && Name[0] != 'I') || (Name[1] != 'f' && Name[1] != 'F')) {
244     if (FriendlyNameToMiniIndex(&MiniIndex, Name) < 0) {
245       OLSR_WARN(LOG_NETWORKING, "No such interface: %s!\n", Name);
246       return -1;
247     }
248   }
249
250   else {
251     if (IntNameToMiniIndex(&MiniIndex, Name) < 0) {
252       OLSR_WARN(LOG_NETWORKING, "No such interface: %s!\n", Name);
253       return -1;
254     }
255   }
256
257   IfTable = (MIB_IFTABLE *) Buff;
258
259   BuffLen = sizeof(Buff);
260
261   Res = GetIfTable(IfTable, &BuffLen, FALSE);
262
263   if (Res != NO_ERROR) {
264     OLSR_WARN(LOG_NETWORKING, "GetIfTable() = %08lx, %s", Res, win32_strerror(Res));
265     return -1;
266   }
267
268   for (TabIdx = 0; TabIdx < (int)IfTable->dwNumEntries; TabIdx++) {
269     OLSR_DEBUG(LOG_NETWORKING, "Index = %08x\n", (int)IfTable->table[TabIdx].dwIndex);
270
271     if ((int)(IfTable->table[TabIdx].dwIndex & 255) == MiniIndex)
272       break;
273   }
274
275   if (TabIdx == (int)IfTable->dwNumEntries) {
276     OLSR_WARN(LOG_NETWORKING, "No such interface: %s!\n", Name);
277     return -1;
278   }
279
280   Info->Index = IfTable->table[TabIdx].dwIndex;
281   Info->Mtu = (int)IfTable->table[TabIdx].dwMtu;
282
283   Info->Mtu -= olsr_cnf->ip_version == AF_INET6 ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
284
285   Lib = LoadLibrary("iphlpapi.dll");
286
287   if (Lib == NULL) {
288     OLSR_WARN(LOG_NETWORKING, "Cannot load iphlpapi.dll: %08lx\n", GetLastError());
289     return -1;
290   }
291
292   InterfaceEntry = (GETIPINTERFACEENTRY) GetProcAddress(Lib, "GetIpInterfaceEntry");
293
294   if (InterfaceEntry == NULL) {
295     OLSR_DEBUG(LOG_NETWORKING, "Not running on Vista - setting interface metric to 0.\n");
296
297     Info->Metric = 0;
298   }
299
300   else {
301     memset(&Row, 0, sizeof(struct MibIpInterfaceRow));
302
303     Row.Family = AF_INET;
304     Row.InterfaceIndex = Info->Index;
305
306     Res = InterfaceEntry(&Row);
307
308     if (Res != NO_ERROR) {
309       OLSR_WARN(LOG_NETWORKING, "GetIpInterfaceEntry() = %08lx", Res);
310       FreeLibrary(Lib);
311       return -1;
312     }
313
314     Info->Metric = Row.Metric;
315
316     OLSR_DEBUG(LOG_NETWORKING, "Running on Vista - interface metric is %d.\n", Info->Metric);
317   }
318
319   FreeLibrary(Lib);
320
321   BuffLen = sizeof(AdInfo);
322
323   Res = GetAdaptersInfo(AdInfo, &BuffLen);
324
325   if (Res != NO_ERROR) {
326     OLSR_WARN(LOG_NETWORKING, "GetAdaptersInfo() = %08lx, %s", GetLastError(), win32_strerror(Res));
327     return -1;
328   }
329
330   for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next) {
331     OLSR_DEBUG(LOG_NETWORKING, "Index = %08x\n", (int)Walker->Index);
332
333     if ((int)(Walker->Index & 255) == MiniIndex)
334       break;
335   }
336
337   if (Walker == NULL) {
338     OLSR_WARN(LOG_NETWORKING, "No such interface: %s!\n", Name);
339     return -1;
340   }
341
342   inet_pton(AF_INET, Walker->IpAddressList.IpAddress.String, &Info->Addr);
343   inet_pton(AF_INET, Walker->IpAddressList.IpMask.String, &Info->Mask);
344
345   Info->Broad = Info->Addr | ~Info->Mask;
346
347   strscpy(Info->Guid, Walker->AdapterName, sizeof(Info->Guid));
348
349   if ((IfTable->table[TabIdx].dwOperStatus != MIB_IF_OPER_STATUS_CONNECTED &&
350        IfTable->table[TabIdx].dwOperStatus != MIB_IF_OPER_STATUS_OPERATIONAL) || Info->Addr == 0) {
351     OLSR_WARN(LOG_NETWORKING, "Interface %s not up!\n", Name);
352     return -1;
353   }
354
355   return 0;
356 }
357
358 #if !defined OID_802_11_CONFIGURATION
359 #define OID_802_11_CONFIGURATION 0x0d010211
360 #endif
361
362 #if !defined IOCTL_NDIS_QUERY_GLOBAL_STATS
363 #define IOCTL_NDIS_QUERY_GLOBAL_STATS 0x00170002
364 #endif
365
366 void
367 ListInterfaces(void)
368 {
369   IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
370   unsigned long AdInfoLen;
371   char IntName[5];
372   unsigned long Res;
373
374   if (olsr_cnf->ip_version == AF_INET6) {
375     OLSR_WARN(LOG_NETWORKING, "IPv6 not supported by ListInterfaces()!\n");
376     return;
377   }
378
379   AdInfoLen = sizeof(AdInfo);
380
381   Res = GetAdaptersInfo(AdInfo, &AdInfoLen);
382
383   if (Res == ERROR_NO_DATA) {
384     OLSR_INFO(LOG_NETWORKING, "No interfaces detected.\n");
385     return;
386   }
387
388   if (Res != NO_ERROR) {
389     OLSR_WARN(LOG_NETWORKING, "GetAdaptersInfo() = %08lx, %s", Res, win32_strerror(Res));
390     return;
391   }
392   // TODO: change to new logging API ?
393   for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next) {
394     OLSR_DEBUG(LOG_NETWORKING, "Index = %08x\n", (int)Walker->Index);
395
396     MiniIndexToIntName(IntName, Walker->Index);
397 #if 0
398     printf("%s: ", IntName);
399
400     IsWlan = IsWireless(IntName);
401
402     if (IsWlan < 0)
403       printf("?");
404
405     else if (IsWlan == 0)
406       printf("-");
407
408     else
409       printf("+");
410
411     for (Walker2 = &Walker->IpAddressList; Walker2 != NULL; Walker2 = Walker2->Next)
412       printf(" %s", Walker2->IpAddress.String);
413
414     printf("\n");
415 #endif
416   }
417 }
418
419 int
420 chk_if_changed(struct olsr_if_config *olsr_if)
421 {
422   struct ipaddr_str buf;
423   struct interface *Int;
424   struct InterfaceInfo Info;
425   int Res;
426   union olsr_ip_addr OldVal, NewVal;
427   struct sockaddr_in *AddrIn;
428
429   if (olsr_cnf->ip_version == AF_INET6) {
430     OLSR_WARN(LOG_NETWORKING, "IPv6 not supported by chk_if_changed()!\n");
431     return 0;
432   }
433
434   Int = olsr_if->interf;
435
436   if (GetIntInfo(&Info, olsr_if->name) < 0) {
437     remove_interface(olsr_if->interf);
438     return 1;
439   }
440
441   Res = 0;
442
443   if (Int->int_mtu != Info.Mtu) {
444     OLSR_INFO(LOG_NETWORKING, "\tMTU change: %d -> %d.\n", (int)Int->int_mtu, Info.Mtu);
445
446     Int->int_mtu = Info.Mtu;
447
448     net_remove_buffer(Int);
449     net_add_buffer(Int);
450
451     Res = 1;
452   }
453
454   OldVal.v4 = Int->int_src.v4.sin_addr;
455   NewVal.v4.s_addr = Info.Addr;
456
457   OLSR_INFO(LOG_NETWORKING, "\tAddress: %s\n", olsr_ip_to_string(&buf, &NewVal));
458
459   if (NewVal.v4.s_addr != OldVal.v4.s_addr) {
460     OLSR_DEBUG(LOG_NETWORKING, "\tAddress change.\n");
461     OLSR_DEBUG(LOG_NETWORKING, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
462     OLSR_DEBUG(LOG_NETWORKING, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
463
464     Int->ip_addr.v4 = NewVal.v4;
465
466     AddrIn = &Int->int_src.v4;
467
468     AddrIn->sin_family = AF_INET;
469     AddrIn->sin_port = 0;
470     AddrIn->sin_addr = NewVal.v4;
471
472     Res = 1;
473   }
474
475   else
476     OLSR_DEBUG(LOG_NETWORKING, "\tNo address change.\n");
477
478   OldVal.v4 = Int->int_multicast.v4.sin_addr;
479   NewVal.v4.s_addr = Info.Broad;
480
481   OLSR_INFO(LOG_NETWORKING, "\tBroadcast address: %s\n", olsr_ip_to_string(&buf, &NewVal));
482
483   if (NewVal.v4.s_addr != OldVal.v4.s_addr) {
484     OLSR_DEBUG(LOG_NETWORKING, "\tBroadcast address change.\n");
485     OLSR_DEBUG(LOG_NETWORKING, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
486     OLSR_DEBUG(LOG_NETWORKING, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
487
488     AddrIn = &Int->int_multicast.v4;
489
490     AddrIn->sin_family = AF_INET;
491     AddrIn->sin_port = 0;
492     AddrIn->sin_addr = NewVal.v4;
493
494     Res = 1;
495   }
496
497   else
498     OLSR_DEBUG(LOG_NETWORKING, "\tNo broadcast address change.\n");
499
500   if (Res != 0)
501     run_ifchg_cbs(Int, IFCHG_IF_UPDATE);
502
503   return Res;
504 }
505
506 int
507 os_init_interface(struct interface *ifp, struct olsr_if_config *IntConf)
508 {
509   struct ipaddr_str buf;
510   struct InterfaceInfo if_info;
511   struct sockaddr_in *if_addr;
512   size_t name_size;
513
514   if (olsr_cnf->ip_version == AF_INET6) {
515     OLSR_ERROR(LOG_NETWORKING, "IPv6 not supported by win32!\n");
516     olsr_exit(1);
517   }
518
519   if (GetIntInfo(&if_info, IntConf->name) < 0)
520     return 0;
521
522 #if 0
523   ifp->gen_properties = NULL;
524 #endif
525   if_addr = &ifp->int_src.v4;
526
527   if_addr->sin_family = AF_INET;
528   if_addr->sin_port = 0;
529   if_addr->sin_addr.s_addr = if_info.Addr;
530
531   if_addr = &ifp->int_multicast.v4;
532
533   if_addr->sin_family = AF_INET;
534   if_addr->sin_port = 0;
535   if_addr->sin_addr.s_addr = if_info.Broad;
536
537   if (IntConf->cnf->ipv4_broadcast.v4.s_addr != 0)
538     if_addr->sin_addr = IntConf->cnf->ipv4_broadcast.v4;
539
540   ifp->int_mtu = if_info.Mtu;
541
542   name_size = strlen(IntConf->name) + 1;
543   ifp->int_name = olsr_malloc(name_size, "Interface 2");
544   strscpy(ifp->int_name, IntConf->name, name_size);
545
546   ifp->olsr_seqnum = rand() & 0xffff;
547
548   OLSR_INFO(LOG_NETWORKING, "\tInterface %s set up for use with index %d\n\n", IntConf->name, ifp->if_index);
549
550   OLSR_INFO(LOG_NETWORKING, "\tMTU: %d\n", ifp->int_mtu);
551   OLSR_INFO(LOG_NETWORKING, "\tAddress: %s\n", ip4_to_string(&buf, ifp->int_src.v4.sin_addr));
552   OLSR_INFO(LOG_NETWORKING, "\tBroadcast address: %s\n", ip4_to_string(&buf, ifp->int_multicast.v4.sin_addr));
553
554   ifp->ip_addr.v4 = ifp->int_src.v4.sin_addr;
555
556   ifp->if_index = if_info.Index;
557
558   OLSR_INFO(LOG_NETWORKING, "\tKernel index: %08x\n", ifp->if_index);
559   return 0;
560 }
561
562 void
563 os_cleanup_interface(struct interface *ifp  __attribute__ ((unused))) {
564 }
565
566 /*
567  * Local Variables:
568  * c-basic-offset: 2
569  * indent-tabs-mode: nil
570  * End:
571  */