3dc240462a3fc0b249bac09e24f8b63d5f7df6dc
[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 #include <stdlib.h>
43 #define random() rand()
44 #define srandom(x) srand(x)
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
58 #include <iphlpapi.h>
59 #include <iprtrmib.h>
60
61 #include <arpa/inet.h>
62
63 #define BUFSPACE  (127*1024)    /* max. input buffer size to request */
64
65 struct MibIpInterfaceRow {
66   USHORT Family;
67   ULONG64 InterfaceLuid;
68   ULONG InterfaceIndex;
69   ULONG MaxReassemblySize;
70   ULONG64 InterfaceIdentifier;
71   ULONG MinRouterAdvertisementInterval;
72   ULONG MaxRouterAdvertisementInterval;
73   BOOLEAN AdvertisingEnabled;
74   BOOLEAN ForwardingEnabled;
75   BOOLEAN WeakHostSend;
76   BOOLEAN WeakHostReceive;
77   BOOLEAN UseAutomaticMetric;
78   BOOLEAN UseNeighborUnreachabilityDetection;
79   BOOLEAN ManagedAddressConfigurationSupported;
80   BOOLEAN OtherStatefulConfigurationSupported;
81   BOOLEAN AdvertiseDefaultRoute;
82   INT RouterDiscoveryBehavior;
83   ULONG DadTransmits;
84   ULONG BaseReachableTime;
85   ULONG RetransmitTime;
86   ULONG PathMtuDiscoveryTimeout;
87   INT LinkLocalAddressBehavior;
88   ULONG LinkLocalAddressTimeout;
89   ULONG ZoneIndices[16];
90   ULONG SitePrefixLength;
91   ULONG Metric;
92   ULONG NlMtu;
93   BOOLEAN Connected;
94   BOOLEAN SupportsWakeUpPatterns;
95   BOOLEAN SupportsNeighborDiscovery;
96   BOOLEAN SupportsRouterDiscovery;
97   ULONG ReachableTime;
98   BYTE TransmitOffload;
99   BYTE ReceiveOffload;
100   BOOLEAN DisableDefaultRoutes;
101 };
102
103 typedef DWORD(__stdcall * GETIPINTERFACEENTRY) (struct MibIpInterfaceRow * Row);
104
105 typedef DWORD(__stdcall * GETADAPTERSADDRESSES) (ULONG Family, DWORD Flags, PVOID Reserved, PIP_ADAPTER_ADDRESSES pAdapterAddresses,
106                                                  PULONG pOutBufLen);
107
108 struct InterfaceInfo {
109   unsigned int Index;
110   int Mtu;
111   int Metric;
112   unsigned int Addr;
113   unsigned int Mask;
114   unsigned int Broad;
115   char Guid[39];
116 };
117
118 void WinSockPError(char *);
119 char *StrError(unsigned int ErrNo);
120
121 void ListInterfaces(void);
122 int GetIntInfo(struct InterfaceInfo *Info, char *Name);
123
124 #define MAX_INTERFACES 100
125
126 static void
127 MiniIndexToIntName(char *String, int MiniIndex)
128 {
129   const char *HexDigits = "0123456789abcdef";
130
131   String[0] = 'i';
132   String[1] = 'f';
133
134   String[2] = HexDigits[(MiniIndex >> 4) & 15];
135   String[3] = HexDigits[MiniIndex & 15];
136
137   String[4] = 0;
138 }
139
140 static int
141 IntNameToMiniIndex(int *MiniIndex, char *String)
142 {
143   const char *HexDigits = "0123456789abcdef";
144   int i, k;
145   char ch;
146
147   if ((String[0] != 'i' && String[0] != 'I') || (String[1] != 'f' && String[1] != 'F'))
148     return -1;
149
150   *MiniIndex = 0;
151
152   for (i = 2; i < 4; i++) {
153     ch = String[i];
154
155     if (ch >= 'A' && ch <= 'F')
156       ch += 32;
157
158     for (k = 0; k < 16 && ch != HexDigits[k]; k++);
159
160     if (k == 16)
161       return -1;
162
163     *MiniIndex = (*MiniIndex << 4) | k;
164   }
165
166   return 0;
167 }
168
169 static int
170 FriendlyNameToMiniIndex(int *MiniIndex, char *String)
171 {
172   unsigned long BuffLen;
173   unsigned long Res;
174   IP_ADAPTER_ADDRESSES AdAddr[MAX_INTERFACES], *WalkerAddr;
175   char FriendlyName[MAX_INTERFACE_NAME_LEN];
176   HMODULE h;
177   GETADAPTERSADDRESSES pfGetAdaptersAddresses;
178
179   h = LoadLibrary("iphlpapi.dll");
180
181   if (h == NULL) {
182     fprintf(stderr, "LoadLibrary() = %08lx", GetLastError());
183     return -1;
184   }
185
186   pfGetAdaptersAddresses = (GETADAPTERSADDRESSES) GetProcAddress(h, "GetAdaptersAddresses");
187
188   if (pfGetAdaptersAddresses == NULL) {
189     fprintf(stderr, "Unable to use adapter friendly name (GetProcAddress() = %08lx)\n", GetLastError());
190     return -1;
191   }
192
193   BuffLen = sizeof(AdAddr);
194
195   Res = pfGetAdaptersAddresses(AF_INET, 0, NULL, AdAddr, &BuffLen);
196
197   if (Res != NO_ERROR) {
198     fprintf(stderr, "GetAdaptersAddresses() = %08lx", GetLastError());
199     return -1;
200   }
201
202   for (WalkerAddr = AdAddr; WalkerAddr != NULL; WalkerAddr = WalkerAddr->Next) {
203     OLSR_PRINTF(5, "Index = %08x - ", (int)WalkerAddr->IfIndex);
204
205     wcstombs(FriendlyName, WalkerAddr->FriendlyName, MAX_INTERFACE_NAME_LEN);
206
207     OLSR_PRINTF(5, "Friendly name = %s\n", FriendlyName);
208
209     if (strncmp(FriendlyName, String, MAX_INTERFACE_NAME_LEN) == 0)
210       break;
211   }
212
213   if (WalkerAddr == NULL) {
214     fprintf(stderr, "No such interface: %s!\n", String);
215     return -1;
216   }
217
218   *MiniIndex = WalkerAddr->IfIndex & 255;
219
220   return 0;
221 }
222
223 int
224 GetIntInfo(struct InterfaceInfo *Info, char *Name)
225 {
226   int MiniIndex;
227   unsigned char Buff[MAX_INTERFACES * sizeof(MIB_IFROW) + 4];
228   MIB_IFTABLE *IfTable;
229   unsigned long BuffLen;
230   unsigned long Res;
231   int TabIdx;
232   IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
233   HMODULE Lib;
234   struct MibIpInterfaceRow Row;
235   GETIPINTERFACEENTRY InterfaceEntry;
236
237   if (olsr_cnf->ip_version == AF_INET6) {
238     fprintf(stderr, "IPv6 not supported by GetIntInfo()!\n");
239     return -1;
240   }
241
242   if ((Name[0] != 'i' && Name[0] != 'I') || (Name[1] != 'f' && Name[1] != 'F')) {
243     if (FriendlyNameToMiniIndex(&MiniIndex, Name) < 0) {
244       fprintf(stderr, "No such interface: %s!\n", Name);
245       return -1;
246     }
247   }
248
249   else {
250     if (IntNameToMiniIndex(&MiniIndex, Name) < 0) {
251       fprintf(stderr, "No such interface: %s!\n", Name);
252       return -1;
253     }
254   }
255
256   IfTable = (MIB_IFTABLE *) Buff;
257
258   BuffLen = sizeof(Buff);
259
260   Res = GetIfTable(IfTable, &BuffLen, FALSE);
261
262   if (Res != NO_ERROR) {
263     fprintf(stderr, "GetIfTable() = %08lx, %s", Res, StrError(Res));
264     return -1;
265   }
266
267   for (TabIdx = 0; TabIdx < (int)IfTable->dwNumEntries; TabIdx++) {
268     OLSR_PRINTF(5, "Index = %08x\n", (int)IfTable->table[TabIdx].dwIndex);
269
270     if ((int)(IfTable->table[TabIdx].dwIndex & 255) == MiniIndex)
271       break;
272   }
273
274   if (TabIdx == (int)IfTable->dwNumEntries) {
275     fprintf(stderr, "No such interface: %s!\n", Name);
276     return -1;
277   }
278
279   Info->Index = IfTable->table[TabIdx].dwIndex;
280   Info->Mtu = (int)IfTable->table[TabIdx].dwMtu;
281
282   Info->Mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
283
284   Lib = LoadLibrary("iphlpapi.dll");
285
286   if (Lib == NULL) {
287     fprintf(stderr, "Cannot load iphlpapi.dll: %08lx\n", GetLastError());
288     return -1;
289   }
290
291   InterfaceEntry = (GETIPINTERFACEENTRY) GetProcAddress(Lib, "GetIpInterfaceEntry");
292
293   if (InterfaceEntry == NULL) {
294     OLSR_PRINTF(5, "Not running on Vista - setting interface metric to 0.\n");
295
296     Info->Metric = 0;
297   }
298
299   else {
300     memset(&Row, 0, sizeof(struct MibIpInterfaceRow));
301
302     Row.Family = AF_INET;
303     Row.InterfaceIndex = Info->Index;
304
305     Res = InterfaceEntry(&Row);
306
307     if (Res != NO_ERROR) {
308       fprintf(stderr, "GetIpInterfaceEntry() = %08lx", Res);
309       FreeLibrary(Lib);
310       return -1;
311     }
312
313     Info->Metric = Row.Metric;
314
315     OLSR_PRINTF(5, "Running on Vista - interface metric is %d.\n", Info->Metric);
316   }
317
318   FreeLibrary(Lib);
319
320   BuffLen = sizeof(AdInfo);
321
322   Res = GetAdaptersInfo(AdInfo, &BuffLen);
323
324   if (Res != NO_ERROR) {
325     fprintf(stderr, "GetAdaptersInfo() = %08lx, %s", GetLastError(), StrError(Res));
326     return -1;
327   }
328
329   for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next) {
330     OLSR_PRINTF(5, "Index = %08x\n", (int)Walker->Index);
331
332     if ((int)(Walker->Index & 255) == MiniIndex)
333       break;
334   }
335
336   if (Walker == NULL) {
337     fprintf(stderr, "No such interface: %s!\n", Name);
338     return -1;
339   }
340
341   inet_pton(AF_INET, Walker->IpAddressList.IpAddress.String, &Info->Addr);
342   inet_pton(AF_INET, Walker->IpAddressList.IpMask.String, &Info->Mask);
343
344   Info->Broad = Info->Addr | ~Info->Mask;
345
346   strscpy(Info->Guid, Walker->AdapterName, sizeof(Info->Guid));
347
348   if ((IfTable->table[TabIdx].dwOperStatus != MIB_IF_OPER_STATUS_CONNECTED
349        && IfTable->table[TabIdx].dwOperStatus != MIB_IF_OPER_STATUS_OPERATIONAL) || Info->Addr == 0) {
350     OLSR_PRINTF(3, "Interface %s not up!\n", Name);
351     return -1;
352   }
353
354   return 0;
355 }
356
357 #if !defined OID_802_11_CONFIGURATION
358 #define OID_802_11_CONFIGURATION 0x0d010211
359 #endif
360
361 #if !defined IOCTL_NDIS_QUERY_GLOBAL_STATS
362 #define IOCTL_NDIS_QUERY_GLOBAL_STATS 0x00170002
363 #endif
364
365 static int
366 IsWireless(char *IntName)
367 {
368 #if !defined WINCE
369   struct InterfaceInfo Info;
370   char DevName[43];
371   HANDLE DevHand;
372   unsigned int ErrNo;
373   unsigned int Oid;
374   unsigned char OutBuff[100];
375   unsigned long OutBytes;
376
377   if (GetIntInfo(&Info, IntName) < 0)
378     return -1;
379
380   DevName[0] = '\\';
381   DevName[1] = '\\';
382   DevName[2] = '.';
383   DevName[3] = '\\';
384
385   strscpy(DevName + 4, Info.Guid, sizeof(DevName) - 4);
386
387   OLSR_PRINTF(5, "Checking whether interface %s is wireless.\n", DevName);
388
389   DevHand = CreateFile(DevName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
390
391   if (DevHand == INVALID_HANDLE_VALUE) {
392     ErrNo = GetLastError();
393
394     OLSR_PRINTF(5, "CreateFile() = %08x, %s\n", ErrNo, StrError(ErrNo));
395     return -1;
396   }
397
398   Oid = OID_802_11_CONFIGURATION;
399
400   if (!DeviceIoControl(DevHand, IOCTL_NDIS_QUERY_GLOBAL_STATS, &Oid, sizeof(Oid), OutBuff, sizeof(OutBuff), &OutBytes, NULL)) {
401     ErrNo = GetLastError();
402
403     CloseHandle(DevHand);
404
405     if (ErrNo == ERROR_GEN_FAILURE || ErrNo == ERROR_INVALID_PARAMETER) {
406       OLSR_PRINTF(5, "OID not supported. Device probably not wireless.\n");
407       return 0;
408     }
409
410     OLSR_PRINTF(5, "DeviceIoControl() = %08x, %s\n", ErrNo, StrError(ErrNo));
411     return -1;
412   }
413
414   CloseHandle(DevHand);
415 #endif
416   return 1;
417 }
418
419 void
420 ListInterfaces(void)
421 {
422   IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
423   unsigned long AdInfoLen;
424   char IntName[5];
425   IP_ADDR_STRING *Walker2;
426   unsigned long Res;
427   int IsWlan;
428
429   if (olsr_cnf->ip_version == AF_INET6) {
430     fprintf(stderr, "IPv6 not supported by ListInterfaces()!\n");
431     return;
432   }
433
434   AdInfoLen = sizeof(AdInfo);
435
436   Res = GetAdaptersInfo(AdInfo, &AdInfoLen);
437
438   if (Res == ERROR_NO_DATA) {
439     printf("No interfaces detected.\n");
440     return;
441   }
442
443   if (Res != NO_ERROR) {
444     fprintf(stderr, "GetAdaptersInfo() = %08lx, %s", Res, StrError(Res));
445     return;
446   }
447
448   for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next) {
449     OLSR_PRINTF(5, "Index = %08x\n", (int)Walker->Index);
450
451     MiniIndexToIntName(IntName, Walker->Index);
452
453     printf("%s: ", IntName);
454
455     IsWlan = IsWireless(IntName);
456
457     if (IsWlan < 0)
458       printf("?");
459
460     else if (IsWlan == 0)
461       printf("-");
462
463     else
464       printf("+");
465
466     for (Walker2 = &Walker->IpAddressList; Walker2 != NULL; Walker2 = Walker2->Next)
467       printf(" %s", Walker2->IpAddress.String);
468
469     printf("\n");
470   }
471 }
472
473 int
474 add_hemu_if(struct olsr_if *iface)
475 {
476   struct interface *ifp;
477   union olsr_ip_addr null_addr;
478   uint32_t addr[4];
479   struct ipaddr_str buf;
480   size_t name_size;
481
482   if (!iface->host_emul)
483     return -1;
484
485   ifp = olsr_malloc(sizeof(struct interface), "Interface update 2");
486
487   memset(ifp, 0, sizeof(struct interface));
488
489   /* initialize backpointer */
490   ifp->olsr_if = iface;
491
492   iface->configured = true;
493   iface->interf = ifp;
494
495   name_size = strlen("hcif01") + 1;
496   ifp->is_hcif = true;
497   ifp->int_name = olsr_malloc(name_size, "Interface update 3");
498   ifp->int_metric = 0;
499
500   strscpy(ifp->int_name, "hcif01", name_size);
501
502   OLSR_PRINTF(1, "Adding %s(host emulation):\n", ifp->int_name);
503
504   OLSR_PRINTF(1, "       Address:%s\n", olsr_ip_to_string(&buf, &iface->hemu_ip));
505
506   OLSR_PRINTF(1, "       NB! This is a emulated interface\n       that does not exist in the kernel!\n");
507
508   ifp->int_next = ifnet;
509   ifnet = ifp;
510
511   memset(&null_addr, 0, olsr_cnf->ipsize);
512   if (ipequal(&null_addr, &olsr_cnf->main_addr)) {
513     olsr_cnf->main_addr = iface->hemu_ip;
514     OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
515   }
516
517   ifp->int_mtu = OLSR_DEFAULT_MTU;
518
519   ifp->int_mtu -= (olsr_cnf->ip_version == AF_INET6) ? UDP_IPV6_HDRSIZE : UDP_IPV4_HDRSIZE;
520
521   /* Set up buffer */
522   net_add_buffer(ifp);
523
524   if (olsr_cnf->ip_version == AF_INET) {
525     struct sockaddr_in sin;
526
527     memset(&sin, 0, sizeof(sin));
528
529     sin.sin_family = AF_INET;
530     sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
531     sin.sin_port = htons(10150);
532
533     /* IP version 4 */
534     ifp->ip_addr.v4 = iface->hemu_ip.v4;
535
536     memcpy(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, &iface->hemu_ip, olsr_cnf->ipsize);
537
538     /*
539      *We create one socket for each interface and bind
540      *the socket to it. This to ensure that we can control
541      *on what interface the message is transmitted
542      */
543
544     ifp->olsr_socket = gethemusocket(&sin);
545
546     if (ifp->olsr_socket < 0) {
547       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
548       exit(1);
549     }
550
551   } else {
552     /* IP version 6 */
553     memcpy(&ifp->ip_addr, &iface->hemu_ip, olsr_cnf->ipsize);
554
555 #if 0
556     /*
557      *We create one socket for each interface and bind
558      *the socket to it. This to ensure that we can control
559      *on what interface the message is transmitted
560      */
561
562     ifp->olsr_socket = gethcsocket6(&addrsock6, bufspace, ifp->int_name);
563
564     join_mcast(ifp, ifp->olsr_socket);
565
566     if (ifp->olsr_socket < 0) {
567       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
568       exit(1);
569     }
570 #endif
571   }
572
573   /* Send IP as first 4/16 bytes on socket */
574   memcpy(addr, iface->hemu_ip.v6.s6_addr, olsr_cnf->ipsize);
575   addr[0] = htonl(addr[0]);
576   addr[1] = htonl(addr[1]);
577   addr[2] = htonl(addr[2]);
578   addr[3] = htonl(addr[3]);
579
580   if (send(ifp->olsr_socket, (char *)addr, olsr_cnf->ipsize, 0) != (int)olsr_cnf->ipsize) {
581     fprintf(stderr, "Error sending IP!");
582   }
583
584   /* Register socket */
585   add_olsr_socket(ifp->olsr_socket, &olsr_input_hostemu, NULL, NULL, SP_PR_READ);
586
587   /*
588    * Register functions for periodic message generation
589    */
590   ifp->hello_gen_timer =
591     olsr_start_timer(iface->cnf->hello_params.emission_interval * MSEC_PER_SEC, HELLO_JITTER, OLSR_TIMER_PERIODIC,
592                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, ifp, hello_gen_timer_cookie);
593   ifp->tc_gen_timer =
594     olsr_start_timer(iface->cnf->tc_params.emission_interval * MSEC_PER_SEC, TC_JITTER, OLSR_TIMER_PERIODIC,
595                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, ifp, tc_gen_timer_cookie);
596   ifp->mid_gen_timer =
597     olsr_start_timer(iface->cnf->mid_params.emission_interval * MSEC_PER_SEC, MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, ifp,
598                      mid_gen_timer_cookie);
599   ifp->hna_gen_timer =
600     olsr_start_timer(iface->cnf->hna_params.emission_interval * MSEC_PER_SEC, HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, ifp,
601                      hna_gen_timer_cookie);
602
603   /* Recalculate max topology hold time */
604   if (olsr_cnf->max_tc_vtime < iface->cnf->tc_params.emission_interval)
605     olsr_cnf->max_tc_vtime = iface->cnf->tc_params.emission_interval;
606
607   ifp->hello_etime = (olsr_reltime) (iface->cnf->hello_params.emission_interval * MSEC_PER_SEC);
608   ifp->valtimes.hello = reltime_to_me(iface->cnf->hello_params.validity_time * MSEC_PER_SEC);
609   ifp->valtimes.tc = reltime_to_me(iface->cnf->tc_params.validity_time * MSEC_PER_SEC);
610   ifp->valtimes.mid = reltime_to_me(iface->cnf->mid_params.validity_time * MSEC_PER_SEC);
611   ifp->valtimes.hna = reltime_to_me(iface->cnf->hna_params.validity_time * MSEC_PER_SEC);
612
613   ifp->mode = iface->cnf->mode;
614
615   return 1;
616 }
617
618 int
619 chk_if_changed(struct olsr_if *IntConf)
620 {
621   struct ipaddr_str buf;
622   struct interface *Int;
623   struct InterfaceInfo Info;
624   int Res;
625   int IsWlan;
626   union olsr_ip_addr OldVal, NewVal;
627   struct sockaddr_in *AddrIn;
628
629   if (olsr_cnf->ip_version == AF_INET6) {
630     fprintf(stderr, "IPv6 not supported by chk_if_changed()!\n");
631     return 0;
632   }
633 #ifdef DEBUG
634   OLSR_PRINTF(3, "Checking if %s is set down or changed\n", IntConf->name);
635 #endif
636
637   Int = IntConf->interf;
638
639   if (GetIntInfo(&Info, IntConf->name) < 0) {
640     olsr_remove_interface(IntConf);
641     return 1;
642   }
643
644   Res = 0;
645
646   IsWlan = IsWireless(IntConf->name);
647
648   if (IsWlan < 0)
649     IsWlan = 1;
650
651   if (Int->is_wireless != IsWlan) {
652     OLSR_PRINTF(1, "\tLAN/WLAN change: %d -> %d.\n", Int->is_wireless, IsWlan);
653
654     Int->is_wireless = IsWlan;
655
656     if (IntConf->cnf->weight.fixed)
657       Int->int_metric = IntConf->cnf->weight.value;
658
659     else
660       Int->int_metric = Info.Metric;
661
662     Res = 1;
663   }
664
665   if (Int->int_mtu != Info.Mtu) {
666     OLSR_PRINTF(1, "\tMTU change: %d -> %d.\n", (int)Int->int_mtu, Info.Mtu);
667
668     Int->int_mtu = Info.Mtu;
669
670     net_remove_buffer(Int);
671     net_add_buffer(Int);
672
673     Res = 1;
674   }
675
676   OldVal.v4 = ((struct sockaddr_in *)&Int->int_addr)->sin_addr;
677   NewVal.v4.s_addr = Info.Addr;
678
679 #ifdef DEBUG
680   OLSR_PRINTF(3, "\tAddress: %s\n", olsr_ip_to_string(&buf, &NewVal));
681 #endif
682
683   if (NewVal.v4.s_addr != OldVal.v4.s_addr) {
684     OLSR_PRINTF(1, "\tAddress change.\n");
685     OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
686     OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
687
688     Int->ip_addr.v4 = NewVal.v4;
689
690     AddrIn = (struct sockaddr_in *)&Int->int_addr;
691
692     AddrIn->sin_family = AF_INET;
693     AddrIn->sin_port = 0;
694     AddrIn->sin_addr = NewVal.v4;
695
696     if (olsr_cnf->main_addr.v4.s_addr == OldVal.v4.s_addr) {
697       OLSR_PRINTF(1, "\tMain address change.\n");
698
699       olsr_cnf->main_addr.v4 = NewVal.v4;
700     }
701
702     Res = 1;
703   }
704
705   else
706     OLSR_PRINTF(3, "\tNo address change.\n");
707
708   OldVal.v4 = ((struct sockaddr_in *)&Int->int_netmask)->sin_addr;
709   NewVal.v4.s_addr = Info.Mask;
710
711 #ifdef DEBUG
712   OLSR_PRINTF(3, "\tNetmask: %s\n", olsr_ip_to_string(&buf, &NewVal));
713 #endif
714
715   if (NewVal.v4.s_addr != OldVal.v4.s_addr) {
716     OLSR_PRINTF(1, "\tNetmask change.\n");
717     OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
718     OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
719
720     AddrIn = (struct sockaddr_in *)&Int->int_netmask;
721
722     AddrIn->sin_family = AF_INET;
723     AddrIn->sin_port = 0;
724     AddrIn->sin_addr = NewVal.v4;
725
726     Res = 1;
727   }
728
729   else
730     OLSR_PRINTF(3, "\tNo netmask change.\n");
731
732   OldVal.v4 = ((struct sockaddr_in *)&Int->int_broadaddr)->sin_addr;
733   NewVal.v4.s_addr = Info.Broad;
734
735 #ifdef DEBUG
736   OLSR_PRINTF(3, "\tBroadcast address: %s\n", olsr_ip_to_string(&buf, &NewVal));
737 #endif
738
739   if (NewVal.v4.s_addr != OldVal.v4.s_addr) {
740     OLSR_PRINTF(1, "\tBroadcast address change.\n");
741     OLSR_PRINTF(1, "\tOld: %s\n", olsr_ip_to_string(&buf, &OldVal));
742     OLSR_PRINTF(1, "\tNew: %s\n", olsr_ip_to_string(&buf, &NewVal));
743
744     AddrIn = (struct sockaddr_in *)&Int->int_broadaddr;
745
746     AddrIn->sin_family = AF_INET;
747     AddrIn->sin_port = 0;
748     AddrIn->sin_addr = NewVal.v4;
749
750     Res = 1;
751   }
752
753   else
754     OLSR_PRINTF(3, "\tNo broadcast address change.\n");
755
756   if (Res != 0)
757     olsr_trigger_ifchange(Int->if_index, Int, IFCHG_IF_UPDATE);
758
759   return Res;
760 }
761
762 int
763 chk_if_up(struct olsr_if *IntConf, int DebugLevel __attribute__ ((unused)))
764 {
765   struct ipaddr_str buf;
766   struct InterfaceInfo Info;
767   struct interface *New;
768   union olsr_ip_addr NullAddr;
769   int IsWlan;
770   struct sockaddr_in *AddrIn;
771   size_t name_size;
772
773   if (olsr_cnf->ip_version == AF_INET6) {
774     fprintf(stderr, "IPv6 not supported by chk_if_up()!\n");
775     return 0;
776   }
777
778   if (GetIntInfo(&Info, IntConf->name) < 0)
779     return 0;
780
781   New = olsr_malloc(sizeof(struct interface), "Interface 1");
782   /* initialize backpointer */
783   New->olsr_if = IntConf;
784
785
786   New->immediate_send_tc = (IntConf->cnf->tc_params.emission_interval < IntConf->cnf->hello_params.emission_interval);
787   if (olsr_cnf->max_jitter == 0) {
788     /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
789     olsr_cnf->max_jitter =
790       New->immediate_send_tc ? IntConf->cnf->tc_params.emission_interval : IntConf->cnf->hello_params.emission_interval;
791   }
792
793   New->gen_properties = NULL;
794
795   AddrIn = (struct sockaddr_in *)&New->int_addr;
796
797   AddrIn->sin_family = AF_INET;
798   AddrIn->sin_port = 0;
799   AddrIn->sin_addr.s_addr = Info.Addr;
800
801   AddrIn = (struct sockaddr_in *)&New->int_netmask;
802
803   AddrIn->sin_family = AF_INET;
804   AddrIn->sin_port = 0;
805   AddrIn->sin_addr.s_addr = Info.Mask;
806
807   AddrIn = (struct sockaddr_in *)&New->int_broadaddr;
808
809   AddrIn->sin_family = AF_INET;
810   AddrIn->sin_port = 0;
811   AddrIn->sin_addr.s_addr = Info.Broad;
812
813   if (IntConf->cnf->ipv4_multicast.v4.s_addr != 0)
814     AddrIn->sin_addr = IntConf->cnf->ipv4_multicast.v4;
815
816   New->int_flags = 0;
817
818   New->is_hcif = false;
819
820   New->int_mtu = Info.Mtu;
821
822   name_size = strlen(IntConf->name) + 1;
823   New->int_name = olsr_malloc(name_size, "Interface 2");
824   strscpy(New->int_name, IntConf->name, name_size);
825
826   IsWlan = IsWireless(IntConf->name);
827
828   if (IsWlan < 0)
829     IsWlan = 1;
830
831   New->is_wireless = IsWlan;
832
833   if (IntConf->cnf->weight.fixed)
834     New->int_metric = IntConf->cnf->weight.value;
835
836   else
837     New->int_metric = Info.Metric;
838
839   New->olsr_seqnum = random() & 0xffff;
840
841   New->ttl_index = -32;         /* For the first 32 TC's, fish-eye is disabled */
842
843   OLSR_PRINTF(1, "\tInterface %s set up for use with index %d\n\n", IntConf->name, New->if_index);
844
845   OLSR_PRINTF(1, "\tMTU: %d\n", New->int_mtu);
846   OLSR_PRINTF(1, "\tAddress: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr *)&New->int_addr));
847   OLSR_PRINTF(1, "\tNetmask: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr *)&New->int_netmask));
848   OLSR_PRINTF(1, "\tBroadcast address: %s\n", sockaddr4_to_string(&buf, (const struct sockaddr *)&New->int_broadaddr));
849
850   New->ip_addr.v4 = New->int_addr.sin_addr;
851
852   New->if_index = Info.Index;
853
854   OLSR_PRINTF(3, "\tKernel index: %08x\n", New->if_index);
855
856   New->olsr_socket = getsocket(BUFSPACE, New);
857   New->send_socket = getsocket(0, New);
858
859   if (New->olsr_socket < 0) {
860     fprintf(stderr, "Could not initialize socket... exiting!\n\n");
861     exit(1);
862   }
863
864   add_olsr_socket(New->olsr_socket, &olsr_input, NULL, NULL, SP_PR_READ);
865
866   New->int_next = ifnet;
867   ifnet = New;
868
869   IntConf->interf = New;
870   IntConf->configured = 1;
871
872   memset(&NullAddr, 0, olsr_cnf->ipsize);
873
874   if (ipequal(&NullAddr, &olsr_cnf->main_addr)) {
875     olsr_cnf->main_addr = New->ip_addr;
876     OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
877   }
878
879   net_add_buffer(New);
880
881   /*
882    * Register functions for periodic message generation
883    */
884   New->hello_gen_timer =
885     olsr_start_timer(IntConf->cnf->hello_params.emission_interval * MSEC_PER_SEC, HELLO_JITTER, OLSR_TIMER_PERIODIC,
886                      olsr_cnf->lq_level == 0 ? &generate_hello : &olsr_output_lq_hello, New, hello_gen_timer_cookie);
887   New->tc_gen_timer =
888     olsr_start_timer(IntConf->cnf->tc_params.emission_interval * MSEC_PER_SEC, TC_JITTER, OLSR_TIMER_PERIODIC,
889                      olsr_cnf->lq_level == 0 ? &generate_tc : &olsr_output_lq_tc, New, tc_gen_timer_cookie);
890   New->mid_gen_timer =
891     olsr_start_timer(IntConf->cnf->mid_params.emission_interval * MSEC_PER_SEC, MID_JITTER, OLSR_TIMER_PERIODIC, &generate_mid, New,
892                      mid_gen_timer_cookie);
893   New->hna_gen_timer =
894     olsr_start_timer(IntConf->cnf->hna_params.emission_interval * MSEC_PER_SEC, HNA_JITTER, OLSR_TIMER_PERIODIC, &generate_hna, New,
895                      hna_gen_timer_cookie);
896
897   if (olsr_cnf->max_tc_vtime < IntConf->cnf->tc_params.emission_interval)
898     olsr_cnf->max_tc_vtime = IntConf->cnf->tc_params.emission_interval;
899
900   New->hello_etime = (olsr_reltime) (IntConf->cnf->hello_params.emission_interval * MSEC_PER_SEC);
901   New->valtimes.hello = reltime_to_me(IntConf->cnf->hello_params.validity_time * MSEC_PER_SEC);
902   New->valtimes.tc = reltime_to_me(IntConf->cnf->tc_params.validity_time * MSEC_PER_SEC);
903   New->valtimes.mid = reltime_to_me(IntConf->cnf->mid_params.validity_time * MSEC_PER_SEC);
904   New->valtimes.hna = reltime_to_me(IntConf->cnf->hna_params.validity_time * MSEC_PER_SEC);
905
906   New->mode = IntConf->cnf->mode;
907
908   olsr_trigger_ifchange(New->if_index, New, IFCHG_IF_ADD);
909
910   return 1;
911 }
912
913 void
914 check_interface_updates(void *dummy __attribute__ ((unused)))
915 {
916   struct olsr_if *IntConf;
917
918 #ifdef DEBUG
919   OLSR_PRINTF(3, "Checking for updates in the interface set\n");
920 #endif
921
922   for (IntConf = olsr_cnf->interfaces; IntConf != NULL; IntConf = IntConf->next) {
923     if (IntConf->host_emul)
924       continue;
925
926     if (olsr_cnf->host_emul)    /* XXX: TEMPORARY! */
927       continue;
928
929     if (IntConf->configured)
930       chk_if_changed(IntConf);
931
932     else
933       chk_if_up(IntConf, 3);
934   }
935 }
936
937 /*
938  * Local Variables:
939  * c-basic-offset: 2
940  * indent-tabs-mode: nil
941  * End:
942  */