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