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"
57 /* The interface list head */
58 struct list_node interface_head;
60 /* Ifchange functions */
62 ifchg_cb_func function;
66 static struct ifchgf *ifchgf_list = NULL;
69 /* Some cookies for stats keeping */
70 struct olsr_cookie_info *interface_mem_cookie = NULL;
71 struct olsr_cookie_info *interface_poll_timer_cookie = NULL;
72 struct olsr_cookie_info *hello_gen_timer_cookie = NULL;
73 struct olsr_cookie_info *tc_gen_timer_cookie = NULL;
74 struct olsr_cookie_info *mid_gen_timer_cookie = NULL;
75 struct olsr_cookie_info *hna_gen_timer_cookie = NULL;
76 struct olsr_cookie_info *buffer_hold_timer_cookie = NULL;
78 static void check_interface_updates(void *);
81 * Do initialization of various data needed for network interface management.
82 * This function also tries to set up the given interfaces.
84 * @return if more than zero interfaces were configured
89 struct olsr_if_config *tmp_if;
92 list_head_init(&interface_head);
95 * Get some cookies for getting stats to ease troubleshooting.
97 interface_mem_cookie =
98 olsr_alloc_cookie("Interface", OLSR_COOKIE_TYPE_MEMORY);
99 olsr_cookie_set_memory_size(interface_mem_cookie, sizeof(struct interface));
101 interface_poll_timer_cookie =
102 olsr_alloc_cookie("Interface Polling", OLSR_COOKIE_TYPE_TIMER);
103 buffer_hold_timer_cookie =
104 olsr_alloc_cookie("Buffer Hold", OLSR_COOKIE_TYPE_TIMER);
106 hello_gen_timer_cookie =
107 olsr_alloc_cookie("Hello Generation", OLSR_COOKIE_TYPE_TIMER);
108 tc_gen_timer_cookie =
109 olsr_alloc_cookie("TC Generation", OLSR_COOKIE_TYPE_TIMER);
110 mid_gen_timer_cookie =
111 olsr_alloc_cookie("MID Generation", OLSR_COOKIE_TYPE_TIMER);
112 hna_gen_timer_cookie =
113 olsr_alloc_cookie("HNA Generation", OLSR_COOKIE_TYPE_TIMER);
115 OLSR_PRINTF(1, "\n ---- Interface configuration ---- \n\n");
117 /* Run trough all interfaces immediately */
118 for (tmp_if = olsr_cnf->if_configs; tmp_if != NULL; tmp_if = tmp_if->next) {
119 chk_if_up(tmp_if, 1);
122 /* Kick a periodic timer for the network interface update function */
123 olsr_start_timer(olsr_cnf->nic_chgs_pollrate * MSEC_PER_SEC, 5,
124 OLSR_TIMER_PERIODIC, &check_interface_updates, NULL,
125 interface_poll_timer_cookie->ci_id);
127 return (!list_is_empty(&interface_head));
131 * Callback function for periodic check of interface parameters.
134 check_interface_updates(void *foo __attribute__((unused)))
136 struct olsr_if_config *tmp_if;
139 OLSR_PRINTF(3, "Checking for updates in the interface set\n");
142 for (tmp_if = olsr_cnf->if_configs; tmp_if != NULL; tmp_if = tmp_if->next) {
144 if (!tmp_if->cnf->autodetect_chg) {
146 /* Don't check this interface */
147 OLSR_PRINTF(3, "Not checking interface %s\n", tmp_if->name);
152 if (tmp_if->interf) {
153 chk_if_changed(tmp_if);
155 chk_if_up(tmp_if, 3);
161 * Remove and cleanup a physical interface.
164 remove_interface(struct interface **pinterf)
166 struct interface *ifp = *pinterf;
167 struct ipaddr_str buf;
173 OLSR_INFO(LOG_NETWORKING, "Removing interface %s\n", ifp->int_name);
175 olsr_delete_link_entry_by_if(ifp);
178 * Call possible ifchange functions registered by plugins
180 run_ifchg_cbs(ifp, IFCHG_IF_REMOVE);
183 list_remove(&ifp->int_node);
185 /* Remove output buffer */
186 net_remove_buffer(ifp);
188 /* Check main addr */
189 if (!olsr_cnf->fixed_origaddr && olsr_ipequal(&olsr_cnf->router_id, &ifp->ip_addr)) {
190 if (list_is_empty(&interface_head)) {
191 /* No more interfaces */
192 memset(&olsr_cnf->router_id, 0, olsr_cnf->ipsize);
193 OLSR_PRINTF(1, "Removed last interface. Cleared main address.\n");
196 /* Grab the first interface in the list. */
197 olsr_cnf->router_id = list2interface(interface_head.next)->ip_addr;
198 olsr_ip_to_string(&buf, &olsr_cnf->router_id);
199 OLSR_INFO(LOG_NETWORKING, "New main address: %s\n", buf.buf);
204 * Deregister functions for periodic message generation
206 olsr_stop_timer(ifp->hello_gen_timer);
207 olsr_stop_timer(ifp->tc_gen_timer);
208 olsr_stop_timer(ifp->mid_gen_timer);
209 olsr_stop_timer(ifp->hna_gen_timer);
212 * Stop interface pacing.
214 olsr_stop_timer(ifp->buffer_hold_timer);
217 * Unlink from config.
219 unlock_interface(*pinterf);
222 /* Close olsr socket */
223 remove_olsr_socket(ifp->olsr_socket, &olsr_input, NULL);
224 CLOSESOCKET(ifp->olsr_socket);
225 ifp->olsr_socket = -1;
227 unlock_interface(ifp);
229 if (list_is_empty(&interface_head) && !olsr_cnf->allow_no_interfaces) {
230 OLSR_ERROR(LOG_NETWORKING, "No more active interfaces - exiting.\n");
231 olsr_exit(EXIT_FAILURE);
236 run_ifchg_cbs(struct interface *ifp, int flag)
239 for (tmp = ifchgf_list; tmp != NULL; tmp = tmp->next) {
240 tmp->function(ifp, flag);
245 * Find the local interface with a given address.
247 * @param addr the address to check.
248 * @return the interface struct representing the interface
249 * that matched the address.
252 if_ifwithaddr(const union olsr_ip_addr *addr)
254 struct interface *ifp;
259 if (olsr_cnf->ip_version == AF_INET) {
262 OLSR_FOR_ALL_INTERFACES(ifp) {
263 if (ip4equal(&ifp->int_addr.sin_addr, &addr->v4)) {
266 } OLSR_FOR_ALL_INTERFACES_END(ifp);
271 OLSR_FOR_ALL_INTERFACES(ifp) {
272 if (ip6equal(&ifp->int6_addr.sin6_addr, &addr->v6)) {
275 } OLSR_FOR_ALL_INTERFACES_END(ifp);
281 * Find the interface with a given number.
283 * @param nr the number of the interface to find.
284 * @return return the interface struct representing the interface
285 * that matched the number.
288 if_ifwithsock(int fd)
290 struct interface *ifp;
292 OLSR_FOR_ALL_INTERFACES(ifp) {
293 if (ifp->olsr_socket == fd) {
296 } OLSR_FOR_ALL_INTERFACES_END(ifp);
303 * Find the interface with a given label.
305 * @param if_name the label of the interface to find.
306 * @return return the interface struct representing the interface
307 * that matched the label.
310 if_ifwithname(const char *if_name)
312 struct interface *ifp;
313 OLSR_FOR_ALL_INTERFACES(ifp) {
315 /* good ol' strcmp should be sufficient here */
316 if (strcmp(ifp->int_name, if_name) == 0) {
319 } OLSR_FOR_ALL_INTERFACES_END(ifp);
326 * Find the interface with a given interface index.
328 * @param iif_index of the interface to find.
329 * @return return the interface struct representing the interface
330 * that matched the iif_index.
333 if_ifwithindex(const int if_index)
335 struct interface *ifp;
336 OLSR_FOR_ALL_INTERFACES(ifp) {
337 if (ifp->if_index == if_index) {
340 } OLSR_FOR_ALL_INTERFACES_END(ifp);
348 * Get an interface name for a given interface index
350 * @param iif_index of the interface to find.
351 * @return "" or interface name.
354 if_ifwithindex_name(const int if_index)
356 const struct interface *const ifp = if_ifwithindex(if_index);
357 return ifp == NULL ? "void" : ifp->int_name;
365 lock_interface(struct interface *ifp)
373 * Unlock an interface and free it if the refcount went down to zero.
376 unlock_interface(struct interface *ifp)
378 /* Node must have a positive refcount balance */
379 assert(ifp->refcount);
381 if (--ifp->refcount) {
385 /* Node must be dequeued at this point */
386 assert(!list_node_on_list(&ifp->int_node));
390 olsr_cookie_free(interface_mem_cookie, ifp);
395 * Add an ifchange function. These functions are called on all (non-initial)
396 * changes in the interface set.
399 add_ifchgf(ifchg_cb_func f)
401 struct ifchgf *tmp = olsr_malloc(sizeof(struct ifchgf), "Add ifchgfunction");
404 tmp->next = ifchgf_list;
410 * Remove an ifchange function
413 del_ifchgf(ifchg_cb_func f)
415 struct ifchgf *tmp, *prev;
417 for (tmp = ifchgf_list, prev = NULL;
419 prev = tmp, tmp = tmp->next) {
420 if (tmp->function == f) {
423 ifchgf_list = tmp->next;
425 prev->next = tmp->next;
438 * indent-tabs-mode: nil