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