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