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