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