X-Git-Url: http://olsr.org/git/?p=olsrd.git;a=blobdiff_plain;f=src%2Finterfaces.c;h=d5c855c55620d347abdaf03f5869159bbb46d832;hp=8a892afbd925cd5b87cd60ecabc97dd7b059d32c;hb=b8eb53fb729164d674a31d7cfcad60c6424b4d5b;hpb=6b0f661c4e4cc7d6640e56c551eed62e6a7dc6a9 diff --git a/src/interfaces.c b/src/interfaces.c index 8a892afb..d5c855c5 100644 --- a/src/interfaces.c +++ b/src/interfaces.c @@ -1,33 +1,34 @@ + /* * The olsr.org Optimized Link-State Routing daemon(olsrd) - * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org) + * 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 + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions * are met: * - * * Redistributions of source code must retain the above copyright + * * 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 + * * 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 + * * 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. * - * 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 + * 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. * * Visit http://www.olsr.org for more information. @@ -36,34 +37,45 @@ * to the project. For more information see the website or contact * the copyright holders. * - * $Id: interfaces.c,v 1.35 2007/10/13 12:09:11 bernd67 Exp $ */ +#include +#include + #include "defs.h" #include "interfaces.h" #include "ifnet.h" #include "scheduler.h" #include "olsr.h" +#include "net_olsr.h" +#include "ipcalc.h" +#include "log.h" +#include "parser.h" +#include "socket_parser.h" -static olsr_u32_t if_property_id; +#ifdef WIN32 +#include +#define close(x) closesocket(x) +#endif /* The interface linked-list */ struct interface *ifnet; -/* Datastructures to use when creating new sockets */ -struct sockaddr_in addrsock; -struct sockaddr_in6 addrsock6; - - /* Ifchange functions */ -struct ifchgf -{ - int (*function)(struct interface *, int); +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 *network interface management. @@ -72,150 +84,52 @@ static struct ifchgf *ifchgf_list; *@return the number of interfaces configured */ int -ifinit(void) +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 = htons(OLSRPORT); - (addrsock.sin_addr).s_addr = INADDR_ANY; - } - else - { - /* IP version 6 */ - memset(&addrsock6, 0, sizeof (addrsock6)); - addrsock6.sin6_family = AF_INET6; - addrsock6.sin6_port = htons(OLSRPORT); - //(addrsock6.sin6_addr).s_addr = IN6ADDR_ANY_INIT; - } - - 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) - { - 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, - olsr_cnf->nic_chgs_pollrate, 0, NULL); - - return (ifnet == NULL) ? 0 : 1; -} + 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_u32_t -get_if_property_id(void) -{ - return if_property_id++; -} - -olsr_bool -add_if_geninfo(struct interface *ifp, void *data, olsr_u32_t owner_id) -{ - struct if_gen_property *igp; - - if(get_if_geninfo(ifp, owner_id) != NULL) - return OLSR_FALSE; - - igp = olsr_malloc(sizeof(struct if_gen_property), __func__); - - igp->owner_id = owner_id; - igp->data = data; - - /* queue */ - igp->next = ifp->gen_properties; - ifp->gen_properties = igp; - - return OLSR_TRUE; -} - -void * -get_if_geninfo(struct interface *ifp, olsr_u32_t owner_id) -{ - struct if_gen_property *igp_list = ifp->gen_properties; - - - while(igp_list) - { - if(igp_list->owner_id == owner_id) - return igp_list->data; - - igp_list = igp_list->next; - } - - return NULL; -} - -void * -del_if_geninfo(struct interface *ifp, olsr_u32_t owner_id) -{ - void *data = NULL; - struct if_gen_property *igp_list = ifp->gen_properties; - struct if_gen_property *igp_prev = NULL; - - - while(igp_list) - { - if(igp_list->owner_id == owner_id) - break; - - igp_prev = igp_list; - igp_list = igp_list->next; + 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) { + if (!tmp_if->host_emul) { + if (!olsr_cnf->host_emul) /* XXX: TEMPORARY! */ + chk_if_up(tmp_if, 1); + } else { + add_hemu_if(tmp_if); } + } - /* Not found */ - if(igp_list == NULL) - return NULL; - - /* Dequeue */ - if(igp_prev == NULL) - { - /* First elem */ - ifp->gen_properties = igp_list->next; - } - else - { - igp_prev->next = igp_list->next; - } - data = igp_list->data; - free(igp_list); + /* 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 data; + return (ifnet == NULL) ? 0 : 1; } - void -run_ifchg_cbs(struct interface *ifp, int flag) +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; - } + 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. * @@ -226,38 +140,32 @@ run_ifchg_cbs(struct interface *ifp, int flag) */ struct interface * -if_ifwithaddr(const union olsr_ip_addr * const addr) +if_ifwithaddr(const union olsr_ip_addr *addr) { struct interface *ifp; - if(!addr) + 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 (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; - } + 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. * @@ -272,17 +180,15 @@ 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. * @@ -294,20 +200,38 @@ if_ifwithsock(int fd) struct interface * if_ifwithname(const char *if_name) { - struct interface *ifp; - ifp = ifnet; - - while (ifp) - { - /* good ol' strcmp should be sufficcient here */ - if (!strcmp(ifp->int_name, if_name)) - return ifp; - ifp = ifp->int_next; + struct interface *ifp = ifnet; + while (ifp) { + /* good ol' strcmp should be sufficcient here */ + if (strcmp(ifp->int_name, if_name) == 0) { + 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. @@ -321,16 +245,15 @@ struct interface * if_ifwithindex(const int if_index) { struct interface *ifp = ifnet; - while (ifp) - { - if (ifp->if_index == if_index) - return ifp; - ifp = ifp->int_next; + 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 * @@ -341,11 +264,10 @@ if_ifwithindex(const int if_index) const char * if_ifwithindex_name(const int if_index) { - const struct interface * const ifp = if_ifwithindex(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 *name and insert it into the interface list. @@ -355,42 +277,42 @@ if_ifwithindex_name(const int if_index) *@return nada */ struct olsr_if * -queue_if(char *name, int hemu) +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 NULL; - } - 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; + 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->host_emul = hemu ? OLSR_TRUE : OLSR_FALSE; + 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; - strncpy(interf_n->name, name, strlen(name) + 1); 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. @@ -400,7 +322,7 @@ queue_if(char *name, int hemu) *@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; @@ -415,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: + */