X-Git-Url: http://olsr.org/git/?p=olsrd.git;a=blobdiff_plain;f=src%2Finterfaces.c;h=d5c855c55620d347abdaf03f5869159bbb46d832;hp=9b6c86272e6cbf9f9c82f1a9e602d112ba889db5;hb=b8eb53fb729164d674a31d7cfcad60c6424b4d5b;hpb=414071c3f5478a8682dd1001b50668daeb8e94d8 diff --git a/src/interfaces.c b/src/interfaces.c index 9b6c8627..d5c855c5 100644 --- a/src/interfaces.c +++ b/src/interfaces.c @@ -1,33 +1,80 @@ + /* - * OLSR ad-hoc routing table management protocol - * Copyright (C) 2003 Andreas Tønnesen (andreto@ifi.uio.no) + * The olsr.org Optimized Link-State Routing daemon(olsrd) + * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * This file is part of the olsr.org OLSR daemon. + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of olsr.org, olsrd nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * olsr.org is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. * - * olsr.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Visit http://www.olsr.org for more information. * - * You should have received a copy of the GNU General Public License - * along with olsr.org; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * $Id: interfaces.c,v 1.10 2004/11/01 20:13:27 kattemat Exp $ + * If you find this software useful feel free to make a donation + * to the project. For more information see the website or contact + * the copyright holders. * */ +#include +#include + #include "defs.h" #include "interfaces.h" #include "ifnet.h" #include "scheduler.h" -#include "main.h" +#include "olsr.h" +#include "net_olsr.h" +#include "ipcalc.h" +#include "log.h" +#include "parser.h" +#include "socket_parser.h" + +#ifdef WIN32 +#include +#define close(x) closesocket(x) +#endif + +/* The interface linked-list */ +struct interface *ifnet; + +/* Ifchange functions */ +struct ifchgf { + int (*function) (struct interface *, enum olsr_ifchg_flag); + struct ifchgf *next; +}; + +static struct ifchgf *ifchgf_list; + +/* Some cookies for stats keeping */ +struct olsr_cookie_info *interface_poll_timer_cookie = NULL; +struct olsr_cookie_info *hello_gen_timer_cookie = NULL; +struct olsr_cookie_info *tc_gen_timer_cookie = NULL; +struct olsr_cookie_info *mid_gen_timer_cookie = NULL; +struct olsr_cookie_info *hna_gen_timer_cookie = NULL; /** *Do initialization of various data needed for @@ -37,49 +84,51 @@ *@return the number of interfaces configured */ int -ifinit() +olsr_init_interfacedb(void) { struct olsr_if *tmp_if; - /* Initial values */ ifnet = NULL; /* - *Initializing addrsock struct to be - *used on all the sockets + * Get some cookies for getting stats to ease troubleshooting. */ - if(olsr_cnf->ip_version == AF_INET) - { - /* IP version 4 */ - memset(&addrsock, 0, sizeof (addrsock)); - addrsock.sin_family = AF_INET; - addrsock.sin_port = olsr_udp_port; - (addrsock.sin_addr).s_addr = INADDR_ANY; - } - else - { - /* IP version 6 */ - memset(&addrsock6, 0, sizeof (addrsock6)); - addrsock6.sin6_family = AF_INET6; - addrsock6.sin6_port = olsr_udp_port; - //(addrsock6.sin6_addr).s_addr = IN6ADDR_ANY_INIT; - } + interface_poll_timer_cookie = olsr_alloc_cookie("Interface Polling", OLSR_COOKIE_TYPE_TIMER); + + hello_gen_timer_cookie = olsr_alloc_cookie("Hello Generation", OLSR_COOKIE_TYPE_TIMER); + tc_gen_timer_cookie = olsr_alloc_cookie("TC Generation", OLSR_COOKIE_TYPE_TIMER); + mid_gen_timer_cookie = olsr_alloc_cookie("MID Generation", OLSR_COOKIE_TYPE_TIMER); + hna_gen_timer_cookie = olsr_alloc_cookie("HNA Generation", OLSR_COOKIE_TYPE_TIMER); - olsr_printf(1, "\n ---- Interface configuration ---- \n\n"); + OLSR_PRINTF(1, "\n ---- Interface configuration ---- \n\n"); /* Run trough all interfaces immedeatly */ - for(tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) - { - chk_if_up(tmp_if, 1); + for (tmp_if = olsr_cnf->interfaces; tmp_if != NULL; tmp_if = tmp_if->next) { + if (!tmp_if->host_emul) { + if (!olsr_cnf->host_emul) /* XXX: TEMPORARY! */ + chk_if_up(tmp_if, 1); + } else { + add_hemu_if(tmp_if); } - - /* register network interface update function with scheduler */ - olsr_register_scheduler_event(&check_interface_updates, NULL, 5.0, 0, NULL); + } + + /* Kick a periodic timer for the network interface update function */ + olsr_start_timer((unsigned int)olsr_cnf->nic_chgs_pollrate * MSEC_PER_SEC, 5, OLSR_TIMER_PERIODIC, &check_interface_updates, NULL, + interface_poll_timer_cookie->ci_id); return (ifnet == NULL) ? 0 : 1; } +void +olsr_trigger_ifchange(struct interface *ifp, enum olsr_ifchg_flag flag) +{ + struct ifchgf *tmp_ifchgf_list = ifchgf_list; + while (tmp_ifchgf_list != NULL) { + tmp_ifchgf_list->function(ifp, flag); + tmp_ifchgf_list = tmp_ifchgf_list->next; + } +} /** *Find the local interface with a given address. @@ -91,35 +140,32 @@ ifinit() */ struct interface * -if_ifwithaddr(union olsr_ip_addr *addr) +if_ifwithaddr(const union olsr_ip_addr *addr) { struct interface *ifp; - for (ifp = ifnet; ifp; ifp = ifp->int_next) - { - if(olsr_cnf->ip_version == AF_INET) - { - /* IPv4 */ - //printf("Checking: %s == ", inet_ntoa(((struct sockaddr_in *)&ifp->int_addr)->sin_addr)); - //printf("%s\n", olsr_ip_to_string(addr)); - - if (COMP_IP(&((struct sockaddr_in *)&ifp->int_addr)->sin_addr, addr)) - return ifp; - } - else - { - /* IPv6 */ - //printf("Checking %s ", olsr_ip_to_string((union olsr_ip_addr *)&ifp->int6_addr.sin6_addr)); - //printf("== %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in6 *)addr)->sin6_addr)); - if (COMP_IP(&ifp->int6_addr.sin6_addr, addr)) - return ifp; - } + if (!addr) + return NULL; + + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (olsr_cnf->ip_version == AF_INET) { + /* IPv4 */ + //printf("Checking: %s == ", inet_ntoa(((struct sockaddr_in *)&ifp->int_addr)->sin_addr)); + //printf("%s\n", olsr_ip_to_string(addr)); + + if (((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr == addr->v4.s_addr) + return ifp; + } else { + /* IPv6 */ + //printf("Checking %s ", olsr_ip_to_string((union olsr_ip_addr *)&ifp->int6_addr.sin6_addr)); + //printf("== %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in6 *)addr)->sin6_addr)); + if (ip6equal(&ifp->int6_addr.sin6_addr, &addr->v6)) + return ifp; } + } return NULL; } - - /** *Find the interface with a given number. * @@ -134,16 +180,93 @@ if_ifwithsock(int fd) struct interface *ifp; ifp = ifnet; - while (ifp) - { - if (ifp->olsr_socket == fd) - return ifp; - ifp = ifp->int_next; + while (ifp) { + if (ifp->olsr_socket == fd || ifp->send_socket == fd) + return ifp; + ifp = ifp->int_next; + } + + return NULL; +} + +/** + *Find the interface with a given label. + * + *@param if_name the label of the interface to find. + * + *@return return the interface struct representing the interface + *that matched the label. + */ +struct interface * +if_ifwithname(const char *if_name) +{ + struct interface *ifp = ifnet; + while (ifp) { + /* good ol' strcmp should be sufficcient here */ + if (strcmp(ifp->int_name, if_name) == 0) { + return ifp; } - - return (ifp); + ifp = ifp->int_next; + } + return NULL; } +/** + *Find the olsr_if with a given label. + * + *@param if_name the label of the interface to find. + * + *@return return the interface struct representing the interface + *that matched the label. + */ +struct olsr_if * +olsrif_ifwithname(const char *if_name) +{ + struct olsr_if *oifp = olsr_cnf->interfaces; + while (oifp) { + /* good ol' strcmp should be sufficcient here */ + if (strcmp(oifp->name, if_name) == 0) { + return oifp; + } + oifp = oifp->next; + } + return NULL; +} + +/** + *Find the interface with a given interface index. + * + *@param iif_index of the interface to find. + * + *@return return the interface struct representing the interface + *that matched the iif_index. + */ +struct interface * +if_ifwithindex(const int if_index) +{ + struct interface *ifp = ifnet; + while (ifp != NULL) { + if (ifp->if_index == if_index) { + return ifp; + } + ifp = ifp->int_next; + } + return NULL; +} + +/** + *Get an interface name for a given interface index + * + *@param iif_index of the interface to find. + * + *@return "" or interface name. + */ +const char * +if_ifwithindex_name(const int if_index) +{ + const struct interface *const ifp = if_ifwithindex(if_index); + return ifp == NULL ? "void" : ifp->int_name; +} /** *Create a new interf_name struct using a given @@ -153,42 +276,43 @@ if_ifwithsock(int fd) * *@return nada */ -void -queue_if(char *name) +struct olsr_if * +olsr_create_olsrif(const char *name, int hemu) { - struct olsr_if *interf_n = olsr_cnf->interfaces; + size_t name_size; //printf("Adding interface %s\n", name); /* check if the inerfaces already exists */ - while(interf_n != NULL) - { - if(memcmp(interf_n->name, name, strlen(name)) == 0) - { - fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name); - return; - } - interf_n = interf_n->next; + while (interf_n != NULL) { + if (strcmp(interf_n->name, name) == 0) { + fprintf(stderr, "Duplicate interfaces defined... not adding %s\n", name); + return NULL; } + interf_n = interf_n->next; + } interf_n = olsr_malloc(sizeof(struct olsr_if), "queue interface"); - /* strlen () does not return length including terminating /0 */ - interf_n->name = olsr_malloc(strlen(name) + 1, "queue interface name"); - interf_n->cnf = NULL; - interf_n->interf = NULL; - interf_n->configured = 0; - interf_n->index = olsr_cnf->ifcnt++; + name_size = strlen(name) + 1; + interf_n->name = olsr_malloc(name_size, "queue interface name"); + strscpy(interf_n->name, name, name_size); + + interf_n->cnf = olsr_malloc(sizeof(*interf_n->cnf), "queue cnf"); + + interf_n->cnfi = olsr_malloc(sizeof(*interf_n->cnfi), "queue cnfi"); + memset(interf_n->cnfi, 0xFF, sizeof(*interf_n->cnfi)); + interf_n->cnfi->orig_lq_mult_cnt=0; + + interf_n->host_emul = hemu ? true : false; - strcpy(interf_n->name, name); interf_n->next = olsr_cnf->interfaces; olsr_cnf->interfaces = interf_n; + return interf_n; } - - /** *Add an ifchange function. These functions are called on all (non-initial) *changes in the interface set. @@ -198,7 +322,7 @@ queue_if(char *name) *@return */ int -add_ifchgf(int (*f)(struct interface *, int)) +olsr_add_ifchange_handler(int (*f) (struct interface *, enum olsr_ifchg_flag)) { struct ifchgf *new_ifchgf; @@ -213,39 +337,118 @@ add_ifchgf(int (*f)(struct interface *, int)) return 1; } - - /* * Remove an ifchange function */ int -del_ifchgf(int (*f)(struct interface *, int)) +olsr_remove_ifchange_handler(int (*f) (struct interface *, enum olsr_ifchg_flag)) { struct ifchgf *tmp_ifchgf, *prev; tmp_ifchgf = ifchgf_list; prev = NULL; - while(tmp_ifchgf) - { - if(tmp_ifchgf->function == f) - { - /* Remove entry */ - if(prev == NULL) - { - ifchgf_list = tmp_ifchgf->next; - free(tmp_ifchgf); - } - else - { - prev->next = tmp_ifchgf->next; - free(tmp_ifchgf); - } - return 1; - } - prev = tmp_ifchgf; - tmp_ifchgf = tmp_ifchgf->next; + while (tmp_ifchgf) { + if (tmp_ifchgf->function == f) { + /* Remove entry */ + if (prev == NULL) { + ifchgf_list = tmp_ifchgf->next; + free(tmp_ifchgf); + } else { + prev->next = tmp_ifchgf->next; + free(tmp_ifchgf); + } + return 1; } + prev = tmp_ifchgf; + tmp_ifchgf = tmp_ifchgf->next; + } return 0; } + +void +olsr_remove_interface(struct olsr_if * iface) +{ + struct interface *ifp, *tmp_ifp; + ifp = iface->interf; + + OLSR_PRINTF(1, "Removing interface %s\n", iface->name); + olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name); + + olsr_delete_link_entry_by_ip(&ifp->ip_addr); + + /* + *Call possible ifchange functions registered by plugins + */ + olsr_trigger_ifchange(ifp, IFCHG_IF_REMOVE); + + /* cleanup routes over this interface */ + olsr_delete_interface_routes(ifp->if_index); + + /* Dequeue */ + if (ifp == ifnet) { + ifnet = ifp->int_next; + } else { + tmp_ifp = ifnet; + while (tmp_ifp->int_next != ifp) { + tmp_ifp = tmp_ifp->int_next; + } + tmp_ifp->int_next = ifp->int_next; + } + + /* Remove output buffer */ + net_remove_buffer(ifp); + + /* Check main addr */ + /* deactivated to prevent change of originator IP */ +#if 0 + if (ipequal(&olsr_cnf->main_addr, &ifp->ip_addr)) { + if (ifnet == NULL) { + /* No more interfaces */ + memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize); + OLSR_PRINTF(1, "No more interfaces...\n"); + } else { + struct ipaddr_str buf; + olsr_cnf->main_addr = ifnet->ip_addr; + OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); + olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); + } + } +#endif + /* + * Deregister functions for periodic message generation + */ + olsr_stop_timer(ifp->hello_gen_timer); + olsr_stop_timer(ifp->tc_gen_timer); + olsr_stop_timer(ifp->mid_gen_timer); + olsr_stop_timer(ifp->hna_gen_timer); + + iface->configured = 0; + iface->interf = NULL; + + /* Close olsr socket */ + close(ifp->olsr_socket); + remove_olsr_socket(ifp->olsr_socket, &olsr_input); + + if (ifp->send_socket != ifp->olsr_socket) { + close(ifp->send_socket); + remove_olsr_socket(ifp->send_socket, &olsr_input); + } + + /* Free memory */ + free(ifp->int_name); + free(ifp); + + if ((ifnet == NULL) && (!olsr_cnf->allow_no_interfaces)) { + olsr_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n"); + olsr_exit("No more active interfaces - exiting.\n", EXIT_FAILURE); + } +} + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */