provide olsr_if pointer in interface
[olsrd.git] / src / interfaces.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
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 <signal.h>
43 #include <unistd.h>
44
45 #include "defs.h"
46 #include "interfaces.h"
47 #include "ifnet.h"
48 #include "scheduler.h"
49 #include "olsr.h"
50 #include "net_olsr.h"
51 #include "ipcalc.h"
52 #include "log.h"
53 #include "parser.h"
54 #include "socket_parser.h"
55
56 #ifdef WIN32
57 #include <winbase.h>
58 #define close(x) closesocket(x)
59 int __stdcall SignalHandler(unsigned long signo);
60
61 static unsigned long __stdcall
62 SignalHandlerWrapper(void *Dummy __attribute__ ((unused)))
63 {
64   SignalHandler(0);
65   return 0;
66 }
67
68 static void
69 CallSignalHandler(void)
70 {
71   unsigned long ThreadId;
72
73   CreateThread(NULL, 0, SignalHandlerWrapper, NULL, 0, &ThreadId);
74 }
75
76
77 #endif
78
79 /* The interface linked-list */
80 struct interface *ifnet;
81
82 /* Ifchange functions */
83 struct ifchgf {
84   int (*function) (struct interface *, int);
85   struct ifchgf *next;
86 };
87
88 static struct ifchgf *ifchgf_list;
89
90 /* Some cookies for stats keeping */
91 struct olsr_cookie_info *interface_poll_timer_cookie = NULL;
92 struct olsr_cookie_info *hello_gen_timer_cookie = NULL;
93 struct olsr_cookie_info *tc_gen_timer_cookie = NULL;
94 struct olsr_cookie_info *mid_gen_timer_cookie = NULL;
95 struct olsr_cookie_info *hna_gen_timer_cookie = NULL;
96
97 /**
98  *Do initialization of various data needed for
99  *network interface management.
100  *This function also tries to set up the given interfaces.
101  *
102  *@return the number of interfaces configured
103  */
104 int
105 olsr_init_interfacedb(void)
106 {
107   struct olsr_if *tmp_if;
108
109   /* Initial values */
110   ifnet = NULL;
111
112   /*
113    * Get some cookies for getting stats to ease troubleshooting.
114    */
115   interface_poll_timer_cookie = olsr_alloc_cookie("Interface Polling", OLSR_COOKIE_TYPE_TIMER);
116
117   hello_gen_timer_cookie = olsr_alloc_cookie("Hello Generation", OLSR_COOKIE_TYPE_TIMER);
118   tc_gen_timer_cookie = olsr_alloc_cookie("TC Generation", OLSR_COOKIE_TYPE_TIMER);
119   mid_gen_timer_cookie = olsr_alloc_cookie("MID Generation", OLSR_COOKIE_TYPE_TIMER);
120   hna_gen_timer_cookie = olsr_alloc_cookie("HNA Generation", OLSR_COOKIE_TYPE_TIMER);
121
122   OLSR_PRINTF(1, "\n ---- Interface configuration ---- \n\n");
123   /* Run trough all interfaces immedeatly */
124   for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) {
125     if (!tmp_if->host_emul) {
126       if (!olsr_cnf->host_emul) /* XXX: TEMPORARY! */
127         chk_if_up(tmp_if, 1);
128     } else {
129       add_hemu_if(tmp_if);
130     }
131   }
132
133   /* Kick a periodic timer for the network interface update function */
134   olsr_start_timer((unsigned int)olsr_cnf->nic_chgs_pollrate * MSEC_PER_SEC, 5, OLSR_TIMER_PERIODIC, &check_interface_updates, NULL,
135                    interface_poll_timer_cookie->ci_id);
136
137   return (ifnet == NULL) ? 0 : 1;
138 }
139
140 void
141 olsr_trigger_ifchange(struct interface *ifp, int flag)
142 {
143   struct ifchgf *tmp_ifchgf_list = ifchgf_list;
144
145   while (tmp_ifchgf_list != NULL) {
146     tmp_ifchgf_list->function(ifp, flag);
147     tmp_ifchgf_list = tmp_ifchgf_list->next;
148   }
149 }
150
151 /**
152  *Find the local interface with a given address.
153  *
154  *@param addr the address to check.
155  *
156  *@return the interface struct representing the interface
157  *that matched the address.
158  */
159
160 struct interface *
161 if_ifwithaddr(const union olsr_ip_addr *addr)
162 {
163   struct interface *ifp;
164
165   if (!addr)
166     return NULL;
167
168   for (ifp = ifnet; ifp; ifp = ifp->int_next) {
169     if (olsr_cnf->ip_version == AF_INET) {
170       /* IPv4 */
171       //printf("Checking: %s == ", inet_ntoa(((struct sockaddr_in *)&ifp->int_addr)->sin_addr));
172       //printf("%s\n", olsr_ip_to_string(addr));
173
174       if (((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr == addr->v4.s_addr)
175         return ifp;
176     } else {
177       /* IPv6 */
178       //printf("Checking %s ", olsr_ip_to_string((union olsr_ip_addr *)&ifp->int6_addr.sin6_addr));
179       //printf("== %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in6 *)addr)->sin6_addr));
180       if (ip6equal(&ifp->int6_addr.sin6_addr, &addr->v6))
181         return ifp;
182     }
183   }
184   return NULL;
185 }
186
187 /**
188  *Find the interface with a given number.
189  *
190  *@param nr the number of the interface to find.
191  *
192  *@return return the interface struct representing the interface
193  *that matched the number.
194  */
195 struct interface *
196 if_ifwithsock(int fd)
197 {
198   struct interface *ifp;
199   ifp = ifnet;
200
201   while (ifp) {
202     if (ifp->olsr_socket == fd || ifp->send_socket == fd)
203       return ifp;
204     ifp = ifp->int_next;
205   }
206
207   return NULL;
208 }
209
210 /**
211  *Find the interface with a given label.
212  *
213  *@param if_name the label of the interface to find.
214  *
215  *@return return the interface struct representing the interface
216  *that matched the label.
217  */
218 struct interface *
219 if_ifwithname(const char *if_name)
220 {
221   struct interface *ifp = ifnet;
222   while (ifp) {
223     /* good ol' strcmp should be sufficcient here */
224     if (strcmp(ifp->int_name, if_name) == 0) {
225       return ifp;
226     }
227     ifp = ifp->int_next;
228   }
229   return NULL;
230 }
231
232 /**
233  *Find the interface with a given interface index.
234  *
235  *@param iif_index of the interface to find.
236  *
237  *@return return the interface struct representing the interface
238  *that matched the iif_index.
239  */
240 struct interface *
241 if_ifwithindex(const int if_index)
242 {
243   struct interface *ifp = ifnet;
244   while (ifp != NULL) {
245     if (ifp->if_index == if_index) {
246       return ifp;
247     }
248     ifp = ifp->int_next;
249   }
250   return NULL;
251 }
252
253 /**
254  *Get an interface name for a given interface index
255  *
256  *@param iif_index of the interface to find.
257  *
258  *@return "" or interface name.
259  */
260 const char *
261 if_ifwithindex_name(const int if_index)
262 {
263   const struct interface *const ifp = if_ifwithindex(if_index);
264   return ifp == NULL ? "void" : ifp->int_name;
265 }
266
267 /**
268  *Create a new interf_name struct using a given
269  *name and insert it into the interface list.
270  *
271  *@param name the name of the interface.
272  *
273  *@return nada
274  */
275 struct olsr_if *
276 olsr_create_olsrif(const char *name, int hemu)
277 {
278   struct olsr_if *interf_n = olsr_cnf->interfaces;
279   size_t name_size;
280
281   //printf("Adding interface %s\n", name);
282
283   /* check if the inerfaces already exists */
284   while (interf_n != NULL) {
285     if (strcmp(interf_n->name, name) == 0) {
286       fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name);
287       return NULL;
288     }
289     interf_n = interf_n->next;
290   }
291
292   interf_n = olsr_malloc(sizeof(struct olsr_if), "queue interface");
293
294   name_size = strlen(name) + 1;
295   interf_n->name = olsr_malloc(name_size, "queue interface name");
296   strscpy(interf_n->name, name, name_size);
297
298   interf_n->cnf = olsr_malloc(sizeof(*interf_n->cnf), "queue cnf");
299
300   interf_n->cnfi = olsr_malloc(sizeof(*interf_n->cnfi), "queue cnfi");
301   memset(interf_n->cnfi, 0xFF, sizeof(*interf_n->cnfi));
302   interf_n->cnfi->orig_lq_mult_cnt=0;
303
304   interf_n->host_emul = hemu ? true : false;
305
306   interf_n->next = olsr_cnf->interfaces;
307   olsr_cnf->interfaces = interf_n;
308
309   return interf_n;
310 }
311
312 /**
313  *Add an ifchange function. These functions are called on all (non-initial)
314  *changes in the interface set.
315  *
316  *@param
317  *
318  *@return
319  */
320 int
321 olsr_add_ifchange_handler(int (*f) (struct interface *, int))
322 {
323
324   struct ifchgf *new_ifchgf;
325
326   new_ifchgf = olsr_malloc(sizeof(struct ifchgf), "Add ifchgfunction");
327
328   new_ifchgf->next = ifchgf_list;
329   new_ifchgf->function = f;
330
331   ifchgf_list = new_ifchgf;
332
333   return 1;
334 }
335
336 /*
337  * Remove an ifchange function
338  */
339 int
340 olsr_remove_ifchange_handler(int (*f) (struct interface *, int))
341 {
342   struct ifchgf *tmp_ifchgf, *prev;
343
344   tmp_ifchgf = ifchgf_list;
345   prev = NULL;
346
347   while (tmp_ifchgf) {
348     if (tmp_ifchgf->function == f) {
349       /* Remove entry */
350       if (prev == NULL) {
351         ifchgf_list = tmp_ifchgf->next;
352         free(tmp_ifchgf);
353       } else {
354         prev->next = tmp_ifchgf->next;
355         free(tmp_ifchgf);
356       }
357       return 1;
358     }
359     prev = tmp_ifchgf;
360     tmp_ifchgf = tmp_ifchgf->next;
361   }
362
363   return 0;
364 }
365
366 void
367 olsr_remove_interface(struct olsr_if * iface, bool went_down)
368 {
369   struct interface *ifp, *tmp_ifp;
370   struct rt_entry *rt;
371   ifp = iface->interf;
372
373   OLSR_PRINTF(1, "Removing interface %s\n", iface->name);
374   olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name);
375
376   olsr_delete_link_entry_by_ip(&ifp->ip_addr);
377
378   /*
379    *Call possible ifchange functions registered by plugins
380    */
381   olsr_trigger_ifchange(ifp, IFCHG_IF_REMOVE);
382
383   /*remove all routes*/
384   if (went_down) {
385     OLSR_FOR_ALL_RT_ENTRIES(rt) {
386       if (rt->rt_nexthop.iif_index == ifp->if_index) {
387         //marks route as unexisting in kernel, do this better !?
388         rt->rt_nexthop.iif_index=-1;
389       }
390     }
391     OLSR_FOR_ALL_RT_ENTRIES_END(rt);
392   }
393
394   /* Dequeue */
395   if (ifp == ifnet) {
396     ifnet = ifp->int_next;
397   } else {
398     tmp_ifp = ifnet;
399     while (tmp_ifp->int_next != ifp) {
400       tmp_ifp = tmp_ifp->int_next;
401     }
402     tmp_ifp->int_next = ifp->int_next;
403   }
404
405   /* Remove output buffer */
406   net_remove_buffer(ifp);
407
408   /* Check main addr */
409   /* deactivated to prevent change of originator IP */
410 #if 0
411   if (ipequal(&olsr_cnf->main_addr, &ifp->ip_addr)) {
412     if (ifnet == NULL) {
413       /* No more interfaces */
414       memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize);
415       OLSR_PRINTF(1, "No more interfaces...\n");
416     } else {
417       struct ipaddr_str buf;
418       olsr_cnf->main_addr = ifnet->ip_addr;
419       OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
420       olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
421     }
422   }
423 #endif
424   /*
425    * Deregister functions for periodic message generation
426    */
427   olsr_stop_timer(ifp->hello_gen_timer);
428   olsr_stop_timer(ifp->tc_gen_timer);
429   olsr_stop_timer(ifp->mid_gen_timer);
430   olsr_stop_timer(ifp->hna_gen_timer);
431
432   iface->configured = 0;
433   iface->interf = NULL;
434   /* Close olsr socket */
435   close(ifp->olsr_socket);
436   remove_olsr_socket(ifp->olsr_socket, &olsr_input);
437
438   /* Free memory */
439   free(ifp->int_name);
440   free(ifp);
441
442   if ((ifnet == NULL) && (!olsr_cnf->allow_no_interfaces)) {
443     OLSR_PRINTF(1, "No more active interfaces - exiting.\n");
444     olsr_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n");
445     olsr_cnf->exit_value = EXIT_FAILURE;
446 #ifndef WIN32
447     kill(getpid(), SIGINT);
448 #else
449     CallSignalHandler();
450 #endif
451   }
452 }
453
454 /*
455  * Local Variables:
456  * c-basic-offset: 2
457  * indent-tabs-mode: nil
458  * End:
459  */