a4e2060e9cb007df0e07bc880c90dac3de98d75c
[olsrd.git] / src / win32 / ifnet.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon (olsrd)
4  * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
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 #ifdef _WIN32
43
44 #include <stdlib.h>
45 #include <winsock2.h>
46 #include "interfaces.h"
47 #include "olsr.h"
48 #include "parser.h"
49 #include "defs.h"
50 #include "net_os.h"
51 #include "ifnet.h"
52 #include "generate_msg.h"
53 #include "scheduler.h"
54 #include "mantissa.h"
55 #include "lq_packet.h"
56 #include "net_olsr.h"
57 #include "olsr_random.h"
58
59 #include <iphlpapi.h>
60 #include <iprtrmib.h>
61
62 #include <arpa/inet.h>
63
64 #define BUFSPACE  (127*1024)    /* max. input buffer size to request */
65
66 struct MibIpInterfaceRow {
67   USHORT Family;
68   ULONG64 InterfaceLuid;
69   ULONG InterfaceIndex;
70   ULONG MaxReassemblySize;
71   ULONG64 InterfaceIdentifier;
72   ULONG MinRouterAdvertisementInterval;
73   ULONG MaxRouterAdvertisementInterval;
74   BOOLEAN AdvertisingEnabled;
75   BOOLEAN ForwardingEnabled;
76   BOOLEAN WeakHostSend;
77   BOOLEAN WeakHostReceive;
78   BOOLEAN UseAutomaticMetric;
79   BOOLEAN UseNeighborUnreachabilityDetection;
80   BOOLEAN ManagedAddressConfigurationSupported;
81   BOOLEAN OtherStatefulConfigurationSupported;
82   BOOLEAN AdvertiseDefaultRoute;
83   INT RouterDiscoveryBehavior;
84   ULONG DadTransmits;
85   ULONG BaseReachableTime;
86   ULONG RetransmitTime;
87   ULONG PathMtuDiscoveryTimeout;
88   INT LinkLocalAddressBehavior;
89   ULONG LinkLocalAddressTimeout;
90   ULONG ZoneIndices[16];
91   ULONG SitePrefixLength;
92   ULONG Metric;
93   ULONG NlMtu;
94   BOOLEAN Connected;
95   BOOLEAN SupportsWakeUpPatterns;
96   BOOLEAN SupportsNeighborDiscovery;
97   BOOLEAN SupportsRouterDiscovery;
98   ULONG ReachableTime;
99   BYTE TransmitOffload;
100   BYTE ReceiveOffload;
101   BOOLEAN DisableDefaultRoutes;
102 };
103
104 typedef DWORD(__stdcall * GETIPINTERFACEENTRY) (struct MibIpInterfaceRow * Row);
105
106 typedef DWORD(__stdcall * GETADAPTERSADDRESSES) (ULONG Family, DWORD Flags, PVOID Reserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses,
107                                                  PULONG pOutBufLen);
108
109 struct InterfaceInfo {
110   unsigned int Index;
111   int Mtu;
112   int Metric;
113   unsigned int Addr;
114   unsigned int Mask;
115   unsigned int Broad;
116   char Guid[39];
117 };
118
119 void WinSockPError(char *);
120 char *StrError(unsigned int ErrNo);
121
122 void ListInterfaces(void);
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     fprintf(stderr, "LoadLibrary() = %08lx", GetLastError());
184     return -1;
185   }
186
187   pfGetAdaptersAddresses = (GETADAPTERSADDRESSES) GetProcAddress(h, "GetAdaptersAddresses");
188
189   if (pfGetAdaptersAddresses == NULL) {
190     fprintf(stderr, "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     fprintf(stderr, "GetAdaptersAddresses() = %08lx", GetLastError());
200     return -1;
201   }
202
203   for (WalkerAddr = AdAddr; WalkerAddr != NULL; WalkerAddr = WalkerAddr->Next) {
204     OLSR_PRINTF(5, "Index = %08x - ", (int)WalkerAddr->IfIndex);
205
206     wcstombs(FriendlyName, WalkerAddr->FriendlyName, MAX_INTERFACE_NAME_LEN);
207
208     OLSR_PRINTF(5, "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     fprintf(stderr, "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     fprintf(stderr, "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       fprintf(stderr, "No such interface: %s!\n", Name);
246       return -1;
247     }
248   }
249
250   else {
251     if (IntNameToMiniIndex(&MiniIndex, Name) < 0) {
252       fprintf(stderr, "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     fprintf(stderr, "GetIfTable() = %08lx, %s", Res, StrError(Res));
265     return -1;
266   }
267
268   for (TabIdx = 0; TabIdx < (int)IfTable->dwNumEntries; TabIdx++) {
269     OLSR_PRINTF(5, "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     fprintf(stderr, "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     fprintf(stderr, "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_PRINTF(5, "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       fprintf(stderr, "GetIpInterfaceEntry() = %08lx", Res);
310       FreeLibrary(Lib);
311       return -1;
312     }
313
314     Info->Metric = Row.Metric;
315
316     OLSR_PRINTF(5, "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     fprintf(stderr, "GetAdaptersInfo() = %08lx, %s", GetLastError(), StrError(Res));
327     return -1;
328   }
329
330   for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next) {
331     OLSR_PRINTF(5, "Index = %08x\n", (int)Walker->Index);
332
333     if ((int)(Walker->Index & 255) == MiniIndex)
334       break;
335   }
336
337   if (Walker == NULL) {
338     fprintf(stderr, "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_PRINTF(3, "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 /* !defined OID_802_11_CONFIGURATION */
361
362 #if !defined IOCTL_NDIS_QUERY_GLOBAL_STATS
363 #define IOCTL_NDIS_QUERY_GLOBAL_STATS 0x00170002
364 #endif /* !defined IOCTL_NDIS_QUERY_GLOBAL_STATS */
365
366 static int
367 IsWireless(char *IntName)
368 {
369 #if !defined WINCE
370   struct InterfaceInfo Info;
371   char DevName[43];
372   HANDLE DevHand;
373   unsigned int ErrNo;
374   unsigned int Oid;
375   unsigned char OutBuff[100];
376   unsigned long OutBytes;
377
378   if (GetIntInfo(&Info, IntName) < 0)
379     return -1;
380
381   DevName[0] = '\\';
382   DevName[1] = '\\';
383   DevName[2] = '.';
384   DevName[3] = '\\';
385
386   strscpy(DevName + 4, Info.Guid, sizeof(DevName) - 4);
387
388   OLSR_PRINTF(5, "Checking whether interface %s is wireless.\n", DevName);
389
390   DevHand = CreateFile(DevName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
391
392   if (DevHand == INVALID_HANDLE_VALUE) {
393     ErrNo = GetLastError();
394
395     OLSR_PRINTF(5, "CreateFile() = %08x, %s\n", ErrNo, StrError(ErrNo));
396     return -1;
397   }
398
399   Oid = OID_802_11_CONFIGURATION;
400
401   if (!DeviceIoControl(DevHand, IOCTL_NDIS_QUERY_GLOBAL_STATS, &Oid, sizeof(Oid), OutBuff, sizeof(OutBuff), &OutBytes, NULL)) {
402     ErrNo = GetLastError();
403
404     CloseHandle(DevHand);
405
406     if (ErrNo == ERROR_GEN_FAILURE || ErrNo == ERROR_INVALID_PARAMETER) {
407       OLSR_PRINTF(5, "OID not supported. Device probably not wireless.\n");
408       return 0;
409     }
410
411     OLSR_PRINTF(5, "DeviceIoControl() = %08x, %s\n", ErrNo, StrError(ErrNo));
412     return -1;
413   }
414
415   CloseHandle(DevHand);
416 #endif /* !defined WINCE */
417   return 1;
418 }
419
420 void
421 ListInterfaces(void)
422 {
423   IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
424   unsigned long AdInfoLen;
425   char IntName[5];
426   IP_ADDR_STRING *Walker2;
427   unsigned long Res;
428   int IsWlan;
429
430   if (olsr_cnf->ip_version == AF_INET6) {
431     fprintf(stderr, "IPv6 not supported by ListInterfaces()!\n");
432     return;
433   }
434
435   AdInfoLen = sizeof(AdInfo);
436
437   Res = GetAdaptersInfo(AdInfo, &AdInfoLen);
438
439   if (Res == ERROR_NO_DATA) {
440     printf("No interfaces detected.\n");
441     return;
442   }
443
444   if (Res != NO_ERROR) {
445     fprintf(stderr, "GetAdaptersInfo() = %08lx, %s", Res, StrError(Res));
446     return;
447   }
448
449   for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next) {
450     OLSR_PRINTF(5, "Index = %08x\n", (int)Walker->Index);
451
452     MiniIndexToIntName(IntName, Walker->Index);
453
454     printf("%s: ", IntName);
455
456     IsWlan = IsWireless(IntName);
457
458     if (IsWlan < 0)
459       printf("?");
460
461     else if (IsWlan == 0)
462       printf("-");
463
464     else
465       printf("+");
466
467     for (Walker2 = &Walker->IpAddressList; Walker2 != NULL; Walker2 = Walker2->Next)
468       printf(" %s", Walker2->IpAddress.String);
469
470     printf("\n");
471   }
472 }
473
474 int
475 add_hemu_if(struct olsr_if *iface)
476 {
477   struct interface_olsr *ifp;
478   union olsr_ip_addr null_addr;
479   uint32_t addr[4];
480   struct ipaddr_str buf;
481   size_t name_size;
482
483   if (!iface->host_emul)
484     return -1;
485
486   ifp = olsr_malloc(sizeof(struct interface_olsr), "Interface update 2");
487
488   memset(ifp, 0, sizeof(struct interface_olsr));
489
490   /* initialize backpointer */
491   ifp->olsr_if = iface;
492
493   iface->configured = true;
494   iface->interf = ifp;
495
496   name_size = strlen("hcif01") + 1;
497   ifp->is_hcif = true;
498   ifp->int_name = olsr_malloc(name_size, "Interface update 3");
499   ifp->int_metric = 0;
500
501   strscpy(ifp->int_name, "hcif01", name_size);
502
503   OLSR_PRINTF(1, "Adding %s(host emulation):\n", ifp->int_name);
504
505   OLSR_PRINTF(1, "       Address:%s\n", olsr_ip_to_string(&buf, &iface->hemu_ip));
506
507   OLSR_PRINTF(1, "       NB! This is a emulated interface\n       that does not exist in the kernel!\n");
508
509   ifp->int_next = ifnet;
510   ifnet = ifp;
511
512   memset(&null_addr, 0, olsr_cnf->ipsize);
513   if (ipequal(&null_addr, &olsr_cnf->main_addr)) {
514     olsr_cnf->main_addr = iface->hemu_ip;
515     olsr_cnf->unicast_src_ip = iface->hemu_ip;
516     OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
517   }
518
519   ifp->int_mtu = OLSR_DEFAULT_MTU;
520
521   ifp->int_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
522
523   /* Set up buffer */
524   net_add_buffer(ifp);
525
526   if (olsr_cnf->ip_version == AF_INET) {
527     struct sockaddr_in sin;
528
529     memset(&sin, 0, sizeof(sin));
530
531     sin.sin_family = AF_INET;
532     sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
533     sin.sin_port = htons(10150);
534
535     /* IP version 4 */
536     ifp->ip_addr.v4 = iface->hemu_ip.v4;
537
538     memcpy(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, &iface->hemu_ip, olsr_cnf->ipsize);
539
540     /*
541      *We create one socket for each interface and bind
542      *the socket to it. This to ensure that we can control
543      *on what interface the message is transmitted
544      */
545
546     ifp->olsr_socket = gethemusocket(&sin);
547
548     if (ifp->olsr_socket < 0) {
549       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
550       exit(1);
551     }
552
553   } else {
554     /* IP version 6 */
555     memcpy(&ifp->ip_addr, &iface->hemu_ip, olsr_cnf->ipsize);
556   }
557
558   /* Send IP as first 4/16 bytes on socket */
559   memcpy(addr, iface->hemu_ip.v6.s6_addr, olsr_cnf->ipsize);
560   addr[0] = htonl(addr[0]);
561   addr[1] = htonl(addr[1]);
562   addr[2] = htonl(addr[2]);
563   addr[3] = htonl(addr[3]);
564
565   if (send(ifp->olsr_socket, (char *)addr, olsr_cnf->ipsize, 0) != (int)olsr_cnf->ipsize) {
566     fprintf(stderr, "Error sending IP!");
567   }
568
569   /* Register socket */
570   add_olsr_socket(ifp->olsr_socket, &olsr_input_hostemu, NULL, NULL, SP_PR_READ);
571
572   /*
573    * Register functions for periodic message generation
574    */
575   ifp->hello_gen_timer =
576     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC, HELLO_JITTER, OLSR_TIMER_PERIODIC,
577                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, ifp, hello_gen_timer_cookie);
578   ifp->tc_gen_timer =
579     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC, TC_JITTER, OLSR_TIMER_PERIODIC,
580                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, ifp, tc_gen_timer_cookie);
581   ifp->mid_gen_timer =
582     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC, MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
583                      mid_gen_timer_cookie);
584   ifp->hna_gen_timer =
585     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC, HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
586                      hna_gen_timer_cookie);
587
588   /* Recalculate max topology hold time */
589   if (olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval)
590     olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
591
592   ifp->hello_etime = (olsr_reltime) (iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
593   ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
594   ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
595   ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
596   ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
597
598   ifp->mode = iface->cnf->mode;
599
600   return 1;
601 }
602
603 int
604 chk_if_changed(struct olsr_if *iface)
605 {
606   struct ipaddr_str buf;
607   struct interface_olsr *Int;
608   struct InterfaceInfo Info;
609   int Res;
610   int IsWlan;
611   union olsr_ip_addr OldVal, NewVal;
612   struct sockaddr_in *AddrIn;
613
614   if (olsr_cnf->ip_version == AF_INET6) {
615     fprintf(stderr, "IPv6 not supported by chk_if_changed()!\n");
616     return 0;
617   }
618 #ifdef DEBUG
619   OLSR_PRINTF(3, "Checking if %s is set down or changed\n", iface->name);
620 #endif /* DEBUG */
621
622   Int = iface->interf;
623
624   if (GetIntInfo(&Info, iface->name) < 0) {
625     olsr_remove_interface(iface);
626     return 1;
627   }
628
629   Res = 0;
630
631   IsWlan = IsWireless(iface->name);
632
633   if (IsWlan < 0)
634     IsWlan = 1;
635
636   if (Int->is_wireless != IsWlan) {
637     OLSR_PRINTF(1, "\tLAN/WLAN change: %d -> %d.\n", Int->is_wireless, IsWlan);
638
639     Int->is_wireless = IsWlan;
640
641     if (iface->cnf->weight.fixed)
642       Int->int_metric = iface->cnf->weight.value;
643
644     else
645       Int->int_metric = Info.Metric;
646
647     Res = 1;
648   }
649
650   if (Int->int_mtu != Info.Mtu) {
651     OLSR_PRINTF(1, "\tMTU change: %d -> %d.\n", (int)Int->int_mtu, Info.Mtu);
652
653     Int->int_mtu = Info.Mtu;
654
655     net_remove_buffer(Int);
656     net_add_buffer(Int);
657
658     Res = 1;
659   }
660
661   OldVal.v4 = ((struct sockaddr_in *)&Int->int_addr)->sin_addr;
662   NewVal.v4.s_addr = Info.Addr;
663
664 #ifdef DEBUG
665   OLSR_PRINTF(3, "\tAddress: %s\n", olsr_ip_to_string(&buf, &NewVal));
666 #endif /* DEBUG */
667
668   if (NewVal.v4.s_addr != OldVal.v4.s_addr) {
669     OLSR_PRINTF(1, "\tAddress change.\n");
670     OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
671     OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
672
673     Int->ip_addr.v4 = NewVal.v4;
674
675     AddrIn = (struct sockaddr_in *)&Int->int_addr;
676
677     AddrIn->sin_family = AF_INET;
678     AddrIn->sin_port = 0;
679     AddrIn->sin_addr = NewVal.v4;
680
681     if (olsr_cnf->main_addr.v4.s_addr == OldVal.v4.s_addr) {
682       OLSR_PRINTF(1, "\tMain address change.\n");
683
684       olsr_cnf->main_addr.v4 = NewVal.v4;
685     }
686
687     Res = 1;
688   }
689
690   else
691     OLSR_PRINTF(3, "\tNo address change.\n");
692
693   OldVal.v4 = ((struct sockaddr_in *)&Int->int_netmask)->sin_addr;
694   NewVal.v4.s_addr = Info.Mask;
695
696 #ifdef DEBUG
697   OLSR_PRINTF(3, "\tNetmask: %s\n", olsr_ip_to_string(&buf, &NewVal));
698 #endif /* DEBUG */
699
700   if (NewVal.v4.s_addr != OldVal.v4.s_addr) {
701     OLSR_PRINTF(1, "\tNetmask change.\n");
702     OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
703     OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
704
705     AddrIn = (struct sockaddr_in *)&Int->int_netmask;
706
707     AddrIn->sin_family = AF_INET;
708     AddrIn->sin_port = 0;
709     AddrIn->sin_addr = NewVal.v4;
710
711     Res = 1;
712   }
713
714   else
715     OLSR_PRINTF(3, "\tNo netmask change.\n");
716
717   OldVal.v4 = ((struct sockaddr_in *)&Int->int_broadaddr)->sin_addr;
718   NewVal.v4.s_addr = Info.Broad;
719
720 #ifdef DEBUG
721   OLSR_PRINTF(3, "\tBroadcast address: %s\n", olsr_ip_to_string(&buf, &NewVal));
722 #endif /* DEBUG */
723
724   if (NewVal.v4.s_addr != OldVal.v4.s_addr) {
725     OLSR_PRINTF(1, "\tBroadcast address change.\n");
726     OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
727     OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
728
729     AddrIn = (struct sockaddr_in *)&Int->int_broadaddr;
730
731     AddrIn->sin_family = AF_INET;
732     AddrIn->sin_port = 0;
733     AddrIn->sin_addr = NewVal.v4;
734
735     Res = 1;
736   }
737
738   else
739     OLSR_PRINTF(3, "\tNo broadcast address change.\n");
740
741   if (Res != 0)
742     olsr_trigger_ifchange(Int->if_index, Int, IFCHG_IF_UPDATE);
743
744   return Res;
745 }
746
747 int
748 chk_if_up(struct olsr_if *iface, int debuglvl __attribute__ ((unused)))
749 {
750   struct ipaddr_str buf;
751   struct InterfaceInfo Info;
752   struct interface_olsr *New;
753   union olsr_ip_addr NullAddr;
754   int IsWlan;
755   struct sockaddr_in *AddrIn;
756   size_t name_size;
757
758   if (olsr_cnf->ip_version == AF_INET6) {
759     fprintf(stderr, "IPv6 not supported by chk_if_up()!\n");
760     return 0;
761   }
762
763   if (GetIntInfo(&Info, iface->name) < 0)
764     return 0;
765
766   New = olsr_malloc(sizeof(struct interface_olsr), "Interface 1");
767   /* initialize backpointer */
768   New->olsr_if = iface;
769
770
771   New->immediate_send_tc = (iface->cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval);
772   if (olsr_cnf->max_jitter == 0) {
773     /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
774     olsr_cnf->max_jitter =
775       New->immediate_send_tc ? iface->cnf->tc_params.emission_interval : iface->cnf->hello_params.emission_interval;
776   }
777
778   New->gen_properties = NULL;
779
780   AddrIn = (struct sockaddr_in *)&New->int_addr;
781
782   AddrIn->sin_family = AF_INET;
783   AddrIn->sin_port = 0;
784   AddrIn->sin_addr.s_addr = Info.Addr;
785
786   AddrIn = (struct sockaddr_in *)&New->int_netmask;
787
788   AddrIn->sin_family = AF_INET;
789   AddrIn->sin_port = 0;
790   AddrIn->sin_addr.s_addr = Info.Mask;
791
792   AddrIn = (struct sockaddr_in *)&New->int_broadaddr;
793
794   AddrIn->sin_family = AF_INET;
795   AddrIn->sin_port = 0;
796   AddrIn->sin_addr.s_addr = Info.Broad;
797
798   if (iface->cnf->ipv4_multicast.v4.s_addr != 0)
799     AddrIn->sin_addr = iface->cnf->ipv4_multicast.v4;
800
801   New->int_flags = 0;
802
803   New->is_hcif = false;
804
805   New->int_mtu = Info.Mtu;
806
807   name_size = strlen(iface->name) + 1;
808   New->int_name = olsr_malloc(name_size, "Interface 2");
809   strscpy(New->int_name, iface->name, name_size);
810
811   IsWlan = IsWireless(iface->name);
812
813   if (IsWlan < 0)
814     IsWlan = 1;
815
816   New->is_wireless = IsWlan;
817
818   if (iface->cnf->weight.fixed)
819     New->int_metric = iface->cnf->weight.value;
820
821   else
822     New->int_metric = Info.Metric;
823
824   New->olsr_seqnum = olsr_random() & 0xffff;
825
826   New->ttl_index = -32;         /* For the first 32 TC's, fish-eye is disabled */
827
828   OLSR_PRINTF(1, "\tInterface %s set up for use with index %d\n\n", iface->name, New->if_index);
829
830   OLSR_PRINTF(1, "\tMTU: %d\n", New->int_mtu);
831   OLSR_PRINTF(1, "\tAddress: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr *)&New->int_addr));
832   OLSR_PRINTF(1, "\tNetmask: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr *)&New->int_netmask));
833   OLSR_PRINTF(1, "\tBroadcast address: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr *)&New->int_broadaddr));
834
835   New->ip_addr.v4 = New->int_addr.sin_addr;
836
837   New->if_index = Info.Index;
838
839   OLSR_PRINTF(3, "\tKernel index: %08x\n", New->if_index);
840
841   New->olsr_socket = getsocket(BUFSPACE, New);
842   New->send_socket = getsocket(0, New);
843
844   if (New->olsr_socket < 0) {
845     fprintf(stderr, "Could not initialize socket... exiting!\n\n");
846     exit(1);
847   }
848
849   add_olsr_socket(New->olsr_socket, &olsr_input, NULL, NULL, SP_PR_READ);
850
851   New->int_next = ifnet;
852   ifnet = New;
853
854   iface->interf = New;
855   iface->configured = 1;
856
857   memset(&NullAddr, 0, olsr_cnf->ipsize);
858
859   if (ipequal(&NullAddr, &olsr_cnf->main_addr)) {
860     olsr_cnf->main_addr = New->ip_addr;
861     olsr_cnf->unicast_src_ip = New->ip_addr;
862     OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
863   }
864
865   net_add_buffer(New);
866
867   /*
868    * Register functions for periodic message generation
869    */
870   New->hello_gen_timer =
871     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC, HELLO_JITTER, OLSR_TIMER_PERIODIC,
872                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, New, hello_gen_timer_cookie);
873   New->tc_gen_timer =
874     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC, TC_JITTER, OLSR_TIMER_PERIODIC,
875                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, New, tc_gen_timer_cookie);
876   New->mid_gen_timer =
877     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC, MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, New,
878                      mid_gen_timer_cookie);
879   New->hna_gen_timer =
880     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC, HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, New,
881                      hna_gen_timer_cookie);
882
883   if (olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval)
884     olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
885
886   New->hello_etime = (olsr_reltime) (iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
887   New->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
888   New->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
889   New->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
890   New->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
891
892   New->mode = iface->cnf->mode;
893
894   olsr_trigger_ifchange(New->if_index, New, IFCHG_IF_ADD);
895
896   return 1;
897 }
898
899 void
900 check_interface_updates(void *dummy __attribute__ ((unused)))
901 {
902   struct olsr_if *IntConf;
903
904 #ifdef DEBUG
905   OLSR_PRINTF(3, "Checking for updates in the interface set\n");
906 #endif /* DEBUG */
907
908   for (IntConf = olsr_cnf->interfaces; IntConf != NULL; IntConf = IntConf->next) {
909     if (IntConf->host_emul)
910       continue;
911
912     if (olsr_cnf->host_emul)    /* XXX: TEMPORARY! */
913       continue;
914
915     if (IntConf->configured)
916       chk_if_changed(IntConf);
917
918     else
919       chk_if_up(IntConf, 3);
920   }
921 }
922
923 #endif /* _WIN32 */
924
925 /*
926  * Local Variables:
927  * c-basic-offset: 2
928  * indent-tabs-mode: nil
929  * End:
930  */