3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
43 #include "interfaces.h"
45 #include "scheduler.h"
51 #include "common/string.h"
52 #include "olsr_logging.h"
58 /* The interface list head */
59 struct list_node interface_head;
61 /* Ifchange functions */
63 ifchg_cb_func function;
67 static struct ifchgf *ifchgf_list = NULL;
70 /* Some cookies for stats keeping */
71 struct olsr_cookie_info *interface_mem_cookie = NULL;
72 struct olsr_cookie_info *interface_poll_timer_cookie = NULL;
73 struct olsr_cookie_info *hello_gen_timer_cookie = NULL;
74 struct olsr_cookie_info *tc_gen_timer_cookie = NULL;
75 struct olsr_cookie_info *mid_gen_timer_cookie = NULL;
76 struct olsr_cookie_info *hna_gen_timer_cookie = NULL;
77 struct olsr_cookie_info *buffer_hold_timer_cookie = NULL;
79 static void check_interface_updates(void *);
82 * Do initialization of various data needed for network interface management.
83 * This function also tries to set up the given interfaces.
85 * @return if more than zero interfaces were configured
90 struct olsr_if_config *tmp_if;
93 list_head_init(&interface_head);
96 * Get some cookies for getting stats to ease troubleshooting.
98 interface_mem_cookie =
99 olsr_alloc_cookie("Interface", OLSR_COOKIE_TYPE_MEMORY);
100 olsr_cookie_set_memory_size(interface_mem_cookie, sizeof(struct interface));
102 interface_poll_timer_cookie =
103 olsr_alloc_cookie("Interface Polling", OLSR_COOKIE_TYPE_TIMER);
104 buffer_hold_timer_cookie =
105 olsr_alloc_cookie("Buffer Hold", OLSR_COOKIE_TYPE_TIMER);
107 hello_gen_timer_cookie =
108 olsr_alloc_cookie("Hello Generation", OLSR_COOKIE_TYPE_TIMER);
109 tc_gen_timer_cookie =
110 olsr_alloc_cookie("TC Generation", OLSR_COOKIE_TYPE_TIMER);
111 mid_gen_timer_cookie =
112 olsr_alloc_cookie("MID Generation", OLSR_COOKIE_TYPE_TIMER);
113 hna_gen_timer_cookie =
114 olsr_alloc_cookie("HNA Generation", OLSR_COOKIE_TYPE_TIMER);
116 OLSR_INFO(LOG_NETWORKING, "\n ---- Interface configuration ---- \n\n");
118 /* Run trough all interfaces immediately */
119 for (tmp_if = olsr_cnf->if_configs; tmp_if != NULL; tmp_if = tmp_if->next) {
120 chk_if_up(tmp_if, 1);
123 /* Kick a periodic timer for the network interface update function */
124 olsr_start_timer(olsr_cnf->nic_chgs_pollrate * MSEC_PER_SEC, 5,
125 OLSR_TIMER_PERIODIC, &check_interface_updates, NULL,
126 interface_poll_timer_cookie->ci_id);
128 return (!list_is_empty(&interface_head));
132 * Callback function for periodic check of interface parameters.
135 check_interface_updates(void *foo __attribute__((unused)))
137 struct olsr_if_config *tmp_if;
139 OLSR_DEBUG(LOG_NETWORKING, "Checking for updates in the interface set\n");
141 for (tmp_if = olsr_cnf->if_configs; tmp_if != NULL; tmp_if = tmp_if->next) {
143 if (!tmp_if->cnf->autodetect_chg) {
144 /* Don't check this interface */
145 OLSR_DEBUG(LOG_NETWORKING, "Not checking interface %s\n", tmp_if->name);
149 if (tmp_if->interf) {
150 chk_if_changed(tmp_if);
152 chk_if_up(tmp_if, 3);
158 * Remove and cleanup a physical interface.
161 remove_interface(struct interface **pinterf)
163 struct interface *ifp = *pinterf;
164 struct ipaddr_str buf;
170 OLSR_INFO(LOG_NETWORKING, "Removing interface %s\n", ifp->int_name);
172 olsr_delete_link_entry_by_if(ifp);
175 * Call possible ifchange functions registered by plugins
177 run_ifchg_cbs(ifp, IFCHG_IF_REMOVE);
180 list_remove(&ifp->int_node);
182 /* Remove output buffer */
183 net_remove_buffer(ifp);
185 /* Check main addr */
186 if (!olsr_cnf->fixed_origaddr && olsr_ipequal(&olsr_cnf->router_id, &ifp->ip_addr)) {
187 if (list_is_empty(&interface_head)) {
188 /* No more interfaces */
189 memset(&olsr_cnf->router_id, 0, olsr_cnf->ipsize);
190 OLSR_INFO(LOG_NETWORKING, "Removed last interface. Cleared main address.\n");
193 /* Grab the first interface in the list. */
194 olsr_cnf->router_id = list2interface(interface_head.next)->ip_addr;
195 olsr_ip_to_string(&buf, &olsr_cnf->router_id);
196 OLSR_INFO(LOG_NETWORKING, "New main address: %s\n", buf.buf);
201 * Deregister functions for periodic message generation
203 olsr_stop_timer(ifp->hello_gen_timer);
204 olsr_stop_timer(ifp->tc_gen_timer);
205 olsr_stop_timer(ifp->mid_gen_timer);
206 olsr_stop_timer(ifp->hna_gen_timer);
209 * Stop interface pacing.
211 olsr_stop_timer(ifp->buffer_hold_timer);
214 * Unlink from config.
216 unlock_interface(*pinterf);
219 /* Close olsr socket */
220 remove_olsr_socket(ifp->olsr_socket, &olsr_input, NULL);
221 CLOSESOCKET(ifp->olsr_socket);
222 ifp->olsr_socket = -1;
224 unlock_interface(ifp);
226 if (list_is_empty(&interface_head) && !olsr_cnf->allow_no_interfaces) {
227 OLSR_ERROR(LOG_NETWORKING, "No more active interfaces - exiting.\n");
228 olsr_exit(EXIT_FAILURE);
233 run_ifchg_cbs(struct interface *ifp, int flag)
236 for (tmp = ifchgf_list; tmp != NULL; tmp = tmp->next) {
237 tmp->function(ifp, flag);
242 * Find the local interface with a given address.
244 * @param addr the address to check.
245 * @return the interface struct representing the interface
246 * that matched the address.
249 if_ifwithaddr(const union olsr_ip_addr *addr)
251 struct interface *ifp;
256 if (olsr_cnf->ip_version == AF_INET) {
259 OLSR_FOR_ALL_INTERFACES(ifp) {
260 if (ip4equal(&ifp->int_addr.sin_addr, &addr->v4)) {
263 } OLSR_FOR_ALL_INTERFACES_END(ifp);
268 OLSR_FOR_ALL_INTERFACES(ifp) {
269 if (ip6equal(&ifp->int6_addr.sin6_addr, &addr->v6)) {
272 } OLSR_FOR_ALL_INTERFACES_END(ifp);
278 * Find the interface with a given number.
280 * @param nr the number of the interface to find.
281 * @return return the interface struct representing the interface
282 * that matched the number.
285 if_ifwithsock(int fd)
287 struct interface *ifp;
289 OLSR_FOR_ALL_INTERFACES(ifp) {
290 if (ifp->olsr_socket == fd) {
293 } OLSR_FOR_ALL_INTERFACES_END(ifp);
300 * Find the interface with a given label.
302 * @param if_name the label of the interface to find.
303 * @return return the interface struct representing the interface
304 * that matched the label.
307 if_ifwithname(const char *if_name)
309 struct interface *ifp;
310 OLSR_FOR_ALL_INTERFACES(ifp) {
312 /* good ol' strcmp should be sufficient here */
313 if (strcmp(ifp->int_name, if_name) == 0) {
316 } OLSR_FOR_ALL_INTERFACES_END(ifp);
323 * Find the interface with a given interface index.
325 * @param iif_index of the interface to find.
326 * @return return the interface struct representing the interface
327 * that matched the iif_index.
330 if_ifwithindex(const int if_index)
332 struct interface *ifp;
333 OLSR_FOR_ALL_INTERFACES(ifp) {
334 if (ifp->if_index == if_index) {
337 } OLSR_FOR_ALL_INTERFACES_END(ifp);
345 * Get an interface name for a given interface index
347 * @param iif_index of the interface to find.
348 * @return "" or interface name.
351 if_ifwithindex_name(const int if_index)
353 const struct interface *const ifp = if_ifwithindex(if_index);
354 return ifp == NULL ? "void" : ifp->int_name;
362 lock_interface(struct interface *ifp)
370 * Unlock an interface and free it if the refcount went down to zero.
373 unlock_interface(struct interface *ifp)
375 /* Node must have a positive refcount balance */
376 assert(ifp->refcount);
378 if (--ifp->refcount) {
382 /* Node must be dequeued at this point */
383 assert(!list_node_on_list(&ifp->int_node));
387 olsr_cookie_free(interface_mem_cookie, ifp);
392 * Add an ifchange function. These functions are called on all (non-initial)
393 * changes in the interface set.
396 add_ifchgf(ifchg_cb_func f)
398 struct ifchgf *tmp = olsr_malloc(sizeof(struct ifchgf), "Add ifchgfunction");
401 tmp->next = ifchgf_list;
407 * Remove an ifchange function
410 del_ifchgf(ifchg_cb_func f)
412 struct ifchgf *tmp, *prev;
414 for (tmp = ifchgf_list, prev = NULL;
416 prev = tmp, tmp = tmp->next) {
417 if (tmp->function == f) {
420 ifchgf_list = tmp->next;
422 prev->next = tmp->next;
435 * indent-tabs-mode: nil