ef465222de4a92110230e337200778b012c62601
[olsrd.git] / src / win32 / ifnet.c
1 /*
2  * Functions for the Windows port
3  * Copyright (C) 2004 Thomas Lopatic (thomas@lopatic.de)
4  *
5  * Derived from their Linux counterparts
6  * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
7  *
8  * This file is part of olsrd-unik.
9  *
10  * olsrd-unik is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * olsrd-unik is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with olsrd-unik; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  */
25
26 #include "../interfaces.h"
27 #include "../olsr.h"
28 #include "../net.h"
29 #include "../parser.h"
30 #include "../socket_parser.h"
31
32 #include <iphlpapi.h>
33 #include <iprtrmib.h>
34
35 void WinSockPError(char *);
36 char *StrError(unsigned int ErrNo);
37 int inet_pton(int af, char *src, void *dst);
38
39 #define MAX_INTERFACES 25
40
41 int __stdcall SignalHandler(unsigned long Signal);
42
43 static unsigned long __stdcall SignalHandlerWrapper(void *Dummy)
44 {
45   SignalHandler(0);
46   return 0;
47 }
48
49 static void CallSignalHandler(void)
50 {
51   unsigned long ThreadId;
52
53   CreateThread(NULL, 0, SignalHandlerWrapper, NULL, 0, &ThreadId);
54 }
55
56 static void MiniIndexToIntName(char *String, int MiniIndex)
57 {
58   char *HexDigits = "0123456789abcdef";
59
60   String[0] = 'i';
61   String[1] = 'f';
62
63   String[2] = HexDigits[(MiniIndex >> 4) & 15];
64   String[3] = HexDigits[MiniIndex & 15];
65
66   String[4] = 0;
67 }
68
69 static int IntNameToMiniIndex(int *MiniIndex, char *String)
70 {
71   char *HexDigits = "0123456789abcdef";
72   int i, k;
73   char ch;
74
75   if (String[0] != 'i' || String[1] != 'f')
76     return -1;
77
78   *MiniIndex = 0;
79
80   for (i = 2; i < 4; i++)
81   {
82     ch = String[i];
83
84     if (ch >= 'A' && ch <= 'F')
85       ch += 32;
86
87     for (k = 0; k < 16 && ch != HexDigits[k]; k++);
88
89     if (k == 16)
90       return -1;
91
92     *MiniIndex = (*MiniIndex << 4) | k;
93   }
94
95   return 0;
96 }
97
98 static int AddrToIndex(int *Index, unsigned int Addr)
99 {
100   unsigned int IntAddr;
101   IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
102   unsigned long AdInfoLen;
103   IP_ADDR_STRING *Walker2;
104   unsigned long Res;
105   
106   olsr_printf(5, "AddrToIndex(%08x)\n", Addr);
107
108   if (ipversion == AF_INET6)
109   {
110     fprintf(stderr, "IPv6 not supported by AddrToIndex()!\n");
111     return -1;
112   }
113
114   AdInfoLen = sizeof (AdInfo);
115
116   Res = GetAdaptersInfo(AdInfo, &AdInfoLen);
117
118   if (Res != NO_ERROR)
119   {
120     fprintf(stderr, "GetAdaptersInfo() = %08lx, %s", Res, StrError(Res));
121     return -1;
122   }
123
124   for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next)
125   {
126     olsr_printf(5, "Index = %08x\n", Walker->Index);
127
128     for (Walker2 = &Walker->IpAddressList; Walker2 != NULL;
129          Walker2 = Walker2->Next)
130     {
131       inet_pton(AF_INET, Walker2->IpAddress.String, &IntAddr);
132
133       olsr_printf(5, "\tIP address = %08x\n", IntAddr);
134
135       if (Addr == IntAddr)
136       {
137         olsr_printf(5, "Found interface.\n");
138         *Index = Walker->Index;
139         return 0;
140       }
141     }
142   }
143
144   olsr_printf(5, "Cannot map IP address %08x to an adapter index.\n", Addr);
145   return -1;
146 }
147
148 void ListInterfaces(void)
149 {
150   IP_ADAPTER_INFO AdInfo[MAX_INTERFACES], *Walker;
151   unsigned long AdInfoLen;
152   char IntName[5];
153   IP_ADDR_STRING *Walker2;
154   unsigned long Res;
155   
156   if (ipversion == AF_INET6)
157   {
158     fprintf(stderr, "IPv6 not supported by ListInterfaces()!\n");
159     return;
160   }
161
162   AdInfoLen = sizeof (AdInfo);
163
164   Res = GetAdaptersInfo(AdInfo, &AdInfoLen);
165
166   if (Res == ERROR_NO_DATA)
167   {
168     printf("No interfaces detected.\n");
169     return;
170   }
171   
172   if (Res != NO_ERROR)
173   {
174     fprintf(stderr, "GetAdaptersInfo() = %08lx, %s", Res, StrError(Res));
175     return;
176   }
177
178   for (Walker = AdInfo; Walker != NULL; Walker = Walker->Next)
179   {
180     olsr_printf(5, "Index = %08x\n", Walker->Index);
181
182     MiniIndexToIntName(IntName, Walker->Index);
183
184     printf("%s:", IntName);
185
186     for (Walker2 = &Walker->IpAddressList; Walker2 != NULL;
187          Walker2 = Walker2->Next)
188       printf(" %s", Walker2->IpAddress.String);
189
190     printf("\n");
191   }
192 }
193
194 int InterfaceInfo(INTERFACE_INFO *IntPara, int *Index, struct if_name *IntName)
195 {
196   int MiniIndex;
197   int Sock;
198   INTERFACE_INFO IntInfo[25];
199   long Num;
200   int WsIdx;
201   int CandIndex;
202
203   if (IntNameToMiniIndex(&MiniIndex, IntName->name) < 0)
204   {
205     fprintf(stderr, "No such interface: %s!\n", IntName->name);
206     return -1;
207   }
208
209   Sock = socket(ipversion, SOCK_STREAM, IPPROTO_TCP);
210
211   if (Sock < 0)
212   {
213     WinSockPError("socket()");
214     return -1;
215   }
216
217   if (WSAIoctl(Sock, SIO_GET_INTERFACE_LIST, NULL, 0,
218                IntInfo, sizeof (IntInfo), &Num, NULL, NULL) < 0)
219   {
220     WinSockPError("WSAIoctl(SIO_GET_INTERFACE_LIST)");
221     closesocket(Sock);
222     return -1;
223   }
224
225   closesocket(Sock);
226
227   Num /= sizeof (INTERFACE_INFO);
228
229   olsr_printf(5, "%s:\n", IntName->name);
230
231   for (WsIdx = 0; WsIdx < Num; WsIdx++)
232   {
233     if (AddrToIndex(&CandIndex,
234                     IntInfo[WsIdx].iiAddress.AddressIn.sin_addr.s_addr) < 0)
235       continue;
236
237     if ((CandIndex & 255) == MiniIndex)
238       break;
239   }
240
241   if (WsIdx == Num)
242   {
243     fprintf(stderr, "No such interface: %s!\n", IntName->name);
244     return -1;
245   }
246     
247   *Index = CandIndex;
248
249   olsr_printf(5, "\tIndex: %08x\n", *Index);
250
251   olsr_printf(5, "\tFlags: %08x\n", IntInfo[WsIdx].iiFlags);
252
253   if ((IntInfo[WsIdx].iiFlags & IFF_UP) == 0)
254   {
255     olsr_printf(1, "\tInterface not up - skipping it...\n");
256     return -1;
257   }
258
259   if (ipversion == AF_INET && (IntInfo[WsIdx].iiFlags & IFF_BROADCAST) == 0)
260   {
261     olsr_printf(1, "\tNo broadcast - skipping it...\n");
262     return -1;
263   }
264
265   if ((IntInfo[WsIdx].iiFlags & IFF_LOOPBACK) != 0)
266   {
267     olsr_printf(1, "\tThis is a loopback interface - skipping it...\n");
268     return -1;
269   }
270
271   // Windows seems to always return 255.255.255.255 as broadcast
272   // address, so I've tried using (address | ~netmask).
273
274   {
275     struct sockaddr_in *sin_a, *sin_n, *sin_b;
276     unsigned int a, n, b;
277
278     sin_a = (struct sockaddr_in *)&IntInfo[WsIdx].iiAddress;
279     sin_n = (struct sockaddr_in *)&IntInfo[WsIdx].iiNetmask;
280     sin_b = (struct sockaddr_in *)&IntInfo[WsIdx].iiBroadcastAddress;
281
282     a = sin_a->sin_addr.s_addr;
283     n = sin_n->sin_addr.s_addr;
284     b = sin_b->sin_addr.s_addr =
285       sin_a->sin_addr.s_addr | ~sin_n->sin_addr.s_addr;
286   }
287
288   memcpy(IntPara, &IntInfo[WsIdx], sizeof (INTERFACE_INFO));
289   return 0;
290 }
291
292 void RemoveInterface(struct if_name *IntName)
293 {
294   struct interface *Int, *Prev;
295   struct ifchgf *Walker;
296
297   olsr_printf(1, "Removing interface %s.\n", IntName->name);
298   
299   Int = IntName->interf;
300
301   for (Walker = ifchgf_list; Walker != NULL; Walker = Walker->next)
302     Walker->function(Int, IFCHG_IF_REMOVE);
303
304   if (Int == ifnet)
305     ifnet = Int->int_next;
306
307   else
308   {
309     for (Prev = ifnet; Prev->int_next != Int; Prev = Prev->int_next);
310
311     Prev->int_next = Int->int_next;
312   }
313
314   if(COMP_IP(&main_addr, &Int->ip_addr))
315   {
316     if(ifnet == NULL)
317     {
318       memset(&main_addr, 0, ipsize);
319       olsr_printf(1, "Removed last interface. Cleared main address.\n");
320     }
321
322     else
323     {
324       COPY_IP(&main_addr, &ifnet->ip_addr);
325       olsr_printf(1, "New main address: %s.\n", olsr_ip_to_string(&main_addr));
326     }
327   }
328
329   nbinterf--;
330
331   IntName->configured = 0;
332   IntName->interf = NULL;
333
334   closesocket(Int->olsr_socket);
335   remove_olsr_socket(Int->olsr_socket, &olsr_input);
336
337   free(Int->int_name);
338   free(Int);
339
340   if(nbinterf == 0 && !allow_no_int)
341   {
342     olsr_printf(1, "No more active interfaces - exiting.\n");
343     exit_value = EXIT_FAILURE;
344     CallSignalHandler();
345   }
346 }
347
348 int chk_if_changed(struct if_name *IntName)
349 {
350   struct interface *Int;
351   INTERFACE_INFO IntInfo;
352   int Index;
353   int Res;
354   union olsr_ip_addr OldVal, NewVal;
355   struct ifchgf *Walker;
356
357   if (ipversion == AF_INET6)
358   {
359     fprintf(stderr, "IPv6 not supported by chk_if_changed()!\n");
360     return 0;
361   }
362
363 #ifdef DEBUG
364   olsr_printf(3, "Checking if %s is set down or changed\n", IntName->name);
365 #endif
366
367   Int = IntName->interf;
368
369   if (InterfaceInfo(&IntInfo, &Index, IntName) < 0)
370   {
371     RemoveInterface(IntName);
372     return 1;
373   }
374
375   Res = 0;
376
377   OldVal.v4 = ((struct sockaddr_in *)&Int->int_addr)->sin_addr.s_addr;
378   NewVal.v4 = ((struct sockaddr_in *)&IntInfo.iiAddress)->sin_addr.s_addr;
379
380 #ifdef DEBUG
381   olsr_printf(3, "\tAddress: %s\n", olsr_ip_to_string(&NewVal));
382 #endif
383
384   if(NewVal.v4 != OldVal.v4)
385   {
386     olsr_printf(1, "\tAddress change.\n");
387     olsr_printf(1, "\tOld: %s\n", olsr_ip_to_string(&OldVal));
388     olsr_printf(1, "\tNew: %s\n", olsr_ip_to_string(&NewVal));
389
390     Int->ip_addr.v4 = NewVal.v4;
391
392     memcpy(&Int->int_addr, &IntInfo.iiAddress, sizeof (struct sockaddr_in));
393
394     if (main_addr.v4 == OldVal.v4)
395     {
396       olsr_printf(1, "\tMain address change.\n");
397
398       main_addr.v4 = NewVal.v4;
399     }
400
401     Res = 1;
402   }
403
404   else
405     olsr_printf(3, "\tNo address change.\n");
406
407   OldVal.v4 = ((struct sockaddr_in *)&Int->int_netmask)->sin_addr.s_addr;
408   NewVal.v4 = ((struct sockaddr_in *)&IntInfo.iiNetmask)->sin_addr.s_addr;
409
410 #ifdef DEBUG
411   olsr_printf(3, "\tNetmask: %s\n", olsr_ip_to_string(&NewVal));
412 #endif
413
414   if(NewVal.v4 != OldVal.v4)
415   {
416     olsr_printf(1, "\tNetmask change.\n");
417     olsr_printf(1, "\tOld: %s\n", olsr_ip_to_string(&OldVal));
418     olsr_printf(1, "\tNew: %s\n", olsr_ip_to_string(&NewVal));
419
420     memcpy(&Int->int_netmask, &IntInfo.iiNetmask, sizeof (struct sockaddr_in));
421
422     Res = 1;
423   }
424
425   else
426     olsr_printf(3, "\tNo netmask change.\n");
427
428   OldVal.v4 = ((struct sockaddr_in *)&Int->int_broadaddr)->sin_addr.s_addr;
429   NewVal.v4 =
430     ((struct sockaddr_in *)&IntInfo.iiBroadcastAddress)->sin_addr.s_addr;
431
432 #ifdef DEBUG
433   olsr_printf(3, "\tBroadcast address: %s\n", olsr_ip_to_string(&NewVal));
434 #endif
435
436   if(NewVal.v4 != OldVal.v4)
437   {
438     olsr_printf(1, "\tBroadcast address change.\n");
439     olsr_printf(1, "\tOld: %s\n", olsr_ip_to_string(&OldVal));
440     olsr_printf(1, "\tNew: %s\n", olsr_ip_to_string(&NewVal));
441
442     memcpy(&Int->int_broadaddr, &IntInfo.iiBroadcastAddress,
443            sizeof (struct sockaddr_in));
444
445     Res = 1;
446   }
447
448   else
449     olsr_printf(3, "\tNo broadcast address change.\n");
450
451   if (Res != 0)
452     for (Walker = ifchgf_list; Walker != NULL; Walker = Walker->next)
453       Walker->function(Int, IFCHG_IF_UPDATE);
454
455   return Res;
456 }
457
458 int chk_if_up(struct if_name *IntName, int DebugLevel)
459 {
460   struct interface *New;
461   union olsr_ip_addr NullAddr;
462   INTERFACE_INFO IntInfo;
463   int Index;
464   unsigned int AddrSockAddr;
465   struct ifchgf *Walker;
466   
467   if (ipversion == AF_INET6)
468   {
469     fprintf(stderr, "IPv6 not supported by chk_if_up()!\n");
470     return 0;
471   }
472
473   if (InterfaceInfo(&IntInfo, &Index, IntName) < 0)
474     return 0;
475
476   New = olsr_malloc(sizeof (struct interface), "Interface 1");
477       
478   memcpy(&New->int_addr, &IntInfo.iiAddress, sizeof (struct sockaddr_in));
479
480   memcpy(&New->int_netmask, &IntInfo.iiNetmask, sizeof (struct sockaddr_in));
481
482   memcpy(&New->int_broadaddr, &IntInfo.iiBroadcastAddress,
483          sizeof (struct sockaddr_in));
484
485   New->int_metric = 1;
486   New->int_flags = IntInfo.iiFlags;
487
488   New->int_name = olsr_malloc(strlen (IntName->name) + 1, "Interface 2");
489   strcpy(New->int_name, IntName->name);
490
491   New->if_nr = IntName->index;
492   New->is_wireless = 1;
493   New->olsr_seqnum = random() & 0xffff;
494     
495   olsr_printf(1, "\tInterface %s set up for use with index %d\n\n",
496               IntName->name, New->if_nr);
497       
498   olsr_printf(1, "\tAddress: %s\n", sockaddr_to_string(&New->int_addr));
499   olsr_printf(1, "\tNetmask: %s\n", sockaddr_to_string(&New->int_netmask));
500   olsr_printf(1, "\tBroadcast address: %s\n",
501               sockaddr_to_string(&New->int_broadaddr));
502
503   New->ip_addr.v4 =
504     ((struct sockaddr_in *)&New->int_addr)->sin_addr.s_addr;
505       
506   New->if_index = Index;
507
508   olsr_printf(3, "\tKernel index: %08x\n", New->if_index);
509
510   AddrSockAddr = addrsock.sin_addr.s_addr;
511   addrsock.sin_addr.s_addr = New->ip_addr.v4;
512
513   New->olsr_socket = getsocket((struct sockaddr *)&addrsock,
514                                bufspace, New->int_name);
515       
516   addrsock.sin_addr.s_addr = AddrSockAddr;
517
518   if (New->olsr_socket < 0)
519   {
520     fprintf(stderr, "Could not initialize socket... exiting!\n\n");
521     exit(1);
522   }
523
524   add_olsr_socket(New->olsr_socket, &olsr_input);
525
526   New->int_next = ifnet;
527   ifnet = New;
528
529   IntName->interf = New;
530   IntName->configured = 1;
531
532   nbinterf++;
533
534   memset(&NullAddr, 0, ipsize);
535   
536   if(COMP_IP(&NullAddr, &main_addr))
537   {
538     COPY_IP(&main_addr, &New->ip_addr);
539
540     olsr_printf(1, "New main address: %s\n", olsr_ip_to_string(&main_addr));
541   }
542
543   for (Walker = ifchgf_list; Walker != NULL; Walker = Walker->next)
544     Walker->function(New, IFCHG_IF_ADD);
545
546   return 1;
547 }
548
549 void check_interface_updates()
550 {
551   struct if_name *tmp_if;
552
553 #ifdef DEBUG
554   olsr_printf(3, "Checking for updates in the interface set\n");
555 #endif
556
557   for(tmp_if = if_names; tmp_if != NULL; tmp_if = tmp_if->next)
558   {
559     if(tmp_if->configured)    
560       chk_if_changed(tmp_if);
561
562     else
563       chk_if_up(tmp_if, 3);
564   }
565 }