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