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