diff options
| author | Daniel Walton <dwalton@cumulusnetworks.com> | 2016-02-11 08:55:24 -0800 | 
|---|---|---|
| committer | Daniel Walton <dwalton@cumulusnetworks.com> | 2016-02-11 08:55:24 -0800 | 
| commit | 41d9cc6a6569e3a66f77a9cfd2869d209e665fa0 (patch) | |
| tree | f7de1b136260d314a26b378156d7f94cf42e36a7 /babeld | |
| parent | b3556ea327bf3abc4bd183a4b5b8ad1a15d15035 (diff) | |
quagga: remove babel
Ticket: CM-9274
Reviewed By: sharpd@cumulusnetworks.com
Testing Done:
<DETAILED DESCRIPTION (REPLACE)>
Diffstat (limited to 'babeld')
| -rw-r--r-- | babeld/.gitignore | 7 | ||||
| -rw-r--r-- | babeld/LICENCE | 36 | ||||
| -rw-r--r-- | babeld/Makefile.am | 29 | ||||
| -rw-r--r-- | babeld/babel_filter.c | 124 | ||||
| -rw-r--r-- | babeld/babel_filter.h | 49 | ||||
| -rw-r--r-- | babeld/babel_interface.c | 1023 | ||||
| -rw-r--r-- | babeld/babel_interface.h | 152 | ||||
| -rw-r--r-- | babeld/babel_main.c | 533 | ||||
| -rw-r--r-- | babeld/babel_main.h | 57 | ||||
| -rw-r--r-- | babeld/babel_zebra.c | 388 | ||||
| -rw-r--r-- | babeld/babel_zebra.h | 50 | ||||
| -rw-r--r-- | babeld/babeld.c | 732 | ||||
| -rw-r--r-- | babeld/babeld.conf.sample | 30 | ||||
| -rw-r--r-- | babeld/babeld.h | 141 | ||||
| -rw-r--r-- | babeld/kernel.c | 316 | ||||
| -rw-r--r-- | babeld/kernel.h | 69 | ||||
| -rw-r--r-- | babeld/message.c | 1561 | ||||
| -rw-r--r-- | babeld/message.h | 111 | ||||
| -rw-r--r-- | babeld/neighbour.c | 343 | ||||
| -rw-r--r-- | babeld/neighbour.h | 66 | ||||
| -rw-r--r-- | babeld/net.c | 239 | ||||
| -rw-r--r-- | babeld/net.h | 44 | ||||
| -rw-r--r-- | babeld/resend.c | 330 | ||||
| -rw-r--r-- | babeld/resend.h | 77 | ||||
| -rw-r--r-- | babeld/route.c | 1019 | ||||
| -rw-r--r-- | babeld/route.h | 135 | ||||
| -rw-r--r-- | babeld/source.c | 180 | ||||
| -rw-r--r-- | babeld/source.h | 67 | ||||
| -rw-r--r-- | babeld/util.c | 445 | ||||
| -rw-r--r-- | babeld/util.h | 165 | ||||
| -rw-r--r-- | babeld/xroute.c | 237 | ||||
| -rw-r--r-- | babeld/xroute.h | 59 | 
32 files changed, 0 insertions, 8814 deletions
diff --git a/babeld/.gitignore b/babeld/.gitignore deleted file mode 100644 index 8384763a65..0000000000 --- a/babeld/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -* -!*.c -!*.h -!LICENCE -!Makefile.am -!babeld.conf.sample -!.gitignore
\ No newline at end of file diff --git a/babeld/LICENCE b/babeld/LICENCE deleted file mode 100644 index 9da569dc28..0000000000 --- a/babeld/LICENCE +++ /dev/null @@ -1,36 +0,0 @@ -Code in this directory is made available under the following licence: - -  --------------------------------------------------------------------------- -  Copyright (c) 2007, 2008 by Juliusz Chroboczek -   -  Permission is hereby granted, free of charge, to any person obtaining a copy -  of this software and associated documentation files (the "Software"), to deal -  in the Software without restriction, including without limitation the rights -  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -  copies of the Software, and to permit persons to whom the Software is -  furnished to do so, subject to the following conditions: -   -  The above copyright notice and this permission notice shall be included in -  all copies or substantial portions of the Software. -   -  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -  THE SOFTWARE. -  --------------------------------------------------------------------------- - -The code also makes calls to and links with the "libzebra" code of Quagga, -in the lib/ directory of this project, which is subject to the GPL licence -as given in the top-level COPYING file included with Quagga. - -Contributors to the code in babeld/ are asked to make their work available -under the same MIT/X11 licence as given immediately above.  Please indicate -your assent to this by updating this file and appending the appropriate - -  Copyright <year> <Author name>, <author contact details> - -line to the existing copyright assertion lines in the MIT/X11 licence text -above in this file. diff --git a/babeld/Makefile.am b/babeld/Makefile.am deleted file mode 100644 index ad6a33bb79..0000000000 --- a/babeld/Makefile.am +++ /dev/null @@ -1,29 +0,0 @@ -## Process this file with automake to produce Makefile.in. - -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib -DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -INSTALL_SDATA=@INSTALL@ -m 600 - -AM_CFLAGS = $(PICFLAGS) $(WERROR) -AM_LDFLAGS = $(PILDFLAGS) - -noinst_LIBRARIES = libbabel.a -sbin_PROGRAMS = babeld - -libbabel_a_SOURCES = \ -	babel_zebra.c net.c kernel.c util.c source.c neighbour.c	\ -	route.c xroute.c message.c resend.c babel_interface.c babeld.c	\ -	babel_filter.c - -noinst_HEADERS = \ -	babel_zebra.h net.h kernel.h util.h source.h neighbour.h	\ -	route.h xroute.h message.h resend.h babel_interface.h babeld.h	\ -	babel_filter.h babel_main.h - -babeld_SOURCES = \ -	babel_main.c $(libbabel_a_SOURCES) - -babeld_LDADD = ../lib/libzebra.la @LIBCAP@ - -examplesdir = $(exampledir) -dist_examples_DATA = babeld.conf.sample diff --git a/babeld/babel_filter.c b/babeld/babel_filter.c deleted file mode 100644 index 191a9f77ea..0000000000 --- a/babeld/babel_filter.c +++ /dev/null @@ -1,124 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   - -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include "babel_filter.h" -#include "vty.h" -#include "filter.h" -#include "log.h" -#include "plist.h" -#include "distribute.h" -#include "util.h" - -int -babel_filter(int output, const unsigned char *prefix, unsigned short plen, -             unsigned int ifindex) -{ -    struct interface *ifp = if_lookup_by_index(ifindex); -    babel_interface_nfo *babel_ifp = ifp ? babel_get_if_nfo(ifp) : NULL; -    struct prefix p; -    struct distribute *dist; -    struct access_list *alist; -    struct prefix_list *plist; -    int filter = output ? BABEL_FILTER_OUT : BABEL_FILTER_IN; -    int distribute = output ? DISTRIBUTE_OUT : DISTRIBUTE_IN; - -    p.family = v4mapped(prefix) ? AF_INET : AF_INET6; -    p.prefixlen = v4mapped(prefix) ? plen - 96 : plen; -    if (p.family == AF_INET) -        uchar_to_inaddr(&p.u.prefix4, prefix); -    else -        uchar_to_in6addr(&p.u.prefix6, prefix); - -    if (babel_ifp != NULL && babel_ifp->list[filter]) { -        if (access_list_apply (babel_ifp->list[filter], &p) -            == FILTER_DENY) { -            debugf(BABEL_DEBUG_FILTER, -                   "%s/%d filtered by distribute in", -                   p.family == AF_INET ? -                   inet_ntoa(p.u.prefix4) : -                   inet6_ntoa (p.u.prefix6), -                   p.prefixlen); -            return INFINITY; -	} -    } -    if (babel_ifp != NULL && babel_ifp->prefix[filter]) { -        if (prefix_list_apply (babel_ifp->prefix[filter], &p) -            == PREFIX_DENY) { -            debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in", -                        p.family == AF_INET ? -                        inet_ntoa(p.u.prefix4) : -                        inet6_ntoa (p.u.prefix6), -                        p.prefixlen); -            return INFINITY; -	} -    } - -    /* All interface filter check. */ -    dist = distribute_lookup (NULL); -    if (dist) { -        if (dist->list[distribute]) { -            alist = access_list_lookup (AFI_IP6, dist->list[distribute]); - -            if (alist) { -                if (access_list_apply (alist, &p) == FILTER_DENY) { -                    debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in", -                                p.family == AF_INET ? -                                inet_ntoa(p.u.prefix4) : -                                inet6_ntoa (p.u.prefix6), -                                p.prefixlen); -                    return INFINITY; -		} -	    } -	} -        if (dist->prefix[distribute]) { -            plist = prefix_list_lookup (AFI_IP6, dist->prefix[distribute]); -            if (plist) { -                if (prefix_list_apply (plist, &p) == PREFIX_DENY) { -                    debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in", -                                p.family == AF_INET ? -                                inet_ntoa(p.u.prefix4) : -                                inet6_ntoa (p.u.prefix6), -                                p.prefixlen); -                    return INFINITY; -		} -	    } -	} -    } -    return 0; -} diff --git a/babeld/babel_filter.h b/babeld/babel_filter.h deleted file mode 100644 index 73722e0a3c..0000000000 --- a/babeld/babel_filter.h +++ /dev/null @@ -1,49 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef BABELD_BABEL_FILTER_H -#define BABELD_BABEL_FILTER_H - -#include <zebra.h> -#include "prefix.h" -#include "babel_interface.h" - -int babel_filter(int output, const unsigned char *prefix, unsigned short plen, -                 unsigned int index); - -#endif /* BABELD_BABEL_FILTER_H */ diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c deleted file mode 100644 index 8dfaffd878..0000000000 --- a/babeld/babel_interface.c +++ /dev/null @@ -1,1023 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   - -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <zebra.h> -#include "memory.h" -#include "log.h" -#include "command.h" -#include "prefix.h" -#include "vector.h" -#include "distribute.h" - -#include "babel_main.h" -#include "util.h" -#include "kernel.h" -#include "babel_interface.h" -#include "message.h" -#include "route.h" -#include "babel_zebra.h" -#include "neighbour.h" -#include "route.h" -#include "xroute.h" -#include "vrf.h" - - -#define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0) - -static int babel_enable_if_lookup (const char *ifname); -static int babel_enable_if_add (const char *ifname); -static int babel_enable_if_delete (const char *ifname); -static int interface_recalculate(struct interface *ifp); -static int interface_reset(struct interface *ifp); -static int babel_if_new_hook    (struct interface *ifp); -static int babel_if_delete_hook (struct interface *ifp); -static int interface_config_write (struct vty *vty); -static babel_interface_nfo * babel_interface_allocate (void); -static void babel_interface_free (babel_interface_nfo *bi); - - -static vector babel_enable_if;                 /* enable interfaces (by cmd). */ -static struct cmd_node babel_interface_node =  /* babeld's interface node.    */ -{ -    INTERFACE_NODE, -    "%s(config-if)# ", -    1 /* VTYSH */ -}; - - -int -babel_interface_up (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf_id) -{ -    struct stream *s = NULL; -    struct interface *ifp = NULL; - -    debugf(BABEL_DEBUG_IF, "receive a 'interface up'"); - -    s = zclient->ibuf; -    ifp = zebra_interface_state_read(s, vrf_id); /* it updates iflist */ - -    if (ifp == NULL) { -        return 0; -    } - -    interface_recalculate(ifp); -    return 0; -} - -int -babel_interface_down (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf_id) -{ -    struct stream *s = NULL; -    struct interface *ifp = NULL; - -    debugf(BABEL_DEBUG_IF, "receive a 'interface down'"); - -    s = zclient->ibuf; -    ifp = zebra_interface_state_read(s, vrf_id); /* it updates iflist */ - -    if (ifp == NULL) { -        return 0; -    } - -    interface_reset(ifp); -    return 0; -} - -int -babel_interface_add (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf_id) -{ -    struct interface *ifp = NULL; - -    debugf(BABEL_DEBUG_IF, "receive a 'interface add'"); - -    /* read and add the interface in the iflist. */ -    ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); - -    if (ifp == NULL) { -        return 0; -    } - -    interface_recalculate(ifp); -    return 0; -} - -int -babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length, vrf_id_t vrf_id) -{ -    struct interface *ifp; -    struct stream *s; - -    debugf(BABEL_DEBUG_IF, "receive a 'interface delete'"); - -    s = zclient->ibuf; -    ifp = zebra_interface_state_read(s, vrf_id); /* it updates iflist */ - -    if (ifp == NULL) -        return 0; - -    if (IS_ENABLE(ifp)) -        interface_reset(ifp); - -    /* To support pseudo interface do not free interface structure.  */ -    /* if_delete(ifp); */ -    ifp->ifindex = IFINDEX_INTERNAL; - -    return 0; -} - -int -babel_interface_address_add (int cmd, struct zclient *client, -                             zebra_size_t length, vrf_id_t vrf_id) -{ -    babel_interface_nfo *babel_ifp; -    struct connected *ifc; -    struct prefix *prefix; - -    debugf(BABEL_DEBUG_IF, "receive a 'interface address add'"); - -    ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, -                                        zclient->ibuf, vrf_id); - -    if (ifc == NULL) -        return 0; - -    prefix = ifc->address; - -    if (prefix->family == AF_INET) { -        flush_interface_routes(ifc->ifp, 0); -        babel_ifp = babel_get_if_nfo(ifc->ifp); -        if (babel_ifp->ipv4 == NULL) { -            babel_ifp->ipv4 = malloc(4); -            if (babel_ifp->ipv4 == NULL) { -                zlog_err("not einough memory"); -            } else { -                memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4); -            } -        } -    } - -    send_request(ifc->ifp, NULL, 0); -    send_update(ifc->ifp, 0, NULL, 0); - -    return 0; -} - -int -babel_interface_address_delete (int cmd, struct zclient *client, -                                zebra_size_t length, vrf_id_t vrf_id) -{ -    babel_interface_nfo *babel_ifp; -    struct connected *ifc; -    struct prefix *prefix; - -    debugf(BABEL_DEBUG_IF, "receive a 'interface address add'"); - -    ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, -                                        zclient->ibuf, vrf_id); - -    if (ifc == NULL) -        return 0; - -    prefix = ifc->address; - -    if (prefix->family == AF_INET) { -        flush_interface_routes(ifc->ifp, 0); -        babel_ifp = babel_get_if_nfo(ifc->ifp); -        if (babel_ifp->ipv4 != NULL -            && memcmp(babel_ifp->ipv4, &prefix->u.prefix4, 4) == 0) { -            free(babel_ifp->ipv4); -            babel_ifp->ipv4 = NULL; -        } -    } - -    send_request(ifc->ifp, NULL, 0); -    send_update(ifc->ifp, 0, NULL, 0); - -    return 0; -} - -/* Lookup function. */ -static int -babel_enable_if_lookup (const char *ifname) -{ -    unsigned int i; -    char *str; - -    for (i = 0; i < vector_active (babel_enable_if); i++) -        if ((str = vector_slot (babel_enable_if, i)) != NULL) -            if (strcmp (str, ifname) == 0) -                return i; -    return -1; -} - -/* Add interface to babel_enable_if. */ -static int -babel_enable_if_add (const char *ifname) -{ -    int ret; -    struct interface *ifp = NULL; - -    ret = babel_enable_if_lookup (ifname); -    if (ret >= 0) -        return -1; - -    vector_set (babel_enable_if, strdup (ifname)); - -    ifp = if_lookup_by_name(ifname); -    if (ifp != NULL) -        interface_recalculate(ifp); - -    return 1; -} - -/* Delete interface from babel_enable_if. */ -static int -babel_enable_if_delete (const char *ifname) -{ -    int babel_enable_if_index; -    char *str; -    struct interface *ifp = NULL; - -    babel_enable_if_index = babel_enable_if_lookup (ifname); -    if (babel_enable_if_index < 0) -        return -1; - -    str = vector_slot (babel_enable_if, babel_enable_if_index); -    free (str); -    vector_unset (babel_enable_if, babel_enable_if_index); - -    ifp = if_lookup_by_name(ifname); -    if (ifp != NULL) -        interface_reset(ifp); - -    return 1; -} - -/* [Babel Command] Babel enable on specified interface or matched network. */ -DEFUN (babel_network, -       babel_network_cmd, -       "network IF_OR_ADDR", -       "Enable Babel protocol on specified interface or network.\n" -       "Interface or address") -{ -    int ret; -    struct prefix p; - -    ret = str2prefix (argv[0], &p); - -    /* Given string is:               */ -    if (ret) /* an IPv4 or v6 network */ -        return CMD_ERR_NO_MATCH; /* not implemented yet */ -    else     /* an interface name     */ -        ret = babel_enable_if_add (argv[0]); - -    if (ret < 0) { -        vty_out (vty, "There is same network configuration %s%s", argv[0], -                 VTY_NEWLINE); -        return CMD_WARNING; -    } - -    return CMD_SUCCESS; -} - -/* [Babel Command] Babel enable on specified interface or matched network. */ -DEFUN (no_babel_network, -       no_babel_network_cmd, -       "no network IF_OR_ADDR", -       NO_STR -       "Disable Babel protocol on specified interface or network.\n" -       "Interface or address") -{ -    int ret; -    struct prefix p; - -    ret = str2prefix (argv[0], &p); - -    /* Given string is:               */ -    if (ret) /* an IPv4 or v6 network */ -        return CMD_ERR_NO_MATCH; /* not implemented yet */ -    else     /* an interface name     */ -        ret = babel_enable_if_delete (argv[0]); - -    if (ret < 0) { -        vty_out (vty, "can't find network %s%s", argv[0], -                 VTY_NEWLINE); -        return CMD_WARNING; -    } - -    return CMD_SUCCESS; -} - -/* There are a number of interface parameters that must be changed when -   an interface becomes wired/wireless.  In Quagga, they cannot be -   configured separately. */ - -static void -babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired) -{ -    if(wired) { -        babel_ifp->flags |= BABEL_IF_WIRED; -        babel_ifp->cost = 96; -        babel_ifp->flags &= ~BABEL_IF_LQ; -    } else { -        babel_ifp->flags &= ~BABEL_IF_WIRED; -        babel_ifp->cost = 256; -        babel_ifp->flags |= BABEL_IF_LQ; -    } - -} - -/* [Interface Command] Tell the interface is wire. */ -DEFUN (babel_set_wired, -       babel_set_wired_cmd, -       "babel wired", -       "Babel interface commands\n" -       "Enable wired optimisations") -{ -    struct interface *ifp; -    babel_interface_nfo *babel_ifp; - -    ifp = vty->index; -    babel_ifp = babel_get_if_nfo(ifp); - -    assert (babel_ifp != NULL); -    babel_set_wired_internal(babel_ifp, 1); -    return CMD_SUCCESS; -} - -/* [Interface Command] Tell the interface is wireless (default). */ -DEFUN (babel_set_wireless, -       babel_set_wireless_cmd, -       "babel wireless", -       "Babel interface commands\n" -       "Disable wired optimiations (assume wireless)") -{ -    struct interface *ifp; -    babel_interface_nfo *babel_ifp; - -    ifp = vty->index; -    babel_ifp = babel_get_if_nfo(ifp); - -    assert (babel_ifp != NULL); -    babel_set_wired_internal(babel_ifp, 0); -    return CMD_SUCCESS; -} - -/* [Interface Command] Enable split horizon. */ -DEFUN (babel_split_horizon, -       babel_split_horizon_cmd, -       "babel split-horizon", -       "Babel interface commands\n" -       "Enable split horizon processing") -{ -    struct interface *ifp; -    babel_interface_nfo *babel_ifp; - -    ifp = vty->index; -    babel_ifp = babel_get_if_nfo(ifp); - -    assert (babel_ifp != NULL); -    babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON; -    return CMD_SUCCESS; -} - -/* [Interface Command] Disable split horizon (default). */ -DEFUN (no_babel_split_horizon, -       no_babel_split_horizon_cmd, -       "no babel split-horizon", -       NO_STR -       "Babel interface commands\n" -       "Disable split horizon processing") -{ -    struct interface *ifp; -    babel_interface_nfo *babel_ifp; - -    ifp = vty->index; -    babel_ifp = babel_get_if_nfo(ifp); - -    assert (babel_ifp != NULL); -    babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON; -    return CMD_SUCCESS; -} - -/* [Interface Command]. */ -DEFUN (babel_set_hello_interval, -       babel_set_hello_interval_cmd, -       "babel hello-interval <20-655340>", -       "Babel interface commands\n" -       "Time between scheduled hellos\n" -       "Milliseconds\n") -{ -    struct interface *ifp; -    babel_interface_nfo *babel_ifp; -    int interval; - -    VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE); - -    ifp = vty->index; -    babel_ifp = babel_get_if_nfo(ifp); -    assert (babel_ifp != NULL); - -    babel_ifp->hello_interval = interval; -    return CMD_SUCCESS; -} - -/* [Interface Command]. */ -DEFUN (babel_set_update_interval, -       babel_set_update_interval_cmd, -       "babel update-interval <20-655340>", -       "Babel interface commands\n" -       "Time between scheduled updates\n" -       "Milliseconds\n") -{ -    struct interface *ifp; -    babel_interface_nfo *babel_ifp; -    int interval; - -    VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE); - -    ifp = vty->index; -    babel_ifp = babel_get_if_nfo(ifp); -    assert (babel_ifp != NULL); - -    babel_ifp->update_interval = interval; -    return CMD_SUCCESS; -} - -/* This should be no more than half the hello interval, so that hellos -   aren't sent late.  The result is in milliseconds. */ -unsigned -jitter(babel_interface_nfo *babel_ifp, int urgent) -{ -    unsigned interval = babel_ifp->hello_interval; -    if(urgent) -        interval = MIN(interval, 100); -    else -        interval = MIN(interval, 4000); -    return roughly(interval) / 4; -} - -unsigned -update_jitter(babel_interface_nfo *babel_ifp, int urgent) -{ -    unsigned interval = babel_ifp->hello_interval; -    if(urgent) -        interval = MIN(interval, 100); -    else -        interval = MIN(interval, 4000); -    return roughly(interval); -} - -/* calculate babeld's specific datas of an interface (change when the interface - change) */ -static int -interface_recalculate(struct interface *ifp) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    unsigned char *tmp = NULL; -    int mtu, rc; -    struct ipv6_mreq mreq; - -    if (!IS_ENABLE(ifp)) -        return -1; - -    if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) { -        interface_reset(ifp); -        return -1; -    } - -    babel_ifp->flags |= BABEL_IF_IS_UP; - -    mtu = MIN(ifp->mtu, ifp->mtu6); - -    /* We need to be able to fit at least two messages into a packet, -     so MTUs below 116 require lower layer fragmentation. */ -    /* In IPv6, the minimum MTU is 1280, and every host must be able -     to reassemble up to 1500 bytes, but I'd rather not rely on this. */ -    if(mtu < 128) { -        debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).", -               mtu, ifp->name, ifp->ifindex); -        mtu = 128; -    } - -    /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */ -    babel_ifp->bufsize = mtu - sizeof(packet_header) - 60; -    tmp = babel_ifp->sendbuf; -    babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize); -    if(babel_ifp->sendbuf == NULL) { -        zlog_err("Couldn't reallocate sendbuf."); -        free(tmp); -        babel_ifp->bufsize = 0; -        return -1; -    } -    tmp = NULL; - -    resize_receive_buffer(mtu); - -    memset(&mreq, 0, sizeof(mreq)); -    memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16); -    mreq.ipv6mr_interface = ifp->ifindex; - -    rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, -                    (char*)&mreq, sizeof(mreq)); -    if(rc < 0) { -        zlog_err("setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s", -                 ifp->name, safe_strerror(errno)); -        /* This is probably due to a missing link-local address, -         so down this interface, and wait until the main loop -         tries to up it again. */ -        interface_reset(ifp); -        return -1; -    } - -    set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval); -    set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval); -    send_hello(ifp); -    send_request(ifp, NULL, 0); - -    update_interface_metric(ifp); - -    debugf(BABEL_DEBUG_COMMON, -           "Upped interface %s (%s, cost=%d, channel=%d%s).", -           ifp->name, -           (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless", -           babel_ifp->cost, -           babel_ifp->channel, -           babel_ifp->ipv4 ? ", IPv4" : ""); - -    if(rc > 0) -        send_update(ifp, 0, NULL, 0); - -    return 1; -} - -/* Reset the interface as it was new: it's not removed from the interface list, - and may be considered as a upped interface. */ -static int -interface_reset(struct interface *ifp) -{ -    int rc; -    struct ipv6_mreq mreq; -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); - -    if (!(babel_ifp->flags & BABEL_IF_IS_UP)) -        return 0; - -    debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name); -    babel_ifp->flags &= ~BABEL_IF_IS_UP; - -    flush_interface_routes(ifp, 0); -    babel_ifp->buffered = 0; -    babel_ifp->bufsize = 0; -    free(babel_ifp->sendbuf); -    babel_ifp->num_buffered_updates = 0; -    babel_ifp->update_bufsize = 0; -    if(babel_ifp->buffered_updates) -        free(babel_ifp->buffered_updates); -    babel_ifp->buffered_updates = NULL; -    babel_ifp->sendbuf = NULL; - -    if(ifp->ifindex > 0) { -        memset(&mreq, 0, sizeof(mreq)); -        memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16); -        mreq.ipv6mr_interface = ifp->ifindex; -        rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP, -                        (char*)&mreq, sizeof(mreq)); -        if(rc < 0) -            zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s", -                     ifp->name, safe_strerror(errno)); -    } - -    update_interface_metric(ifp); - -    debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).", -           ifp->name, -           (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless", -           babel_ifp->cost, -           babel_ifp->ipv4 ? ", IPv4" : ""); - -    return 1; -} - -/* Send retraction to all, and reset all interfaces statistics. */ -void -babel_interface_close_all(void) -{ -    struct interface *ifp = NULL; -    struct listnode *linklist_node = NULL; - -    FOR_ALL_INTERFACES(ifp, linklist_node) { -        if(!if_up(ifp)) -            continue; -        send_wildcard_retraction(ifp); -        /* Make sure that we expire quickly from our neighbours' -         association caches. */ -        send_hello_noupdate(ifp, 10); -        flushbuf(ifp); -        usleep(roughly(1000)); -        gettime(&babel_now); -    } -    FOR_ALL_INTERFACES(ifp, linklist_node) { -        if(!if_up(ifp)) -            continue; -        /* Make sure they got it. */ -        send_wildcard_retraction(ifp); -        send_hello_noupdate(ifp, 1); -        flushbuf(ifp); -        usleep(roughly(10000)); -        gettime(&babel_now); -        interface_reset(ifp); -    } -} - -/* return "true" if address is one of our ipv6 addresses */ -int -is_interface_ll_address(struct interface *ifp, const unsigned char *address) -{ -    struct connected *connected; -    struct listnode *node; - -    if(!if_up(ifp)) -        return 0; - -    FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) { -        if(connected->address->family == AF_INET6 && -           memcmp(&connected->address->u.prefix6, address, 16) == 0) -            return 1; -    } - -    return 0; -} - -static void -show_babel_interface_sub (struct vty *vty, struct interface *ifp) -{ -  int is_up; -  babel_interface_nfo *babel_ifp; - -  vty_out (vty, "%s is %s%s", ifp->name, -    ((is_up = if_is_operative(ifp)) ? "up" : "down"), VTY_NEWLINE); -  vty_out (vty, "  ifindex %u, MTU %u bytes %s%s", -    ifp->ifindex, ifp->mtu, if_flag_dump(ifp->flags), VTY_NEWLINE); - -  if (babel_enable_if_lookup (ifp->name) < 0) -  { -    vty_out (vty, "  Babel protocol is not enabled on this interface%s", VTY_NEWLINE); -    return; -  } -  if (!is_up) -  { -    vty_out (vty, "  Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE); -    return; -  } -  babel_ifp = babel_get_if_nfo (ifp); -  vty_out (vty, "  Babel protocol is running on this interface%s", VTY_NEWLINE); -  vty_out (vty, "  Operating mode is \"%s\"%s", -           CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless", VTY_NEWLINE); -  vty_out (vty, "  Split horizon mode is %s%s", -           CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off", VTY_NEWLINE); -  vty_out (vty, "  Hello interval is %u ms%s", babel_ifp->hello_interval, VTY_NEWLINE); -  vty_out (vty, "  Update interval is %u ms%s", babel_ifp->update_interval, VTY_NEWLINE); -} - -DEFUN (show_babel_interface, -       show_babel_interface_cmd, -       "show babel interface [INTERFACE]", -       SHOW_STR -       IP_STR -       "Babel information\n" -       "Interface information\n" -       "Interface name\n") -{ -  struct interface *ifp; -  struct listnode *node; - -  if (argc == 0) -  { -    for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) -      show_babel_interface_sub (vty, ifp); -    return CMD_SUCCESS; -  } -  if ((ifp = if_lookup_by_name (argv[0])) == NULL) -  { -    vty_out (vty, "No such interface name%s", VTY_NEWLINE); -    return CMD_WARNING; -  } -  show_babel_interface_sub (vty, ifp); -  return CMD_SUCCESS; -} - -static void -show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh) -{ -    vty_out (vty, -             "Neighbour %s dev %s reach %04x rxcost %d txcost %d %s.%s", -             format_address(neigh->address), -             neigh->ifp->name, -             neigh->reach, -             neighbour_rxcost(neigh), -             neigh->txcost, -             if_up(neigh->ifp) ? "" : " (down)", -             VTY_NEWLINE); -} - -DEFUN (show_babel_neighbour, -       show_babel_neighbour_cmd, -       "show babel neighbour [INTERFACE]", -       SHOW_STR -       IP_STR -       "Babel information\n" -       "Print neighbours\n" -       "Interface name\n") -{ -    struct neighbour *neigh; -    struct interface *ifp; - -    if (argc == 0) { -        FOR_ALL_NEIGHBOURS(neigh) { -            show_babel_neighbour_sub(vty, neigh); -        } -        return CMD_SUCCESS; -    } -    if ((ifp = if_lookup_by_name (argv[0])) == NULL) -    { -        vty_out (vty, "No such interface name%s", VTY_NEWLINE); -        return CMD_WARNING; -    } -    FOR_ALL_NEIGHBOURS(neigh) { -        if(ifp->ifindex == neigh->ifp->ifindex) { -            show_babel_neighbour_sub(vty, neigh); -        } -    } -    return CMD_SUCCESS; -} - -static void -show_babel_routes_sub (struct babel_route *route, void *closure) -{ -    struct vty *vty = (struct vty*) closure; -    const unsigned char *nexthop = -        memcmp(route->nexthop, route->neigh->address, 16) == 0 ? -        NULL : route->nexthop; -    char channels[100]; - -    if(route->channels[0] == 0) -        channels[0] = '\0'; -    else { -        int k, j = 0; -        snprintf(channels, 100, " chan ("); -        j = strlen(channels); -        for(k = 0; k < DIVERSITY_HOPS; k++) { -            if(route->channels[k] == 0) -                break; -            if(k > 0) -                channels[j++] = ','; -            snprintf(channels + j, 100 - j, "%d", route->channels[k]); -            j = strlen(channels); -        } -        snprintf(channels + j, 100 - j, ")"); -        if(k == 0) -            channels[0] = '\0'; -    } - -    vty_out(vty, -            "%s metric %d refmetric %d id %s seqno %d%s age %d " -            "via %s neigh %s%s%s%s%s", -            format_prefix(route->src->prefix, route->src->plen), -            route_metric(route), route->refmetric, -            format_eui64(route->src->id), -            (int)route->seqno, -            channels, -            (int)(babel_now.tv_sec - route->time), -            route->neigh->ifp->name, -            format_address(route->neigh->address), -            nexthop ? " nexthop " : "", -            nexthop ? format_address(nexthop) : "", -            route->installed ? " (installed)" : -            route_feasible(route) ? " (feasible)" : "", -            VTY_NEWLINE); -} - -static void -show_babel_xroutes_sub (struct xroute *xroute, void *closure) -{ -    struct vty *vty = (struct vty *) closure; -    vty_out(vty, "%s metric %d (exported)%s", -            format_prefix(xroute->prefix, xroute->plen), -            xroute->metric, -            VTY_NEWLINE); -} - -DEFUN (show_babel_database, -       show_babel_database_cmd, -       "show babel database", -       SHOW_STR -       IP_STR -       "Babel information\n" -       "Database information\n" -       "No attributes\n") -{ -    for_all_routes(show_babel_routes_sub, vty); -    for_all_xroutes(show_babel_xroutes_sub, vty); -    return CMD_SUCCESS; -} - -DEFUN (show_babel_parameters, -       show_babel_parameters_cmd, -       "show babel parameters", -       SHOW_STR -       IP_STR -       "Babel information\n" -       "Configuration information\n" -       "No attributes\n") -{ -    vty_out(vty, "    -- Babel running configuration --%s", VTY_NEWLINE); -    show_babel_main_configuration(vty); -    vty_out(vty, "    -- distribution lists --%s", VTY_NEWLINE); -    config_show_distribute(vty); - -    return CMD_SUCCESS; -} - -void -babel_if_init () -{ -    /* initialize interface list */ -    vrf_init(); -    if_add_hook (IF_NEW_HOOK,    babel_if_new_hook); -    if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook); - -    babel_enable_if = vector_init (1); - -    /* install interface node and commands */ -    install_element (CONFIG_NODE, &interface_cmd); -    install_element (CONFIG_NODE, &no_interface_cmd); -    install_node (&babel_interface_node, interface_config_write); -    install_default(INTERFACE_NODE); -    install_element(INTERFACE_NODE, &interface_cmd); -    install_element(INTERFACE_NODE, &no_interface_cmd); - -    install_element(BABEL_NODE, &babel_network_cmd); -    install_element(BABEL_NODE, &no_babel_network_cmd); -    install_element(INTERFACE_NODE, &babel_split_horizon_cmd); -    install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd); -    install_element(INTERFACE_NODE, &babel_set_wired_cmd); -    install_element(INTERFACE_NODE, &babel_set_wireless_cmd); -    install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd); -    install_element(INTERFACE_NODE, &babel_set_update_interval_cmd); - -    /* "show babel ..." commands */ -    install_element(VIEW_NODE, &show_babel_interface_cmd); -    install_element(ENABLE_NODE, &show_babel_interface_cmd); -    install_element(VIEW_NODE, &show_babel_neighbour_cmd); -    install_element(ENABLE_NODE, &show_babel_neighbour_cmd); -    install_element(VIEW_NODE, &show_babel_database_cmd); -    install_element(ENABLE_NODE, &show_babel_database_cmd); -    install_element(VIEW_NODE, &show_babel_parameters_cmd); -    install_element(ENABLE_NODE, &show_babel_parameters_cmd); -} - -/* hooks: functions called respectively when struct interface is - created or deleted. */ -static int -babel_if_new_hook (struct interface *ifp) -{ -    ifp->info = babel_interface_allocate(); -    return 0; -} - -static int -babel_if_delete_hook (struct interface *ifp) -{ -    babel_interface_free(ifp->info); -    ifp->info = NULL; -    return 0; -} - -/* Output an "interface" section for each of the known interfaces with -babeld-specific statement lines where appropriate. */ -static int -interface_config_write (struct vty *vty) -{ -    struct listnode *node; -    struct interface *ifp; -    int write = 0; - -    for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) { -        vty_out (vty, "interface %s%s", ifp->name, -                 VTY_NEWLINE); -        if (ifp->desc) -            vty_out (vty, " description %s%s", ifp->desc, -                     VTY_NEWLINE); -        if (IS_ENABLE (ifp)) -        { -            babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp); -            /* wireless/no split-horizon is the default */ -            if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED)) -            { -                vty_out (vty, " babel wired%s", VTY_NEWLINE); -                write++; -            } -            if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON)) -            { -                vty_out (vty, " babel split-horizon%s", VTY_NEWLINE); -                write++; -            } -            if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL) -            { -                vty_out (vty, " babel hello-interval %u%s", babel_ifp->hello_interval, VTY_NEWLINE); -                write++; -            } -            if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL) -            { -                vty_out (vty, " babel update-interval %u%s", babel_ifp->update_interval, VTY_NEWLINE); -                write++; -            } -        } -        vty_out (vty, "!%s", VTY_NEWLINE); -        write++; -    } -    return write; -} - -/* Output a "network" statement line for each of the enabled interfaces. */ -int -babel_enable_if_config_write (struct vty * vty) -{ -    unsigned int i, lines = 0; -    char *str; - -    for (i = 0; i < vector_active (babel_enable_if); i++) -        if ((str = vector_slot (babel_enable_if, i)) != NULL) -        { -            vty_out (vty, " network %s%s", str, VTY_NEWLINE); -            lines++; -        } -    return lines; -} - -/* functions to allocate or free memory for a babel_interface_nfo, filling - needed fields */ -static babel_interface_nfo * -babel_interface_allocate (void) -{ -    babel_interface_nfo *babel_ifp; -    babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo)); -    if(babel_ifp == NULL) -        return NULL; - -    /* Here are set the default values for an interface. */ -    memset(babel_ifp, 0, sizeof(babel_interface_nfo)); -    /* All flags are unset */ -    babel_ifp->bucket_time = babel_now.tv_sec; -    babel_ifp->bucket = BUCKET_TOKENS_MAX; -    babel_ifp->hello_seqno = (random() & 0xFFFF); -    babel_ifp->hello_interval = BABEL_DEFAULT_HELLO_INTERVAL; -    babel_ifp->update_interval = BABEL_DEFAULT_UPDATE_INTERVAL; -    babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING; -    babel_set_wired_internal(babel_ifp, 0); - -    return babel_ifp; -} - -static void -babel_interface_free (babel_interface_nfo *babel_ifp) -{ -    XFREE(MTYPE_BABEL_IF, babel_ifp); -} diff --git a/babeld/babel_interface.h b/babeld/babel_interface.h deleted file mode 100644 index e0d53d6ef4..0000000000 --- a/babeld/babel_interface.h +++ /dev/null @@ -1,152 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef BABEL_INTERFACE_H -#define BABEL_INTERFACE_H - -#include <zebra.h> -#include "zclient.h" -#include "vty.h" - -#define CONFIG_DEFAULT 0 -#define CONFIG_NO 1 -#define CONFIG_YES 2 - -/* babeld interface informations */ -struct babel_interface { -    unsigned short flags;                     /* see below */ -    unsigned short cost; -    int channel; -    struct timeval hello_timeout; -    struct timeval update_timeout; -    struct timeval flush_timeout; -    struct timeval update_flush_timeout; -    unsigned char *ipv4; -    int buffered; -    int bufsize; -    char have_buffered_hello; -    char have_buffered_id; -    char have_buffered_nh; -    char have_buffered_prefix; -    unsigned char buffered_id[16]; -    unsigned char buffered_nh[4]; -    unsigned char buffered_prefix[16]; -    unsigned char *sendbuf; -    struct buffered_update *buffered_updates; -    int num_buffered_updates; -    int update_bufsize; -    time_t bucket_time; -    unsigned int bucket; -    time_t last_update_time; -    unsigned short hello_seqno; -    unsigned hello_interval; -    unsigned update_interval; - -    /* For filter type slot. */ -#define BABEL_FILTER_IN  0 -#define BABEL_FILTER_OUT 1 -#define BABEL_FILTER_MAX 2 -    struct access_list *list[BABEL_FILTER_MAX];               /* Access-list. */ -    struct prefix_list *prefix[BABEL_FILTER_MAX];             /* Prefix-list. */ -}; - -typedef struct babel_interface babel_interface_nfo; -static inline babel_interface_nfo* babel_get_if_nfo(struct interface *ifp) -{ -    return ((babel_interface_nfo*) ifp->info); -} - -/* babel_interface_nfo flags */ -#define BABEL_IF_IS_UP         (1 << 0) -#define BABEL_IF_WIRED         (1 << 1) -#define BABEL_IF_SPLIT_HORIZON (1 << 2) -#define BABEL_IF_LQ            (1 << 3) -#define BABEL_IF_FARAWAY       (1 << 4) - -/* Only INTERFERING can appear on the wire. */ -#define BABEL_IF_CHANNEL_UNKNOWN 0 -#define BABEL_IF_CHANNEL_INTERFERING 255 -#define BABEL_IF_CHANNEL_NONINTERFERING -2 - -static inline int -if_up(struct interface *ifp) -{ -    return (if_is_operative(ifp) && -            ifp->connected != NULL && -            (babel_get_if_nfo(ifp)->flags & BABEL_IF_IS_UP)); -} - -/* types: - struct interface _ifp, struct listnode node */ -#define FOR_ALL_INTERFACES(_ifp, _node)                                              \ -    for(ALL_LIST_ELEMENTS_RO(iflist, _node, _ifp)) - -/* types: - struct interface *ifp, struct connected *_connected, struct listnode *node */ -#define FOR_ALL_INTERFACES_ADDRESSES(ifp, _connected, _node)                   \ -    for(ALL_LIST_ELEMENTS_RO(ifp->connected, _node, _connected)) - -struct buffered_update { -    unsigned char id[8]; -    unsigned char prefix[16]; -    unsigned char plen; -    unsigned char pad[3]; -}; - - -/* init function */ -void babel_if_init(void); - -/* Callback functions for zebra client */ -int babel_interface_up (int, struct zclient *, zebra_size_t, vrf_id_t); -int babel_interface_down (int, struct zclient *, zebra_size_t, vrf_id_t); -int babel_interface_add (int, struct zclient *, zebra_size_t, vrf_id_t); -int babel_interface_delete (int, struct zclient *, zebra_size_t, vrf_id_t); -int babel_interface_address_add (int, struct zclient *, zebra_size_t, vrf_id_t); -int babel_interface_address_delete (int, struct zclient *, zebra_size_t, vrf_id_t); - -unsigned jitter(babel_interface_nfo *, int); -unsigned update_jitter(babel_interface_nfo *babel_ifp, int urgent); -/* return "true" if "address" is one of our ipv6 addresses */ -int is_interface_ll_address(struct interface *ifp, const unsigned char *address); -/* Send retraction to all, and reset all interfaces statistics. */ -void babel_interface_close_all(void); -extern int babel_enable_if_config_write (struct vty *); - - -#endif diff --git a/babeld/babel_main.c b/babeld/babel_main.c deleted file mode 100644 index 21b2513d70..0000000000 --- a/babeld/babel_main.c +++ /dev/null @@ -1,533 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   - -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* include zebra library */ -#include <zebra.h> -#include "getopt.h" -#include "if.h" -#include "log.h" -#include "thread.h" -#include "privs.h" -#include "sigevent.h" -#include "version.h" -#include "command.h" -#include "vty.h" -#include "memory.h" -#include "systemd.h" - -#include "babel_main.h" -#include "babeld.h" -#include "util.h" -#include "kernel.h" -#include "babel_interface.h" -#include "neighbour.h" -#include "route.h" -#include "xroute.h" -#include "message.h" -#include "resend.h" -#include "babel_zebra.h" - - -static void babel_init (int argc, char **argv); -static char *babel_get_progname(char *argv_0); -static void babel_fail(void); -static void babel_init_random(void); -static void babel_replace_by_null(int fd); -static void babel_init_signals(void); -static void babel_exit_properly(void); -static void babel_save_state_file(void); - - -struct thread_master *master;     /* quagga's threads handler */ -struct timeval babel_now;         /* current time             */ - -unsigned char myid[8];            /* unique id (mac address of an interface) */ -int debug = 0; - -int resend_delay = -1; -static const char *pidfile = PATH_BABELD_PID; - -const unsigned char zeroes[16] = {0}; -const unsigned char ones[16] = -    {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - -static const char *state_file = DAEMON_VTY_DIR "/babel-state"; - -unsigned char protocol_group[16]; /* babel's link-local multicast address */ -int protocol_port;                /* babel's port */ -int protocol_socket = -1;         /* socket: communicate with others babeld */ - -static char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG; -static char *babel_config_file = NULL; -static char *babel_vty_addr = NULL; -static int babel_vty_port = BABEL_VTY_PORT; - -/* Babeld options. */ -struct option longopts[] = -{ -    { "daemon",      no_argument,       NULL, 'd'}, -    { "config_file", required_argument, NULL, 'f'}, -    { "pid_file",    required_argument, NULL, 'i'}, -    { "socket",      required_argument, NULL, 'z'}, -    { "help",        no_argument,       NULL, 'h'}, -    { "vty_addr",    required_argument, NULL, 'A'}, -    { "vty_port",    required_argument, NULL, 'P'}, -    { "user",        required_argument, NULL, 'u'}, -    { "group",       required_argument, NULL, 'g'}, -    { "version",     no_argument,       NULL, 'v'}, -    { 0 } -}; - -/* babeld privileges */ -static zebra_capabilities_t _caps_p [] = -{ -    ZCAP_NET_RAW, -    ZCAP_BIND -}; -static struct zebra_privs_t babeld_privs = -{ -#if defined(QUAGGA_USER) -    .user = QUAGGA_USER, -#endif -#if defined QUAGGA_GROUP -    .group = QUAGGA_GROUP, -#endif -#ifdef VTY_GROUP -    .vty_group = VTY_GROUP, -#endif -    .caps_p = _caps_p, -    .cap_num_p = 2, -    .cap_num_i = 0 -}; - - -int -main(int argc, char **argv) -{ -    struct thread thread; -    /* and print banner too */ -    babel_init(argc, argv); -    while (thread_fetch (master, &thread)) { -        thread_call (&thread); -    } -    return 0; -} - -static void -babel_usage (char *progname, int status) -{ -  if (status != 0) -    fprintf (stderr, "Try `%s --help' for more information.\n", progname); -  else -    { -      printf ("Usage : %s [OPTION...]\n\ -Daemon which manages Babel routing protocol.\n\n\ --d, --daemon       Runs in daemon mode\n\ --f, --config_file  Set configuration file name\n\ --i, --pid_file     Set process identifier file name\n\ --z, --socket       Set path of zebra socket\n\ --A, --vty_addr     Set vty's bind address\n\ --P, --vty_port     Set vty's port number\n\ --u, --user         User to run as\n\ --g, --group        Group to run as\n\ --v, --version      Print program version\n\ --h, --help         Display this help and exit\n\ -\n\ -Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS); -    } -  exit (status); -} - -/* make initialisations witch don't need infos about kernel(interfaces, etc.) */ -static void -babel_init(int argc, char **argv) -{ -    int rc, opt; -    int do_daemonise = 0; -    char *progname = NULL; - -    /* Set umask before anything for security */ -    umask (0027); -    progname = babel_get_progname(argv[0]); - -    /* set default log (lib/log.h) */ -    zlog_default = openzlog(progname, ZLOG_BABEL, 0, -                            LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); -    /* set log destination as stdout until the config file is read */ -    zlog_set_level(NULL, ZLOG_DEST_STDOUT, LOG_WARNING); - -    babel_init_random(); - -    /* set the Babel's default link-local multicast address and Babel's port */ -    parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL); -    protocol_port = 6696; - -    /* get options */ -    while(1) { -        opt = getopt_long(argc, argv, "df:i:z:hA:P:u:g:v", longopts, 0); -        if(opt < 0) -            break; - -        switch(opt) { -            case 0: -                break; -            case 'd': -                do_daemonise = -1; -                break; -            case 'f': -                babel_config_file = optarg; -                break; -            case 'i': -                pidfile = optarg; -                break; -            case 'z': -                zclient_serv_path_set (optarg); -                break; -            case 'A': -                babel_vty_addr = optarg; -                break; -            case 'P': -                babel_vty_port = atoi (optarg); -                if (babel_vty_port <= 0 || babel_vty_port > 0xffff) -                    babel_vty_port = BABEL_VTY_PORT; -                break; -            case 'u': -                babeld_privs.user = optarg; -                break; -            case 'g': -                babeld_privs.group = optarg; -                break; -            case 'v': -                print_version (progname); -                exit (0); -                break; -            case 'h': -                babel_usage (progname, 0); -                break; -            default: -                babel_usage (progname, 1); -                break; -        } -    } - -    /* create the threads handler */ -    master = thread_master_create (); - -    /* Library inits. */ -    zprivs_init (&babeld_privs); -    babel_init_signals(); -    cmd_init (1); -    vty_init (master); -    memory_init (); - -    resend_delay = BABEL_DEFAULT_RESEND_DELAY; - -    babel_replace_by_null(STDIN_FILENO); - -    if (do_daemonise && daemonise() < 0) { -        zlog_err("daemonise: %s", safe_strerror(errno)); -        exit (1); -    } - -    /* write pid file */ -    if (pid_output(pidfile) < 0) { -        zlog_err("error while writing pidfile"); -        exit (1); -    }; - -    systemd_send_started (master); -    /* init some quagga's dependencies, and babeld's commands */ -    babeld_quagga_init(); -    /* init zebra client's structure and it's commands */ -    /* this replace kernel_setup && kernel_setup_socket */ -    babelz_zebra_init(master); - -    /* Get zebra configuration file. */ -    zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED); -    vty_read_config (babel_config_file, babel_config_default); - -    /* Create VTY socket */ -    vty_serv_sock (babel_vty_addr, babel_vty_port, BABEL_VTYSH_PATH); - -    /* init buffer */ -    rc = resize_receive_buffer(1500); -    if(rc < 0) -        babel_fail(); - -    schedule_neighbours_check(5000, 1); - -    zlog_notice ("BABELd %s starting: vty@%d", BABEL_VERSION, babel_vty_port); -} - -/* return the progname (without path, example: "./x/progname" --> "progname") */ -static char * -babel_get_progname(char *argv_0) { -    char *p = strrchr (argv_0, '/'); -    return (p ? ++p : argv_0); -} - -static void -babel_fail(void) -{ -    systemd_send_stopping (); -    exit(1); -} - -/* initialize random value, and set 'babel_now' by the way. */ -static void -babel_init_random(void) -{ -    gettime(&babel_now); -    int rc; -    unsigned int seed; - -    rc = read_random_bytes(&seed, sizeof(seed)); -    if(rc < 0) { -        zlog_err("read(random): %s", safe_strerror(errno)); -        seed = 42; -    } - -    seed ^= (babel_now.tv_sec ^ babel_now.tv_usec); -    srandom(seed); -} - -/* - close fd, and replace it by "/dev/null" - exit if error - */ -static void -babel_replace_by_null(int fd) -{ -    int fd_null; -    int rc; - -    fd_null = open("/dev/null", O_RDONLY); -    if(fd_null < 0) { -        zlog_err("open(null): %s", safe_strerror(errno)); -        exit(1); -    } - -    rc = dup2(fd_null, fd); -    if(rc < 0) { -        zlog_err("dup2(null, 0): %s", safe_strerror(errno)); -        exit(1); -    } - -    close(fd_null); -} - -/* - Load the state file: check last babeld's running state, usefull in case of - "/etc/init.d/babeld restart" - */ -void -babel_load_state_file(void) -{ -    int fd; -    int rc; - -    fd = open(state_file, O_RDONLY); -    if(fd < 0 && errno != ENOENT) -        zlog_err("open(babel-state: %s)", safe_strerror(errno)); -    rc = unlink(state_file); -    if(fd >= 0 && rc < 0) { -        zlog_err("unlink(babel-state): %s", safe_strerror(errno)); -        /* If we couldn't unlink it, it's probably stale. */ -        close(fd); -        fd = -1; -    } -    if(fd >= 0) { -        char buf[100]; -        char buf2[100]; -        int s; -        long t; -        rc = read(fd, buf, 99); -        if(rc < 0) { -            zlog_err("read(babel-state): %s", safe_strerror(errno)); -        } else { -            buf[rc] = '\0'; -            rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t); -            if(rc == 3 && s >= 0 && s <= 0xFFFF) { -                unsigned char sid[8]; -                rc = parse_eui64(buf2, sid); -                if(rc < 0) { -                    zlog_err("Couldn't parse babel-state."); -                } else { -                    struct timeval realnow; -                    debugf(BABEL_DEBUG_COMMON, -                           "Got %s %d %ld from babel-state.", -                           format_eui64(sid), s, t); -                    gettimeofday(&realnow, NULL); -                    if(memcmp(sid, myid, 8) == 0) -                        myseqno = seqno_plus(s, 1); -                    else -                        zlog_err("ID mismatch in babel-state. id=%s; old=%s", -                                 format_eui64(myid), -                                 format_eui64(sid)); -                } -            } else { -                zlog_err("Couldn't parse babel-state."); -            } -        } -        close(fd); -        fd = -1; -    } -} - -static void -babel_sigexit(void) -{ -    zlog_notice("Terminating on signal"); - -    babel_exit_properly(); -} - -static void -babel_sigusr1 (void) -{ -    zlog_rotate (NULL); -} - -static void -babel_init_signals(void) -{ -    static struct quagga_signal_t babel_signals[] = -    { -        { -            .signal = SIGUSR1, -            .handler = &babel_sigusr1, -        }, -        { -            .signal = SIGINT, -            .handler = &babel_sigexit, -        }, -        { -            .signal = SIGTERM, -            .handler = &babel_sigexit, -        }, -    }; - -    signal_init (master, array_size(babel_signals), babel_signals); -} - -static void -babel_exit_properly(void) -{ -    debugf(BABEL_DEBUG_COMMON, "Exiting..."); -    usleep(roughly(10000)); -    gettime(&babel_now); - -    /* Uninstall and flush all routes. */ -    debugf(BABEL_DEBUG_COMMON, "Uninstall routes."); -    flush_all_routes(); -    babel_interface_close_all(); -    babel_zebra_close_connexion(); -    babel_save_state_file(); -    debugf(BABEL_DEBUG_COMMON, "Remove pid file."); -    if(pidfile) -        unlink(pidfile); -    debugf(BABEL_DEBUG_COMMON, "Done."); - -    systemd_send_stopping (); -    exit(0); -} - -static void -babel_save_state_file(void) -{ -    int fd; -    int rc; - -    debugf(BABEL_DEBUG_COMMON, "Save state file."); -    fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644); -    if(fd < 0) { -        zlog_err("creat(babel-state): %s", safe_strerror(errno)); -        unlink(state_file); -    } else { -        struct timeval realnow; -        char buf[100]; -        gettimeofday(&realnow, NULL); -        rc = snprintf(buf, 100, "%s %d %ld\n", -                      format_eui64(myid), (int)myseqno, -                      (long)realnow.tv_sec); -        if(rc < 0 || rc >= 100) { -            zlog_err("write(babel-state): overflow."); -            unlink(state_file); -        } else { -            rc = write(fd, buf, rc); -            if(rc < 0) { -                zlog_err("write(babel-state): %s", safe_strerror(errno)); -                unlink(state_file); -            } -            fsync(fd); -        } -        close(fd); -    } -} - -void -show_babel_main_configuration (struct vty *vty) -{ -    vty_out(vty, -            "pid file                = %s%s" -            "state file              = %s%s" -            "configuration file      = %s%s" -            "protocol informations:%s" -            "  multicast address     = %s%s" -            "  port                  = %d%s" -            "vty address             = %s%s" -            "vty port                = %d%s" -            "id                      = %s%s" -            "allow_duplicates        = %s%s" -            "kernel_metric           = %d%s", -            pidfile, VTY_NEWLINE, -            state_file, VTY_NEWLINE, -            babel_config_file ? babel_config_file : babel_config_default, -            VTY_NEWLINE, -            VTY_NEWLINE, -            format_address(protocol_group), VTY_NEWLINE, -            protocol_port, VTY_NEWLINE, -            babel_vty_addr ? babel_vty_addr : "None", -            VTY_NEWLINE, -            babel_vty_port, VTY_NEWLINE, -            format_eui64(myid), VTY_NEWLINE, -            format_bool(allow_duplicates), VTY_NEWLINE, -            kernel_metric, VTY_NEWLINE); -} diff --git a/babeld/babel_main.h b/babeld/babel_main.h deleted file mode 100644 index a4038decb3..0000000000 --- a/babeld/babel_main.h +++ /dev/null @@ -1,57 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include "vty.h" - -extern struct timeval babel_now;         /* current time             */ -extern struct thread_master *master;     /* quagga's threads handler */ -extern int debug; -extern int resend_delay; - -extern unsigned char myid[8]; - -extern const unsigned char zeroes[16], ones[16]; - -extern int protocol_port; -extern unsigned char protocol_group[16]; -extern int protocol_socket; -extern int kernel_socket; -extern int max_request_hopcount; - -void babel_load_state_file(void); -void show_babel_main_configuration (struct vty *vty); diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c deleted file mode 100644 index 5ae35ec5cd..0000000000 --- a/babeld/babel_zebra.c +++ /dev/null @@ -1,388 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - * -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* quagga's includes */ -#include <zebra.h> -#include "command.h" -#include "zclient.h" -#include "stream.h" - -/* babel's includes*/ -#include "babel_zebra.h" -#include "babel_interface.h" -#include "xroute.h" -#include "util.h" - -/* we must use a pointer because of zclient.c's functions (new, free). */ -struct zclient *zclient; -static int zebra_config_write (struct vty *vty); - -/* Debug types */ -static struct { -    int type; -    int str_min_len; -    const char *str; -} debug_type[] = { -    {BABEL_DEBUG_COMMON,  1, "common"}, -    {BABEL_DEBUG_KERNEL,  1, "kernel"}, -    {BABEL_DEBUG_FILTER,  1, "filter"}, -    {BABEL_DEBUG_TIMEOUT, 1, "timeout"}, -    {BABEL_DEBUG_IF,      1, "interface"}, -    {BABEL_DEBUG_ROUTE,   1, "route"}, -    {BABEL_DEBUG_ALL,     1, "all"}, -    {0, 0, NULL} -}; - -/* Zebra node structure. */ -struct cmd_node zebra_node = -{ -    ZEBRA_NODE, -    "%s(config-router)# ", -    1 /* vtysh? yes */ -}; - - -/* Zebra route add and delete treatment (ipv6). */ -static int -babel_zebra_read_ipv6 (int command, struct zclient *zclient, -		       zebra_size_t length, vrf_id_t vrf_id) -{ -    struct stream *s; -    struct zapi_ipv6 api; -    unsigned long ifindex = -1; -    struct in6_addr nexthop; -    struct prefix_ipv6 prefix; - -    s = zclient->ibuf; -    ifindex = 0; -    memset (&nexthop, 0, sizeof (struct in6_addr)); -    memset (&api, 0, sizeof(struct zapi_ipv6)); -    memset (&prefix, 0, sizeof (struct prefix_ipv6)); - -    /* Type, flags, message. */ -    api.type = stream_getc (s); -    api.instance = stream_getw (s); -    api.flags = stream_getc (s); -    api.message = stream_getc (s); - -    /* IPv6 prefix. */ -    prefix.family = AF_INET6; -    prefix.prefixlen = stream_getc (s); -    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); - -    /* Nexthop, ifindex, distance, metric. */ -    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { -        api.nexthop_num = stream_getc (s); -        stream_get (&nexthop, s, sizeof(nexthop)); -    } -    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { -        api.ifindex_num = stream_getc (s); -        ifindex = stream_getl (s); -    } -    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) -        api.distance = stream_getc (s); -    else -        api.distance = 0; -    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) -        api.metric = stream_getl (s); -    else -        api.metric = 0; - -    if (command == ZEBRA_IPV6_ROUTE_ADD) -        babel_ipv6_route_add(&api, &prefix, ifindex, &nexthop); -    else -        babel_ipv6_route_delete(&api, &prefix, ifindex); - -    return 0; -} - -static int -babel_zebra_read_ipv4 (int command, struct zclient *zclient, -		       zebra_size_t length, vrf_id_t vrf_id) -{ -    struct stream *s; -    struct zapi_ipv4 api; -    unsigned long ifindex = -1; -    struct in_addr nexthop; -    struct prefix_ipv4 prefix; - -    s = zclient->ibuf; -    ifindex = 0; -    memset (&nexthop, 0, sizeof (struct in_addr)); -    memset (&api, 0, sizeof(struct zapi_ipv4)); -    memset (&prefix, 0, sizeof (struct prefix_ipv4)); - -    /* Type, flags, message. */ -    api.type = stream_getc (s); -    api.instance = stream_getw (s); -    api.flags = stream_getc (s); -    api.message = stream_getc (s); - -    /* IPv6 prefix. */ -    prefix.family = AF_INET; -    prefix.prefixlen = stream_getc (s); -    stream_get (&prefix.prefix, s, PSIZE (prefix.prefixlen)); - -    /* Nexthop, ifindex, distance, metric. */ -    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { -        api.nexthop_num = stream_getc (s); -        stream_get (&nexthop, s, sizeof(nexthop)); -    } -    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { -        api.ifindex_num = stream_getc (s); -        ifindex = stream_getl (s); -    } -    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) -        api.distance = stream_getc (s); -    else -        api.distance = 0; -    if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) -        api.metric = stream_getl (s); -    else -        api.metric = 0; - -    if (command == ZEBRA_IPV6_ROUTE_ADD) { -        babel_ipv4_route_add(&api, &prefix, ifindex, &nexthop); -    } else { -        babel_ipv4_route_delete(&api, &prefix, ifindex); -    } - -    return 0; -} - -/* [Babel Command] */ -DEFUN (babel_redistribute_type, -       babel_redistribute_type_cmd, -       "redistribute " QUAGGA_REDIST_STR_BABELD, -       "Redistribute\n" -       QUAGGA_REDIST_HELP_STR_BABELD) -{ -    int type; -    afi_t afi; - -    afi = AFI_IP6; -    type = proto_redistnum(afi, argv[0]); - -    if (type < 0) -      { -        afi = AFI_IP; -        type = proto_redistnum(afi, argv[0]); -      } - -    if (type < 0) { -        vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); -        return CMD_WARNING; -    } - -    zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, 0, VRF_DEFAULT); -    return CMD_SUCCESS; -} - -/* [Babel Command] */ -DEFUN (no_babel_redistribute_type, -       no_babel_redistribute_type_cmd, -       "no redistribute " QUAGGA_REDIST_STR_BABELD, -       NO_STR -       "Redistribute\n" -       QUAGGA_REDIST_HELP_STR_BABELD) -{ -    int type; -    afi_t afi; - -    afi = AFI_IP6; -    type = proto_redistnum(afi, argv[0]); - -    if (type < 0) -      { -        afi = AFI_IP; -        type = proto_redistnum(afi, argv[0]); -      } - -    if (type < 0) { -        vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); -        return CMD_WARNING; -    } - -    zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, 0, VRF_DEFAULT); -    /* perhaps should we remove xroutes having the same type... */ -    return CMD_SUCCESS; -} - -#ifndef NO_DEBUG -/* [Babel Command] */ -DEFUN (debug_babel, -       debug_babel_cmd, -       "debug babel (common|kernel|filter|timeout|interface|route|all)", -       "Enable debug messages for specific or all part.\n" -       "Babel information\n" -       "Common messages (default)\n" -       "Kernel messages\n" -       "Filter messages\n" -       "Timeout messages\n" -       "Interface messages\n" -       "Route messages\n" -       "All messages\n") -{ -    int i; - -    for(i = 0; debug_type[i].str != NULL; i++) { -        if (strncmp (debug_type[i].str, argv[0], -                     debug_type[i].str_min_len) == 0) { -            debug |= debug_type[i].type; -            return CMD_SUCCESS; -        } -    } - -    vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); - -    return CMD_WARNING; -} - -/* [Babel Command] */ -DEFUN (no_debug_babel, -       no_debug_babel_cmd, -       "no debug babel (common|kernel|filter|timeout|interface|route|all)", -       NO_STR -       "Disable debug messages for specific or all part.\n" -       "Babel information\n" -       "Common messages (default)\n" -       "Kernel messages\n" -       "Filter messages\n" -       "Timeout messages\n" -       "Interface messages\n" -       "Route messages\n" -       "All messages\n") -{ -    int i; - -    for (i = 0; debug_type[i].str; i++) { -        if (strncmp(debug_type[i].str, argv[0], -                    debug_type[i].str_min_len) == 0) { -            debug &= ~debug_type[i].type; -            return CMD_SUCCESS; -        } -    } - -    vty_out(vty, "Invalid type %s%s", argv[0], VTY_NEWLINE); - -    return CMD_WARNING; -} -#endif /* NO_DEBUG */ - -/* Output "debug" statement lines, if necessary. */ -int -debug_babel_config_write (struct vty * vty) -{ -#ifdef NO_DEBUG -    return 0; -#else -    int i, lines = 0; - -    if (debug == BABEL_DEBUG_ALL) -    { -        vty_out (vty, "debug babel all%s", VTY_NEWLINE); -        lines++; -    } -    else -        for (i = 0; debug_type[i].str != NULL; i++) -            if -            ( -                debug_type[i].type != BABEL_DEBUG_ALL -                && CHECK_FLAG (debug, debug_type[i].type) -            ) -            { -                vty_out (vty, "debug babel %s%s", debug_type[i].str, VTY_NEWLINE); -                lines++; -            } -    if (lines) -    { -        vty_out (vty, "!%s", VTY_NEWLINE); -        lines++; -    } -    return lines; -#endif /* NO_DEBUG */ -} - -void babelz_zebra_init (struct thread_master *master) -{ -    zclient = zclient_new(master); -    zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0); - -    zclient->interface_add = babel_interface_add; -    zclient->interface_delete = babel_interface_delete; -    zclient->interface_up = babel_interface_up; -    zclient->interface_down = babel_interface_down; -    zclient->interface_address_add = babel_interface_address_add; -    zclient->interface_address_delete = babel_interface_address_delete; -    zclient->ipv4_route_add = babel_zebra_read_ipv4; -    zclient->ipv4_route_delete = babel_zebra_read_ipv4; -    zclient->ipv6_route_add = babel_zebra_read_ipv6; -    zclient->ipv6_route_delete = babel_zebra_read_ipv6; - -    install_node (&zebra_node, zebra_config_write); -    install_element(BABEL_NODE, &babel_redistribute_type_cmd); -    install_element(BABEL_NODE, &no_babel_redistribute_type_cmd); -    install_element(ENABLE_NODE, &debug_babel_cmd); -    install_element(ENABLE_NODE, &no_debug_babel_cmd); -    install_element(CONFIG_NODE, &debug_babel_cmd); -    install_element(CONFIG_NODE, &no_debug_babel_cmd); -} - -static int -zebra_config_write (struct vty *vty) -{ -    if (! zclient->enable) -    { -        vty_out (vty, "no router zebra%s", VTY_NEWLINE); -        return 1; -    } -    else if (! (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BABEL], VRF_DEFAULT) || -                vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_BABEL], VRF_DEFAULT))) -    { -        vty_out (vty, "router zebra%s", VTY_NEWLINE); -        vty_out (vty, " no redistribute babel%s", VTY_NEWLINE); -        return 1; -    } -    return 0; -} - -void -babel_zebra_close_connexion(void) -{ -    zclient_stop(zclient); -} diff --git a/babeld/babel_zebra.h b/babeld/babel_zebra.h deleted file mode 100644 index 9504faf4fe..0000000000 --- a/babeld/babel_zebra.h +++ /dev/null @@ -1,50 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef BABEL_ZEBRA_H -#define BABEL_ZEBRA_H - -#include "vty.h" - -extern struct zclient *zclient; - -void babelz_zebra_init(struct thread_master *); -void babel_zebra_close_connexion(void); -extern int debug_babel_config_write (struct vty *); - -#endif diff --git a/babeld/babeld.c b/babeld/babeld.c deleted file mode 100644 index 9e0018ad25..0000000000 --- a/babeld/babeld.c +++ /dev/null @@ -1,732 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   - -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <zebra.h> -#include "command.h" -#include "prefix.h" -#include "memory.h" -#include "memtypes.h" -#include "table.h" -#include "distribute.h" -#include "prefix.h" -#include "filter.h" -#include "plist.h" - -#include "babel_main.h" -#include "babeld.h" -#include "util.h" -#include "net.h" -#include "kernel.h" -#include "babel_interface.h" -#include "neighbour.h" -#include "route.h" -#include "message.h" -#include "resend.h" -#include "babel_filter.h" -#include "babel_zebra.h" -#include "vrf.h" - - -static int babel_init_routing_process(struct thread *thread); -static void babel_get_myid(void); -static void babel_initial_noise(void); -static int babel_read_protocol (struct thread *thread); -static int babel_main_loop(struct thread *thread); -static void babel_set_timer(struct timeval *timeout); -static void babel_fill_with_next_timeout(struct timeval *tv); - - -/* Informations relative to the babel running daemon. */ -static struct babel *babel_routing_process = NULL; -static unsigned char *receive_buffer = NULL; -static int receive_buffer_size = 0; - -/* timeouts */ -struct timeval check_neighbours_timeout; -static time_t expiry_time; -static time_t source_expiry_time; - -/* Babel node structure. */ -static struct cmd_node cmd_babel_node = -{ -    .node   = BABEL_NODE, -    .prompt = "%s(config-router)# ", -    .vtysh  = 1, -}; - -/* print current babel configuration on vty */ -static int -babel_config_write (struct vty *vty) -{ -    int lines = 0; -    int i; -    afi_t afi; - -    /* list enabled debug modes */ -    lines += debug_babel_config_write (vty); - -    if (!babel_routing_process) -        return lines; -    vty_out (vty, "router babel%s", VTY_NEWLINE); -    if (resend_delay != BABEL_DEFAULT_RESEND_DELAY) -    { -        vty_out (vty, " babel resend-delay %u%s", resend_delay, VTY_NEWLINE); -        lines++; -    } -    /* list enabled interfaces */ -    lines = 1 + babel_enable_if_config_write (vty); -    /* list redistributed protocols */ -    for (afi = AFI_IP; afi < AFI_MAX; afi++) -      for (i = 0; i < ZEBRA_ROUTE_MAX; i++) -        if (i != zclient->redist_default && -            vrf_bitmap_check (zclient->redist[afi][i], VRF_DEFAULT) ) -          { -            vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE); -            lines++; -          } - -    return lines; -} - - -static int -babel_create_routing_process (void) -{ -    assert (babel_routing_process == NULL); - -    /* Allocaste Babel instance. */ -    babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel)); - -    /* Initialize timeouts */ -    gettime(&babel_now); -    expiry_time = babel_now.tv_sec + roughly(30); -    source_expiry_time = babel_now.tv_sec + roughly(300); - -    /* Make socket for Babel protocol. */ -    protocol_socket = babel_socket(protocol_port); -    if (protocol_socket < 0) { -        zlog_err("Couldn't create link local socket: %s", safe_strerror(errno)); -        goto fail; -    } - -    /* Threads. */ -    babel_routing_process->t_read = -    thread_add_read(master, &babel_read_protocol, NULL, protocol_socket); -    /* wait a little: zebra will announce interfaces, addresses, routes... */ -    babel_routing_process->t_update = -    thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L); -    return 0; - -fail: -    XFREE(MTYPE_BABEL, babel_routing_process); -    babel_routing_process = NULL; -    return -1; -} - -/* thread reading entries form others babel daemons */ -static int -babel_read_protocol (struct thread *thread) -{ -    int rc; -    struct interface *ifp = NULL; -    struct sockaddr_in6 sin6; -    struct listnode *linklist_node = NULL; - -    assert(babel_routing_process != NULL); -    assert(protocol_socket >= 0); - -    rc = babel_recv(protocol_socket, -                    receive_buffer, receive_buffer_size, -                    (struct sockaddr*)&sin6, sizeof(sin6)); -    if(rc < 0) { -        if(errno != EAGAIN && errno != EINTR) { -            zlog_err("recv: %s", safe_strerror(errno)); -        } -    } else { -        FOR_ALL_INTERFACES(ifp, linklist_node) { -            if(!if_up(ifp)) -                continue; -            if(ifp->ifindex == sin6.sin6_scope_id) { -                parse_packet((unsigned char*)&sin6.sin6_addr, ifp, -                             receive_buffer, rc); -                break; -            } -        } -    } - -    /* re-add thread */ -    babel_routing_process->t_read = -    thread_add_read(master, &babel_read_protocol, NULL, protocol_socket); -    return 0; -} - -/* Zebra will give some information, especially about interfaces. This function - must be call with a litte timeout wich may give zebra the time to do his job, - making these inits have sense. */ -static int -babel_init_routing_process(struct thread *thread) -{ -    myseqno = (random() & 0xFFFF); -    babel_get_myid(); -    babel_load_state_file(); -    debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid)); -    babel_initial_noise(); -    babel_main_loop(thread);/* this function self-add to the t_update thread */ -    return 0; -} - -/* fill "myid" with an unique id (only if myid != {0}). */ -static void -babel_get_myid(void) -{ -    struct interface *ifp = NULL; -    struct listnode *linklist_node = NULL; -    int rc; -    int i; - -    /* if we already have an id (from state file), we return. */ -    if (memcmp(myid, zeroes, 8) != 0) { -        return; -    } - -    FOR_ALL_INTERFACES(ifp, linklist_node) { -        /* ifp->ifindex is not necessarily valid at this point */ -        int ifindex = if_nametoindex(ifp->name); -        if(ifindex > 0) { -            unsigned char eui[8]; -            rc = if_eui64(ifp->name, ifindex, eui); -            if(rc < 0) -                continue; -            memcpy(myid, eui, 8); -            return; -        } -    } - -    /* We failed to get a global EUI64 from the interfaces we were given. -     Let's try to find an interface with a MAC address. */ -    for(i = 1; i < 256; i++) { -        char buf[IF_NAMESIZE], *ifname; -        unsigned char eui[8]; -        ifname = if_indextoname(i, buf); -        if(ifname == NULL) -            continue; -        rc = if_eui64(ifname, i, eui); -        if(rc < 0) -            continue; -        memcpy(myid, eui, 8); -        return; -    } - -    zlog_err("Warning: couldn't find router id -- using random value."); - -    rc = read_random_bytes(myid, 8); -    if(rc < 0) { -        zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno)); -        exit(1); -    } -    /* Clear group and global bits */ -    myid[0] &= ~3; -} - -/* Make some noise so that others notice us, and send retractions in - case we were restarted recently */ -static void -babel_initial_noise(void) -{ -    struct interface *ifp = NULL; -    struct listnode *linklist_node = NULL; - -    FOR_ALL_INTERFACES(ifp, linklist_node) { -        if(!if_up(ifp)) -            continue; -        /* Apply jitter before we send the first message. */ -        usleep(roughly(10000)); -        gettime(&babel_now); -        send_hello(ifp); -        send_wildcard_retraction(ifp); -    } - -    FOR_ALL_INTERFACES(ifp, linklist_node) { -        if(!if_up(ifp)) -            continue; -        usleep(roughly(10000)); -        gettime(&babel_now); -        send_hello(ifp); -        send_wildcard_retraction(ifp); -        send_self_update(ifp); -        send_request(ifp, NULL, 0); -        flushupdates(ifp); -        flushbuf(ifp); -    } -} - -/* Delete all the added babel routes, make babeld only speak to zebra. */ -static void -babel_clean_routing_process() -{ -    flush_all_routes(); -    babel_interface_close_all(); - -    /* cancel threads */ -    if (babel_routing_process->t_read != NULL) { -        thread_cancel(babel_routing_process->t_read); -    } -    if (babel_routing_process->t_update != NULL) { -        thread_cancel(babel_routing_process->t_update); -    } - -    XFREE(MTYPE_BABEL, babel_routing_process); -    babel_routing_process = NULL; -} - -/* Function used with timeout. */ -static int -babel_main_loop(struct thread *thread) -{ -    struct timeval tv; -    struct interface *ifp = NULL; -    struct listnode *linklist_node = NULL; - -    while(1) { -        gettime(&babel_now); - -        /* timeouts --------------------------------------------------------- */ -        /* get the next timeout */ -        babel_fill_with_next_timeout(&tv); -        /* if there is no timeout, we must wait. */ -        if(timeval_compare(&tv, &babel_now) > 0) { -            timeval_minus(&tv, &tv, &babel_now); -            debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs", -                   tv.tv_sec * 1000 + tv.tv_usec / 1000); -            /* it happens often to have less than 1 ms, it's bad. */ -            timeval_add_msec(&tv, &tv, 300); -            babel_set_timer(&tv); -            return 0; -        } - -        gettime(&babel_now); - -        /* update database -------------------------------------------------- */ -        if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) { -            int msecs; -            msecs = check_neighbours(); -            msecs = MAX(msecs, 10); -            schedule_neighbours_check(msecs, 1); -        } - -        if(babel_now.tv_sec >= expiry_time) { -            expire_routes(); -            expire_resend(); -            expiry_time = babel_now.tv_sec + roughly(30); -        } - -        if(babel_now.tv_sec >= source_expiry_time) { -            expire_sources(); -            source_expiry_time = babel_now.tv_sec + roughly(300); -        } - -        FOR_ALL_INTERFACES(ifp, linklist_node) { -            babel_interface_nfo *babel_ifp = NULL; -            if(!if_up(ifp)) -                continue; -            babel_ifp = babel_get_if_nfo(ifp); -            if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0) -                send_hello(ifp); -            if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0) -                send_update(ifp, 0, NULL, 0); -            if(timeval_compare(&babel_now, -                               &babel_ifp->update_flush_timeout) >= 0) -                flushupdates(ifp); -        } - -        if(resend_time.tv_sec != 0) { -            if(timeval_compare(&babel_now, &resend_time) >= 0) -                do_resend(); -        } - -        if(unicast_flush_timeout.tv_sec != 0) { -            if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0) -                flush_unicast(1); -        } - -        FOR_ALL_INTERFACES(ifp, linklist_node) { -            babel_interface_nfo *babel_ifp = NULL; -            if(!if_up(ifp)) -                continue; -            babel_ifp = babel_get_if_nfo(ifp); -            if(babel_ifp->flush_timeout.tv_sec != 0) { -                if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0) -                    flushbuf(ifp); -            } -        } -    } - -    assert(0); /* this line should never be reach */ -} - -static void -printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname) -{ -    static struct timeval curr_tv; -    static char buffer[200]; -    static const char *curr_tag = NULL; - -    switch (cmd) { -        case 0: /* reset timeval */ -            curr_tv = *tv; -            if(ifname != NULL) { -                snprintf(buffer, 200L, "interface: %s; %s", ifname, tag); -                curr_tag = buffer; -            } else { -                curr_tag = tag; -            } -            break; -        case 1: /* take the min */ -            if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */ -                break; -            } -            if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec && -                                               tv->tv_usec < curr_tv.tv_usec)) { -                curr_tv = *tv; -                if(ifname != NULL) { -                    snprintf(buffer, 200L, "interface: %s; %s", ifname, tag); -                    curr_tag = buffer; -                } else { -                    curr_tag = tag; -                } -            } -            break; -        case 2: /* print message */ -            debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag); -            break; -        default: -            break; -    } -} - -static void -babel_fill_with_next_timeout(struct timeval *tv) -{ -#if (defined NO_DEBUG) -#define printIfMin(a,b,c,d) -#else -#define printIfMin(a,b,c,d) \ -  if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);} - -    struct interface *ifp = NULL; -    struct listnode *linklist_node = NULL; - -    *tv = check_neighbours_timeout; -    printIfMin(tv, 0, "check_neighbours_timeout", NULL); -    timeval_min_sec(tv, expiry_time); -    printIfMin(tv, 1, "expiry_time", NULL); -    timeval_min_sec(tv, source_expiry_time); -    printIfMin(tv, 1, "source_expiry_time", NULL); -    timeval_min(tv, &resend_time); -    printIfMin(tv, 1, "resend_time", NULL); -    FOR_ALL_INTERFACES(ifp, linklist_node) { -        babel_interface_nfo *babel_ifp = NULL; -        if(!if_up(ifp)) -            continue; -        babel_ifp = babel_get_if_nfo(ifp); -        timeval_min(tv, &babel_ifp->flush_timeout); -        printIfMin(tv, 1, "flush_timeout", ifp->name); -        timeval_min(tv, &babel_ifp->hello_timeout); -        printIfMin(tv, 1, "hello_timeout", ifp->name); -        timeval_min(tv, &babel_ifp->update_timeout); -        printIfMin(tv, 1, "update_timeout", ifp->name); -        timeval_min(tv, &babel_ifp->update_flush_timeout); -        printIfMin(tv, 1, "update_flush_timeout",ifp->name); -    } -    timeval_min(tv, &unicast_flush_timeout); -    printIfMin(tv, 1, "unicast_flush_timeout", NULL); -    printIfMin(tv, 2, NULL, NULL); -#undef printIfMin -#endif -} - -/* set the t_update thread of the babel routing process to be launch in - 'timeout' (approximate at the milisecond) */ -static void -babel_set_timer(struct timeval *timeout) -{ -    long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; -    if (babel_routing_process->t_update != NULL) { -        thread_cancel(babel_routing_process->t_update); -    } -    babel_routing_process->t_update = -    thread_add_timer_msec(master, &babel_main_loop, NULL, msecs); -} - -/* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */ -void -schedule_neighbours_check(int msecs, int override) -{ -    struct timeval timeout; - -    timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2)); -    if(override) -        check_neighbours_timeout = timeout; -    else -        timeval_min(&check_neighbours_timeout, &timeout); -} - -int -resize_receive_buffer(int size) -{ -    if(size <= receive_buffer_size) -        return 0; - -    if(receive_buffer == NULL) { -        receive_buffer = malloc(size); -        if(receive_buffer == NULL) { -            zlog_err("malloc(receive_buffer): %s", safe_strerror(errno)); -            return -1; -        } -        receive_buffer_size = size; -    } else { -        unsigned char *new; -        new = realloc(receive_buffer, size); -        if(new == NULL) { -            zlog_err("realloc(receive_buffer): %s", safe_strerror(errno)); -            return -1; -        } -        receive_buffer = new; -        receive_buffer_size = size; -    } -    return 1; -} - -static void -babel_distribute_update (struct distribute *dist) -{ -    struct interface *ifp; -    babel_interface_nfo *babel_ifp; -    struct access_list *alist; -    struct prefix_list *plist; - -    if (! dist->ifname) -        return; - -    ifp = if_lookup_by_name (dist->ifname); -    if (ifp == NULL) -        return; - -    babel_ifp = babel_get_if_nfo(ifp); - -    if (dist->list[DISTRIBUTE_IN]) { -        alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]); -        if (alist) -            babel_ifp->list[BABEL_FILTER_IN] = alist; -        else -            babel_ifp->list[BABEL_FILTER_IN] = NULL; -    } else { -        babel_ifp->list[BABEL_FILTER_IN] = NULL; -    } - -    if (dist->list[DISTRIBUTE_OUT]) { -        alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]); -        if (alist) -            babel_ifp->list[BABEL_FILTER_OUT] = alist; -        else -            babel_ifp->list[BABEL_FILTER_OUT] = NULL; -    } else { -        babel_ifp->list[BABEL_FILTER_OUT] = NULL; -    } - -    if (dist->prefix[DISTRIBUTE_IN]) { -        plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]); -        if (plist) -            babel_ifp->prefix[BABEL_FILTER_IN] = plist; -        else -            babel_ifp->prefix[BABEL_FILTER_IN] = NULL; -    } else { -        babel_ifp->prefix[BABEL_FILTER_IN] = NULL; -    } - -    if (dist->prefix[DISTRIBUTE_OUT]) { -        plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]); -        if (plist) -            babel_ifp->prefix[BABEL_FILTER_OUT] = plist; -        else -            babel_ifp->prefix[BABEL_FILTER_OUT] = NULL; -    } else { -        babel_ifp->prefix[BABEL_FILTER_OUT] = NULL; -    } -} - -static void -babel_distribute_update_interface (struct interface *ifp) -{ -    struct distribute *dist; - -    dist = distribute_lookup (ifp->name); -    if (dist) -        babel_distribute_update (dist); -} - -/* Update all interface's distribute list. */ -static void -babel_distribute_update_all (struct prefix_list *notused) -{ -    struct interface *ifp; -    struct listnode *node; - -    for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) -        babel_distribute_update_interface (ifp); -} - -static void -babel_distribute_update_all_wrapper (struct access_list *notused) -{ -    babel_distribute_update_all(NULL); -} - - -/* [Command] */ -DEFUN (router_babel, -       router_babel_cmd, -       "router babel", -       "Enable a routing process\n" -       "Make Babel instance command\n" -       "No attributes\n") -{ -    int ret; - -    vty->node = BABEL_NODE; - -    if (!babel_routing_process) { -        ret = babel_create_routing_process (); - -        /* Notice to user we couldn't create Babel. */ -        if (ret < 0) { -            zlog_warn ("can't create Babel"); -            return CMD_WARNING; -        } -    } - -    return CMD_SUCCESS; -} - -/* [Command] */ -DEFUN (no_router_babel, -       no_router_babel_cmd, -       "no router babel", -       NO_STR -       "Disable a routing process\n" -       "Remove Babel instance command\n" -       "No attributes\n") -{ -    if(babel_routing_process) -        babel_clean_routing_process(); -    return CMD_SUCCESS; -} - -/* [Babel Command] */ -DEFUN (babel_set_resend_delay, -       babel_set_resend_delay_cmd, -       "babel resend-delay <20-655340>", -       "Babel commands\n" -       "Time before resending a message\n" -       "Milliseconds\n") -{ -    int interval; - -    VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE); - -    resend_delay = interval; -    return CMD_SUCCESS; -} - -void -babeld_quagga_init(void) -{ - -    install_node(&cmd_babel_node, &babel_config_write); - -    install_element(CONFIG_NODE, &router_babel_cmd); -    install_element(CONFIG_NODE, &no_router_babel_cmd); - -    install_default(BABEL_NODE); -    install_element(BABEL_NODE, &babel_set_resend_delay_cmd); - -    babel_if_init(); - -    /* Access list install. */ -    access_list_init (); -    access_list_add_hook (babel_distribute_update_all_wrapper); -    access_list_delete_hook (babel_distribute_update_all_wrapper); - -    /* Prefix list initialize.*/ -    prefix_list_init (); -    prefix_list_add_hook (babel_distribute_update_all); -    prefix_list_delete_hook (babel_distribute_update_all); - -    /* Distribute list install. */ -    distribute_list_init (BABEL_NODE); -    distribute_list_add_hook (babel_distribute_update); -    distribute_list_delete_hook (babel_distribute_update); -} - -/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */ - -int -input_filter(const unsigned char *id, -             const unsigned char *prefix, unsigned short plen, -             const unsigned char *neigh, unsigned int ifindex) -{ -    return babel_filter(0, prefix, plen, ifindex); -} - -int -output_filter(const unsigned char *id, const unsigned char *prefix, -              unsigned short plen, unsigned int ifindex) -{ -    return babel_filter(1, prefix, plen, ifindex); -} - -/* There's no redistribute filter in Quagga -- the zebra daemon does its -   own filtering. */ -int -redistribute_filter(const unsigned char *prefix, unsigned short plen, -                    unsigned int ifindex, int proto) -{ -    return 0; -} - diff --git a/babeld/babeld.conf.sample b/babeld/babeld.conf.sample deleted file mode 100644 index a4924ec7b7..0000000000 --- a/babeld/babeld.conf.sample +++ /dev/null @@ -1,30 +0,0 @@ -debug babel common -!debug babel kernel -!debug babel filter -!debug babel timeout -!debug babel interface -!debug babel route -!debug babel all - -router babel -! network wlan0 -! network eth0 -! redistribute kernel -! no redistribute static - -! The defaults are fine for a wireless interface - -!interface wlan0 - -! A few optimisation tweaks are optional but recommended on a wired interface -! Disable link quality estimation, enable split horizon processing, and -! increase the hello and update intervals. - -!interface eth0 -! babel wired -! babel split-horizon -! babel hello-interval 12000 -! babel update-interval 36000 - -! log file /var/log/quagga/babeld.log -log stdout diff --git a/babeld/babeld.h b/babeld/babeld.h deleted file mode 100644 index b19ae0f2db..0000000000 --- a/babeld/babeld.h +++ /dev/null @@ -1,141 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef BABEL_BABELD_H -#define BABEL_BABELD_H - -#include <zebra.h> -#include "vty.h" - -#define INFINITY ((unsigned short)(~0)) - -#ifndef RTPROT_BABEL -#define RTPROT_BABEL 42 -#endif - -#define RTPROT_BABEL_LOCAL -2 - -#undef MAX -#undef MIN - -#define MAX(x,y) ((x)<=(y)?(y):(x)) -#define MIN(x,y) ((x)<=(y)?(x):(y)) - -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -/* nothing */ -#elif defined(__GNUC__) -#define inline __inline -#if  (__GNUC__ >= 3) -#define restrict __restrict -#else -#define restrict /**/ -#endif -#else -#define inline /**/ -#define restrict /**/ -#endif - -#if defined(__GNUC__) && (__GNUC__ >= 3) -#define ATTRIBUTE(x) __attribute__ (x) -#define LIKELY(_x) __builtin_expect(!!(_x), 1) -#define UNLIKELY(_x) __builtin_expect(!!(_x), 0) -#else -#define ATTRIBUTE(x) /**/ -#define LIKELY(_x) !!(_x) -#define UNLIKELY(_x) !!(_x) -#endif - -#if defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3) -#define COLD __attribute__ ((cold)) -#else -#define COLD /**/ -#endif - -#ifndef IF_NAMESIZE -#include <sys/socket.h> -#include <net/if.h> -#endif - -#ifdef HAVE_VALGRIND -#include <valgrind/memcheck.h> -#else -#ifndef VALGRIND_MAKE_MEM_UNDEFINED -#define VALGRIND_MAKE_MEM_UNDEFINED(a, b) do {} while(0) -#endif -#ifndef VALGRIND_CHECK_MEM_IS_DEFINED -#define VALGRIND_CHECK_MEM_IS_DEFINED(a, b) do {} while(0) -#endif -#endif - - -#define BABEL_VTY_PORT 2609 -#define BABEL_DEFAULT_CONFIG "babeld.conf" -#define BABEL_VERSION "0.1 for quagga" - -/* Values in milliseconds */ -#define BABEL_DEFAULT_HELLO_INTERVAL 4000 -#define BABEL_DEFAULT_UPDATE_INTERVAL 16000 -#define BABEL_DEFAULT_RESEND_DELAY 2000 - - -/* Babel socket. */ -extern int protocol_socket; - -/* Babel structure. */ -struct babel -{ -    /* Babel threads. */ -    struct thread *t_read;    /* on Babel protocol's socket */ -    struct thread *t_update;  /* timers */ -}; - - -extern void babeld_quagga_init(void); -extern int input_filter(const unsigned char *id, -                        const unsigned char *prefix, unsigned short plen, -                        const unsigned char *neigh, unsigned int ifindex); -extern int output_filter(const unsigned char *id, const unsigned char *prefix, -                         unsigned short plen, unsigned int ifindex); -extern int redistribute_filter(const unsigned char *prefix, unsigned short plen, -                               unsigned int ifindex, int proto); -extern int resize_receive_buffer(int size); -extern void schedule_neighbours_check(int msecs, int override); - - -#endif /* BABEL_BABELD_H */ diff --git a/babeld/kernel.c b/babeld/kernel.c deleted file mode 100644 index 061d669256..0000000000 --- a/babeld/kernel.c +++ /dev/null @@ -1,316 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   - -Copyright 2007, 2008 by Grégoire Henry, Julien Cristau and Juliusz Chroboczek -Copyright 2011, 2012 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <sys/time.h> -#include <sys/param.h> -#include <time.h> - -#include "babeld.h" - - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> - -#include <zebra.h> -#include "prefix.h" -#include "zclient.h" -#include "kernel.h" -#include "privs.h" -#include "command.h" -#include "vty.h" -#include "memory.h" -#include "thread.h" - -#include "util.h" -#include "babel_interface.h" -#include "babel_zebra.h" - - -static int -kernel_route_v4(int add, const unsigned char *pref, unsigned short plen, -                const unsigned char *gate, int ifindex, -                unsigned int metric); -static int -kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, -                const unsigned char *gate, int ifindex, -                unsigned int metric); - -int -kernel_interface_operational(struct interface *interface) -{ -    return if_is_operative(interface); -} - -int -kernel_interface_mtu(struct interface *interface) -{ -    return MIN(interface->mtu, interface->mtu6); -} - -int -kernel_interface_wireless(struct interface *interface) -{ -    return 0; -} - -int -kernel_route(int operation, const unsigned char *pref, unsigned short plen, -             const unsigned char *gate, int ifindex, unsigned int metric, -             const unsigned char *newgate, int newifindex, -             unsigned int newmetric) -{ -    int rc; -    int ipv4; - -    /* Check that the protocol family is consistent. */ -    if(plen >= 96 && v4mapped(pref)) { -        if(!v4mapped(gate)) { -            errno = EINVAL; -            return -1; -        } -        ipv4 = 1; -    } else { -        if(v4mapped(gate)) { -            errno = EINVAL; -            return -1; -        } -        ipv4 = 0; -    } - -    switch (operation) { -        case ROUTE_ADD: -            return ipv4 ? -                   kernel_route_v4(1, pref, plen, gate, ifindex, metric): -                   kernel_route_v6(1, pref, plen, gate, ifindex, metric); -            break; -        case ROUTE_FLUSH: -            return ipv4 ? -                   kernel_route_v4(0, pref, plen, gate, ifindex, metric): -                   kernel_route_v6(0, pref, plen, gate, ifindex, metric); -            break; -        case ROUTE_MODIFY: -            if(newmetric == metric && memcmp(newgate, gate, 16) == 0 && -               newifindex == ifindex) -                return 0; -            debugf(BABEL_DEBUG_ROUTE, "Modify route: delete old; add new."); -            rc = ipv4 ? -                kernel_route_v4(0, pref, plen, gate, ifindex, metric): -                kernel_route_v6(0, pref, plen, gate, ifindex, metric); - -            if (rc < 0) -                return -1; - -            rc = ipv4 ? -                kernel_route_v4(1, pref, plen, newgate, newifindex, newmetric): -                kernel_route_v6(1, pref, plen, newgate, newifindex, newmetric); - -            return rc; -            break; -        default: -            zlog_err("this should never appens (false value - kernel_route)"); -            assert(0); -            exit(1); -            break; -    } -} - -static int -kernel_route_v4(int add, -                const unsigned char *pref, unsigned short plen, -                const unsigned char *gate, int ifindex, unsigned int metric) -{ -    struct zapi_ipv4 api;               /* quagga's communication system */ -    struct prefix_ipv4 quagga_prefix;   /* quagga's prefix */ -    struct in_addr babel_prefix_addr;   /* babeld's prefix addr */ -    struct in_addr nexthop;             /* next router to go */ -    struct in_addr *nexthop_pointer = &nexthop; /* it's an array! */ - -    /* convert to be understandable by quagga */ -    /* convert given addresses */ -    uchar_to_inaddr(&babel_prefix_addr, pref); -    uchar_to_inaddr(&nexthop, gate); - -    /* make prefix structure */ -    memset (&quagga_prefix, 0, sizeof(quagga_prefix)); -    quagga_prefix.family = AF_INET; -    IPV4_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr); -    quagga_prefix.prefixlen = plen - 96; /* our plen is for v4mapped's addr */ -    apply_mask_ipv4(&quagga_prefix); - -    api.vrf_id = VRF_DEFAULT; -    api.type  = ZEBRA_ROUTE_BABEL; -    api.flags = 0; -    api.message = 0; -    api.safi = SAFI_UNICAST; - -    /* Unlike the native Linux and BSD interfaces, Quagga doesn't like -       there to be both and IPv4 nexthop and an ifindex.  Omit the -       ifindex, and assume that the connected prefixes be set up -       correctly. */ - -    SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); -    api.ifindex_num = 0; -    if(metric >= KERNEL_INFINITY) { -        api.flags = ZEBRA_FLAG_BLACKHOLE; -        api.nexthop_num = 0; -    } else { -        api.nexthop_num = 1; -        api.nexthop = &nexthop_pointer; -        SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); -        api.metric = metric; -    } - -    debugf(BABEL_DEBUG_ROUTE, "%s route (ipv4) to zebra", -           add ? "adding" : "removing" ); -    return zapi_ipv4_route (add ? ZEBRA_IPV4_ROUTE_ADD : -                                  ZEBRA_IPV4_ROUTE_DELETE, -                            zclient, &quagga_prefix, &api); -} - -static int -kernel_route_v6(int add, const unsigned char *pref, unsigned short plen, -                const unsigned char *gate, int ifindex, unsigned int metric) -{ -    unsigned int tmp_ifindex = ifindex; /* (for typing) */ -    struct zapi_ipv6 api;               /* quagga's communication system */ -    struct prefix_ipv6 quagga_prefix;   /* quagga's prefix */ -    struct in6_addr babel_prefix_addr;  /* babeld's prefix addr */ -    struct in6_addr nexthop;            /* next router to go */ -    struct in6_addr *nexthop_pointer = &nexthop; - -    /* convert to be understandable by quagga */ -    /* convert given addresses */ -    uchar_to_in6addr(&babel_prefix_addr, pref); -    uchar_to_in6addr(&nexthop, gate); - -    /* make prefix structure */ -    memset (&quagga_prefix, 0, sizeof(quagga_prefix)); -    quagga_prefix.family = AF_INET6; -    IPV6_ADDR_COPY (&quagga_prefix.prefix, &babel_prefix_addr); -    quagga_prefix.prefixlen = plen; -    apply_mask_ipv6(&quagga_prefix); - -    api.vrf_id = VRF_DEFAULT; -    api.type  = ZEBRA_ROUTE_BABEL; -    api.flags = 0; -    api.message = 0; -    api.safi = SAFI_UNICAST; -    SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); -    if(metric >= KERNEL_INFINITY) { -        api.flags = ZEBRA_FLAG_BLACKHOLE; -        api.nexthop_num = 0; -        api.ifindex_num = 0; -    } else { -        api.nexthop_num = 1; -        api.nexthop = &nexthop_pointer; -        SET_FLAG(api.message, ZAPI_MESSAGE_IFINDEX); -        api.ifindex_num = 1; -        api.ifindex = &tmp_ifindex; -        SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); -        api.metric = metric; -    } - -    debugf(BABEL_DEBUG_ROUTE, "%s route (ipv6) to zebra", -           add ? "adding" : "removing" ); -    return zapi_ipv6_route (add ? ZEBRA_IPV6_ROUTE_ADD : -                                  ZEBRA_IPV6_ROUTE_DELETE, -                            zclient, &quagga_prefix, &api); -} - -int -if_eui64(char *ifname, int ifindex, unsigned char *eui) -{ -    struct interface *ifp = if_lookup_by_index(ifindex); -    if (ifp == NULL) { -        return -1; -    } -#ifdef HAVE_STRUCT_SOCKADDR_DL -    u_char len = ifp->sdl.sdl_alen; -    char *tmp = ifp->sdl.sdl_data + ifp->sdl.sdl_nlen; -#else -    u_char len = (u_char) ifp->hw_addr_len; -    char *tmp = (void*) ifp->hw_addr; -#endif -    if (len == 8) { -        memcpy(eui, tmp, 8); -        eui[0] ^= 2; -    } else if (len == 6) { -        memcpy(eui,   tmp,   3); -        eui[3] = 0xFF; -        eui[4] = 0xFE; -        memcpy(eui+5, tmp+3, 3); -    } else { -        return -1; -    } -    return 0; -} - -/* Like gettimeofday, but returns monotonic time.  If POSIX clocks are not -   available, falls back to gettimeofday but enforces monotonicity. */ -int -gettime(struct timeval *tv) -{ -    return quagga_gettime(QUAGGA_CLK_MONOTONIC, tv); -} - -/* If /dev/urandom doesn't exist, this will fail with ENOENT, which the -   caller will deal with gracefully. */ - -int -read_random_bytes(void *buf, size_t len) -{ -    int fd; -    int rc; - -    fd = open("/dev/urandom", O_RDONLY); -    if(fd < 0) { -        rc = -1; -    } else { -        rc = read(fd, buf, len); -        if(rc < 0 || (unsigned) rc < len) -            rc = -1; -        close(fd); -    } -    return rc; -} - diff --git a/babeld/kernel.h b/babeld/kernel.h deleted file mode 100644 index e8c8f9b7c6..0000000000 --- a/babeld/kernel.h +++ /dev/null @@ -1,69 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <netinet/in.h> -#include "babel_main.h" -#include "if.h" - -#define KERNEL_INFINITY 0xFFFF - -struct kernel_route { -    unsigned char prefix[16]; -    int plen; -    int metric; -    unsigned int ifindex; -    int proto; -    unsigned char gw[16]; -}; - -#define ROUTE_FLUSH 0 -#define ROUTE_ADD 1 -#define ROUTE_MODIFY 2 - -extern int export_table, import_table; - -int kernel_interface_operational(struct interface *interface); -int kernel_interface_mtu(struct interface *interface); -int kernel_interface_wireless(struct interface *interface); -int kernel_route(int operation, const unsigned char *dest, unsigned short plen, -                 const unsigned char *gate, int ifindex, unsigned int metric, -                 const unsigned char *newgate, int newifindex, -                 unsigned int newmetric); -int if_eui64(char *ifname, int ifindex, unsigned char *eui); -int gettime(struct timeval *tv); -int read_random_bytes(void *buf, size_t len); diff --git a/babeld/message.c b/babeld/message.c deleted file mode 100644 index 9dcfc6771c..0000000000 --- a/babeld/message.c +++ /dev/null @@ -1,1561 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   - -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <zebra.h> -#include "if.h" - -#include "babeld.h" -#include "util.h" -#include "net.h" -#include "babel_interface.h" -#include "source.h" -#include "neighbour.h" -#include "route.h" -#include "xroute.h" -#include "resend.h" -#include "message.h" -#include "kernel.h" - -unsigned char packet_header[4] = {42, 2}; - -int split_horizon = 1; - -unsigned short myseqno = 0; -struct timeval seqno_time = {0, 0}; - -#define UNICAST_BUFSIZE 1024 -int unicast_buffered = 0; -unsigned char *unicast_buffer = NULL; -struct neighbour *unicast_neighbour = NULL; -struct timeval unicast_flush_timeout = {0, 0}; - -static const unsigned char v4prefix[16] = -    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; - -/* Parse a network prefix, encoded in the somewhat baroque compressed -   representation used by Babel.  Return the number of bytes parsed. */ -static int -network_prefix(int ae, int plen, unsigned int omitted, -               const unsigned char *p, const unsigned char *dp, -               unsigned int len, unsigned char *p_r) -{ -    unsigned pb; -    unsigned char prefix[16]; -    int ret = -1; - -    if(plen >= 0) -        pb = (plen + 7) / 8; -    else if(ae == 1) -        pb = 4; -    else -        pb = 16; - -    if(pb > 16) -        return -1; - -    memset(prefix, 0, 16); - -    switch(ae) { -    case 0: -        ret = 0; -        break; -    case 1: -        if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted)) -            return -1; -        memcpy(prefix, v4prefix, 12); -        if(omitted) { -            if (dp == NULL || !v4mapped(dp)) return -1; -            memcpy(prefix, dp, 12 + omitted); -        } -        if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted); -        ret = pb - omitted; -        break; -    case 2: -        if(omitted > 16 || (pb > omitted && len < pb - omitted)) return -1; -        if(omitted) { -            if (dp == NULL || v4mapped(dp)) return -1; -            memcpy(prefix, dp, omitted); -        } -        if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted); -        ret = pb - omitted; -        break; -    case 3: -        if(pb > 8 && len < pb - 8) return -1; -        prefix[0] = 0xfe; -        prefix[1] = 0x80; -        if(pb > 8) memcpy(prefix + 8, p, pb - 8); -        ret = pb - 8; -        break; -    default: -        return -1; -    } - -    mask_prefix(p_r, prefix, plen < 0 ? 128 : ae == 1 ? plen + 96 : plen); -    return ret; -} - -static void -parse_route_attributes(const unsigned char *a, int alen, -                       unsigned char *channels) -{ -    int type, len, i = 0; - -    while(i < alen) { -        type = a[i]; -        if(type == 0) { -            i++; -            continue; -        } - -        if(i + 1 > alen) { -            fprintf(stderr, "Received truncated attributes.\n"); -            return; -        } -        len = a[i + 1]; -        if(i + len > alen) { -            fprintf(stderr, "Received truncated attributes.\n"); -            return; -        } - -        if(type == 1) { -            /* Nothing. */ -        } else if(type == 2) { -            if(len > DIVERSITY_HOPS) { -                fprintf(stderr, -                        "Received overlong channel information (%d > %d).\n", -                        len, DIVERSITY_HOPS); -                len = DIVERSITY_HOPS; -            } -            if(memchr(a + i + 2, 0, len) != NULL) { -                /* 0 is reserved. */ -                fprintf(stderr, "Channel information contains 0!"); -                return; -            } -            memset(channels, 0, DIVERSITY_HOPS); -            memcpy(channels, a + i + 2, len); -        } else { -            fprintf(stderr, "Received unknown route attribute %d.\n", type); -        } - -        i += len + 2; -    } -} - -static int -network_address(int ae, const unsigned char *a, unsigned int len, -                unsigned char *a_r) -{ -    return network_prefix(ae, -1, 0, a, NULL, len, a_r); -} - -static int -channels_len(unsigned char *channels) -{ -    unsigned char *p = memchr(channels, 0, DIVERSITY_HOPS); -    return p ? (p - channels) : DIVERSITY_HOPS; -} - -void -parse_packet(const unsigned char *from, struct interface *ifp, -             const unsigned char *packet, int packetlen) -{ -    int i; -    const unsigned char *message; -    unsigned char type, len; -    int bodylen; -    struct neighbour *neigh; -    int have_router_id = 0, have_v4_prefix = 0, have_v6_prefix = 0, -        have_v4_nh = 0, have_v6_nh = 0; -    unsigned char router_id[8], v4_prefix[16], v6_prefix[16], -        v4_nh[16], v6_nh[16]; - -    if(!linklocal(from)) { -        zlog_err("Received packet from non-local address %s.", -                 format_address(from)); -        return; -    } - -    if(packet[0] != 42) { -        zlog_err("Received malformed packet on %s from %s.", -                 ifp->name, format_address(from)); -        return; -    } - -    if(packet[1] != 2) { -        zlog_err("Received packet with unknown version %d on %s from %s.", -                 packet[1], ifp->name, format_address(from)); -        return; -    } - -    neigh = find_neighbour(from, ifp); -    if(neigh == NULL) { -        zlog_err("Couldn't allocate neighbour."); -        return; -    } - -    DO_NTOHS(bodylen, packet + 2); - -    if(bodylen + 4 > packetlen) { -        zlog_err("Received truncated packet (%d + 4 > %d).", -                 bodylen, packetlen); -        bodylen = packetlen - 4; -    } - -    i = 0; -    while(i < bodylen) { -        message = packet + 4 + i; -        type = message[0]; -        if(type == MESSAGE_PAD1) { -            debugf(BABEL_DEBUG_COMMON,"Received pad1 from %s on %s.", -                   format_address(from), ifp->name); -            i++; -            continue; -        } -        if(i + 1 > bodylen) { -            zlog_err("Received truncated message."); -            break; -        } -        len = message[1]; -        if(i + len > bodylen) { -            zlog_err("Received truncated message."); -            break; -        } - -        if(type == MESSAGE_PADN) { -            debugf(BABEL_DEBUG_COMMON,"Received pad%d from %s on %s.", -                   len, format_address(from), ifp->name); -        } else if(type == MESSAGE_ACK_REQ) { -            unsigned short nonce, interval; -            if(len < 6) goto fail; -            DO_NTOHS(nonce, message + 4); -            DO_NTOHS(interval, message + 6); -            debugf(BABEL_DEBUG_COMMON,"Received ack-req (%04X %d) from %s on %s.", -                   nonce, interval, format_address(from), ifp->name); -            send_ack(neigh, nonce, interval); -        } else if(type == MESSAGE_ACK) { -            debugf(BABEL_DEBUG_COMMON,"Received ack from %s on %s.", -                   format_address(from), ifp->name); -            /* Nothing right now */ -        } else if(type == MESSAGE_HELLO) { -            unsigned short seqno, interval; -            int changed; -            if(len < 6) goto fail; -            DO_NTOHS(seqno, message + 4); -            DO_NTOHS(interval, message + 6); -            debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.", -                   seqno, interval, -                   format_address(from), ifp->name); -            changed = update_neighbour(neigh, seqno, interval); -            update_neighbour_metric(neigh, changed); -            if(interval > 0) -                schedule_neighbours_check(interval * 10, 0); -        } else if(type == MESSAGE_IHU) { -            unsigned short txcost, interval; -            unsigned char address[16]; -            int rc; -            if(len < 6) goto fail; -            DO_NTOHS(txcost, message + 4); -            DO_NTOHS(interval, message + 6); -            rc = network_address(message[2], message + 8, len - 6, address); -            if(rc < 0) goto fail; -            debugf(BABEL_DEBUG_COMMON,"Received ihu %d (%d) from %s on %s for %s.", -                   txcost, interval, -                   format_address(from), ifp->name, -                   format_address(address)); -            if(message[2] == 0 || is_interface_ll_address(ifp, address)) { -                int changed = txcost != neigh->txcost; -                neigh->txcost = txcost; -                neigh->ihu_time = babel_now; -                neigh->ihu_interval = interval; -                update_neighbour_metric(neigh, changed); -                if(interval > 0) -                    schedule_neighbours_check(interval * 10 * 3, 0); -            } -        } else if(type == MESSAGE_ROUTER_ID) { -            if(len < 10) { -                have_router_id = 0; -                goto fail; -            } -            memcpy(router_id, message + 4, 8); -            have_router_id = 1; -            debugf(BABEL_DEBUG_COMMON,"Received router-id %s from %s on %s.", -                   format_eui64(router_id), format_address(from), ifp->name); -        } else if(type == MESSAGE_NH) { -            unsigned char nh[16]; -            int rc; -            if(len < 2) { -                have_v4_nh = 0; -                have_v6_nh = 0; -                goto fail; -            } -            rc = network_address(message[2], message + 4, len - 2, -                                 nh); -            if(rc < 0) { -                have_v4_nh = 0; -                have_v6_nh = 0; -                goto fail; -            } -            debugf(BABEL_DEBUG_COMMON,"Received nh %s (%d) from %s on %s.", -                   format_address(nh), message[2], -                   format_address(from), ifp->name); -            if(message[2] == 1) { -                memcpy(v4_nh, nh, 16); -                have_v4_nh = 1; -            } else { -                memcpy(v6_nh, nh, 16); -                have_v6_nh = 1; -            } -        } else if(type == MESSAGE_UPDATE) { -            unsigned char prefix[16], *nh; -            unsigned char plen; -            unsigned char channels[DIVERSITY_HOPS]; -            unsigned short interval, seqno, metric; -            int rc, parsed_len; -            if(len < 10) { -                if(len < 2 || message[3] & 0x80) -                    have_v4_prefix = have_v6_prefix = 0; -                goto fail; -            } -            DO_NTOHS(interval, message + 6); -            DO_NTOHS(seqno, message + 8); -            DO_NTOHS(metric, message + 10); -            if(message[5] == 0 || -               (message[3] == 1 ? have_v4_prefix : have_v6_prefix)) -                rc = network_prefix(message[2], message[4], message[5], -                                    message + 12, -                                    message[2] == 1 ? v4_prefix : v6_prefix, -                                    len - 10, prefix); -            else -                rc = -1; -            if(rc < 0) { -                if(message[3] & 0x80) -                    have_v4_prefix = have_v6_prefix = 0; -                goto fail; -            } -            parsed_len = 10 + rc; - -            plen = message[4] + (message[2] == 1 ? 96 : 0); - -            if(message[3] & 0x80) { -                if(message[2] == 1) { -                    memcpy(v4_prefix, prefix, 16); -                    have_v4_prefix = 1; -                } else { -                    memcpy(v6_prefix, prefix, 16); -                    have_v6_prefix = 1; -                } -            } -            if(message[3] & 0x40) { -                if(message[2] == 1) { -                    memset(router_id, 0, 4); -                    memcpy(router_id + 4, prefix + 12, 4); -                } else { -                    memcpy(router_id, prefix + 8, 8); -                } -                have_router_id = 1; -            } -            if(!have_router_id && message[2] != 0) { -                zlog_err("Received prefix with no router id."); -                goto fail; -            } -            debugf(BABEL_DEBUG_COMMON,"Received update%s%s for %s from %s on %s.", -                   (message[3] & 0x80) ? "/prefix" : "", -                   (message[3] & 0x40) ? "/id" : "", -                   format_prefix(prefix, plen), -                   format_address(from), ifp->name); - -            if(message[2] == 0) { -                if(metric < 0xFFFF) { -                    zlog_err("Received wildcard update with finite metric."); -                    goto done; -                } -                retract_neighbour_routes(neigh); -                goto done; -            } else if(message[2] == 1) { -                if(!have_v4_nh) -                    goto fail; -                nh = v4_nh; -            } else if(have_v6_nh) { -                nh = v6_nh; -            } else { -                nh = neigh->address; -            } - -            if(message[2] == 1) { -                if(!babel_get_if_nfo(ifp)->ipv4) -                    goto done; -            } - -            if((ifp->flags & BABEL_IF_FARAWAY)) { -                channels[0] = 0; -            } else { -                /* This will be overwritten by parse_route_attributes below. */ -                if(metric < 256) { -                    /* Assume non-interfering (wired) link. */ -                    channels[0] = 0; -                } else { -                    /* Assume interfering. */ -                    channels[0] = BABEL_IF_CHANNEL_INTERFERING; -                    channels[1] = 0; -                } - -                if(parsed_len < len) -                    parse_route_attributes(message + 2 + parsed_len, -                                           len - parsed_len, channels); -            } - -            update_route(router_id, prefix, plen, seqno, metric, interval, -                         neigh, nh, -                         channels, channels_len(channels)); -        } else if(type == MESSAGE_REQUEST) { -            unsigned char prefix[16], plen; -            int rc; -            if(len < 2) goto fail; -            rc = network_prefix(message[2], message[3], 0, -                                message + 4, NULL, len - 2, prefix); -            if(rc < 0) goto fail; -            plen = message[3] + (message[2] == 1 ? 96 : 0); -            debugf(BABEL_DEBUG_COMMON,"Received request for %s from %s on %s.", -                   message[2] == 0 ? "any" : format_prefix(prefix, plen), -                   format_address(from), ifp->name); -            if(message[2] == 0) { -                struct babel_interface *babel_ifp =babel_get_if_nfo(neigh->ifp); -                /* If a neighbour is requesting a full route dump from us, -                   we might as well send it an IHU. */ -                send_ihu(neigh, NULL); -                /* Since nodes send wildcard requests on boot, booting -                   a large number of nodes at the same time may cause an -                   update storm.  Ignore a wildcard request that happens -                   shortly after we sent a full update. */ -                if(babel_ifp->last_update_time < -                   (time_t)(babel_now.tv_sec - -                            MAX(babel_ifp->hello_interval / 100, 1))) -                    send_update(neigh->ifp, 0, NULL, 0); -            } else { -                send_update(neigh->ifp, 0, prefix, plen); -            } -        } else if(type == MESSAGE_MH_REQUEST) { -            unsigned char prefix[16], plen; -            unsigned short seqno; -            int rc; -            if(len < 14) goto fail; -            DO_NTOHS(seqno, message + 4); -            rc = network_prefix(message[2], message[3], 0, -                                message + 16, NULL, len - 14, prefix); -            if(rc < 0) goto fail; -            plen = message[3] + (message[2] == 1 ? 96 : 0); -            debugf(BABEL_DEBUG_COMMON,"Received request (%d) for %s from %s on %s (%s, %d).", -                   message[6], -                   format_prefix(prefix, plen), -                   format_address(from), ifp->name, -                   format_eui64(message + 8), seqno); -            handle_request(neigh, prefix, plen, message[6], -                           seqno, message + 8); -        } else { -            debugf(BABEL_DEBUG_COMMON,"Received unknown packet type %d from %s on %s.", -                   type, format_address(from), ifp->name); -        } -    done: -        i += len + 2; -        continue; - -    fail: -        zlog_err("Couldn't parse packet (%d, %d) from %s on %s.", -                 message[0], message[1], format_address(from), ifp->name); -        goto done; -    } -    return; -} - -/* Under normal circumstances, there are enough moderation mechanisms -   elsewhere in the protocol to make sure that this last-ditch check -   should never trigger.  But I'm superstitious. */ - -static int -check_bucket(struct interface *ifp) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    if(babel_ifp->bucket <= 0) { -        int seconds = babel_now.tv_sec - babel_ifp->bucket_time; -        if(seconds > 0) { -            babel_ifp->bucket = MIN(BUCKET_TOKENS_MAX, -                              seconds * BUCKET_TOKENS_PER_SEC); -        } -        /* Reset bucket time unconditionally, in case clock is stepped. */ -        babel_ifp->bucket_time = babel_now.tv_sec; -    } - -    if(babel_ifp->bucket > 0) { -        babel_ifp->bucket--; -        return 1; -    } else { -        return 0; -    } -} - -void -flushbuf(struct interface *ifp) -{ -    int rc; -    struct sockaddr_in6 sin6; -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); - -    assert(babel_ifp->buffered <= babel_ifp->bufsize); - -    flushupdates(ifp); - -    if(babel_ifp->buffered > 0) { -        debugf(BABEL_DEBUG_COMMON,"  (flushing %d buffered bytes on %s)", -               babel_ifp->buffered, ifp->name); -        if(check_bucket(ifp)) { -            memset(&sin6, 0, sizeof(sin6)); -            sin6.sin6_family = AF_INET6; -            memcpy(&sin6.sin6_addr, protocol_group, 16); -            sin6.sin6_port = htons(protocol_port); -            sin6.sin6_scope_id = ifp->ifindex; -            DO_HTONS(packet_header + 2, babel_ifp->buffered); -            rc = babel_send(protocol_socket, -                            packet_header, sizeof(packet_header), -                            babel_ifp->sendbuf, babel_ifp->buffered, -                            (struct sockaddr*)&sin6, sizeof(sin6)); -            if(rc < 0) -                zlog_err("send: %s", safe_strerror(errno)); -        } else { -            zlog_err("Warning: bucket full, dropping packet to %s.", -                     ifp->name); -        } -    } -    VALGRIND_MAKE_MEM_UNDEFINED(babel_ifp->sendbuf, babel_ifp->bufsize); -    babel_ifp->buffered = 0; -    babel_ifp->have_buffered_hello = 0; -    babel_ifp->have_buffered_id = 0; -    babel_ifp->have_buffered_nh = 0; -    babel_ifp->have_buffered_prefix = 0; -    babel_ifp->flush_timeout.tv_sec = 0; -    babel_ifp->flush_timeout.tv_usec = 0; -} - -static void -schedule_flush(struct interface *ifp) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    unsigned msecs = jitter(babel_ifp, 0); -    if(babel_ifp->flush_timeout.tv_sec != 0 && -       timeval_minus_msec(&babel_ifp->flush_timeout, &babel_now) < msecs) -        return; -    set_timeout(&babel_ifp->flush_timeout, msecs); -} - -static void -schedule_flush_now(struct interface *ifp) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    /* Almost now */ -    unsigned msecs = roughly(10); -    if(babel_ifp->flush_timeout.tv_sec != 0 && -       timeval_minus_msec(&babel_ifp->flush_timeout, &babel_now) < msecs) -        return; -    set_timeout(&babel_ifp->flush_timeout, msecs); -} - -static void -schedule_unicast_flush(unsigned msecs) -{ -    if(!unicast_neighbour) -        return; -    if(unicast_flush_timeout.tv_sec != 0 && -       timeval_minus_msec(&unicast_flush_timeout, &babel_now) < msecs) -        return; -    unicast_flush_timeout.tv_usec = (babel_now.tv_usec + msecs * 1000) %1000000; -    unicast_flush_timeout.tv_sec = -        babel_now.tv_sec + (babel_now.tv_usec / 1000 + msecs) / 1000; -} - -static void -ensure_space(struct interface *ifp, int space) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    if(babel_ifp->bufsize - babel_ifp->buffered < space) -        flushbuf(ifp); -} - -static void -start_message(struct interface *ifp, int type, int len) -{ -  babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    if(babel_ifp->bufsize - babel_ifp->buffered < len + 2) -        flushbuf(ifp); -    babel_ifp->sendbuf[babel_ifp->buffered++] = type; -    babel_ifp->sendbuf[babel_ifp->buffered++] = len; -} - -static void -end_message(struct interface *ifp, int type, int bytes) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    assert(babel_ifp->buffered >= bytes + 2 && -           babel_ifp->sendbuf[babel_ifp->buffered - bytes - 2] == type && -           babel_ifp->sendbuf[babel_ifp->buffered - bytes - 1] == bytes); -    schedule_flush(ifp); -} - -static void -accumulate_byte(struct interface *ifp, unsigned char value) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    babel_ifp->sendbuf[babel_ifp->buffered++] = value; -} - -static void -accumulate_short(struct interface *ifp, unsigned short value) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    DO_HTONS(babel_ifp->sendbuf + babel_ifp->buffered, value); -    babel_ifp->buffered += 2; -} - -static void -accumulate_bytes(struct interface *ifp, -                 const unsigned char *value, unsigned len) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    memcpy(babel_ifp->sendbuf + babel_ifp->buffered, value, len); -    babel_ifp->buffered += len; -} - -static int -start_unicast_message(struct neighbour *neigh, int type, int len) -{ -    if(unicast_neighbour) { -        if(neigh != unicast_neighbour || -           unicast_buffered + len + 2 >= -           MIN(UNICAST_BUFSIZE, babel_get_if_nfo(neigh->ifp)->bufsize)) -            flush_unicast(0); -    } -    if(!unicast_buffer) -        unicast_buffer = malloc(UNICAST_BUFSIZE); -    if(!unicast_buffer) { -        zlog_err("malloc(unicast_buffer): %s", safe_strerror(errno)); -        return -1; -    } - -    unicast_neighbour = neigh; - -    unicast_buffer[unicast_buffered++] = type; -    unicast_buffer[unicast_buffered++] = len; -    return 1; -} - -static void -end_unicast_message(struct neighbour *neigh, int type, int bytes) -{ -    assert(unicast_neighbour == neigh && unicast_buffered >= bytes + 2 && -           unicast_buffer[unicast_buffered - bytes - 2] == type && -           unicast_buffer[unicast_buffered - bytes - 1] == bytes); -    schedule_unicast_flush(jitter(babel_get_if_nfo(neigh->ifp), 0)); -} - -static void -accumulate_unicast_byte(struct neighbour *neigh, unsigned char value) -{ -    unicast_buffer[unicast_buffered++] = value; -} - -static void -accumulate_unicast_short(struct neighbour *neigh, unsigned short value) -{ -    DO_HTONS(unicast_buffer + unicast_buffered, value); -    unicast_buffered += 2; -} - -static void -accumulate_unicast_bytes(struct neighbour *neigh, -                         const unsigned char *value, unsigned len) -{ -    memcpy(unicast_buffer + unicast_buffered, value, len); -    unicast_buffered += len; -} - -void -send_ack(struct neighbour *neigh, unsigned short nonce, unsigned short interval) -{ -    int rc; -    debugf(BABEL_DEBUG_COMMON,"Sending ack (%04x) to %s on %s.", -           nonce, format_address(neigh->address), neigh->ifp->name); -    rc = start_unicast_message(neigh, MESSAGE_ACK, 2); if(rc < 0) return; -    accumulate_unicast_short(neigh, nonce); -    end_unicast_message(neigh, MESSAGE_ACK, 2); -    /* Roughly yields a value no larger than 3/2, so this meets the deadline */ -    schedule_unicast_flush(roughly(interval * 6)); -} - -void -send_hello_noupdate(struct interface *ifp, unsigned interval) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    /* This avoids sending multiple hellos in a single packet, which breaks -       link quality estimation. */ -    if(babel_ifp->have_buffered_hello) -        flushbuf(ifp); - -    babel_ifp->hello_seqno = seqno_plus(babel_ifp->hello_seqno, 1); -    set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval); - -    if(!if_up(ifp)) -        return; - -    debugf(BABEL_DEBUG_COMMON,"Sending hello %d (%d) to %s.", -           babel_ifp->hello_seqno, interval, ifp->name); - -    start_message(ifp, MESSAGE_HELLO, 6); -    accumulate_short(ifp, 0); -    accumulate_short(ifp, babel_ifp->hello_seqno); -    accumulate_short(ifp, interval > 0xFFFF ? 0xFFFF : interval); -    end_message(ifp, MESSAGE_HELLO, 6); -    babel_ifp->have_buffered_hello = 1; -} - -void -send_hello(struct interface *ifp) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    send_hello_noupdate(ifp, (babel_ifp->hello_interval + 9) / 10); -    /* Send full IHU every 3 hellos, and marginal IHU each time */ -    if(babel_ifp->hello_seqno % 3 == 0) -        send_ihu(NULL, ifp); -    else -        send_marginal_ihu(ifp); -} - -void -flush_unicast(int dofree) -{ -    struct sockaddr_in6 sin6; -    int rc; - -    if(unicast_buffered == 0) -        goto done; - -    if(!if_up(unicast_neighbour->ifp)) -        goto done; - -    /* Preserve ordering of messages */ -    flushbuf(unicast_neighbour->ifp); - -    if(check_bucket(unicast_neighbour->ifp)) { -        memset(&sin6, 0, sizeof(sin6)); -        sin6.sin6_family = AF_INET6; -        memcpy(&sin6.sin6_addr, unicast_neighbour->address, 16); -        sin6.sin6_port = htons(protocol_port); -        sin6.sin6_scope_id = unicast_neighbour->ifp->ifindex; -        DO_HTONS(packet_header + 2, unicast_buffered); -        rc = babel_send(protocol_socket, -                        packet_header, sizeof(packet_header), -                        unicast_buffer, unicast_buffered, -                        (struct sockaddr*)&sin6, sizeof(sin6)); -        if(rc < 0) -            zlog_err("send(unicast): %s", safe_strerror(errno)); -    } else { -        zlog_err("Warning: bucket full, dropping unicast packet to %s if %s.", -                 format_address(unicast_neighbour->address), -                 unicast_neighbour->ifp->name); -    } - - done: -    VALGRIND_MAKE_MEM_UNDEFINED(unicast_buffer, UNICAST_BUFSIZE); -    unicast_buffered = 0; -    if(dofree && unicast_buffer) { -        free(unicast_buffer); -        unicast_buffer = NULL; -    } -    unicast_neighbour = NULL; -    unicast_flush_timeout.tv_sec = 0; -    unicast_flush_timeout.tv_usec = 0; -} - -static void -really_send_update(struct interface *ifp, -                   const unsigned char *id, -                   const unsigned char *prefix, unsigned char plen, -                   unsigned short seqno, unsigned short metric, -                   unsigned char *channels, int channels_len) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    int add_metric, v4, real_plen, omit = 0; -    const unsigned char *real_prefix; -    unsigned short flags = 0; -    int channels_size; - -    if(diversity_kind != DIVERSITY_CHANNEL) -        channels_len = -1; - -    channels_size = channels_len >= 0 ? channels_len + 2 : 0; - -    if(!if_up(ifp)) -        return; - -    add_metric = output_filter(id, prefix, plen, ifp->ifindex); -    if(add_metric >= INFINITY) -        return; - -    metric = MIN(metric + add_metric, INFINITY); -    /* Worst case */ -    ensure_space(ifp, 20 + 12 + 28); - -    v4 = plen >= 96 && v4mapped(prefix); - -    if(v4) { -        if(!babel_ifp->ipv4) -            return; -        if(!babel_ifp->have_buffered_nh || -           memcmp(babel_ifp->buffered_nh, babel_ifp->ipv4, 4) != 0) { -            start_message(ifp, MESSAGE_NH, 6); -            accumulate_byte(ifp, 1); -            accumulate_byte(ifp, 0); -            accumulate_bytes(ifp, babel_ifp->ipv4, 4); -            end_message(ifp, MESSAGE_NH, 6); -            memcpy(babel_ifp->buffered_nh, babel_ifp->ipv4, 4); -            babel_ifp->have_buffered_nh = 1; -        } - -        real_prefix = prefix + 12; -        real_plen = plen - 96; -    } else { -        if(babel_ifp->have_buffered_prefix) { -            while(omit < plen / 8 && -                  babel_ifp->buffered_prefix[omit] == prefix[omit]) -                omit++; -        } -        if(!babel_ifp->have_buffered_prefix || plen >= 48) -            flags |= 0x80; -        real_prefix = prefix; -        real_plen = plen; -    } - -    if(!babel_ifp->have_buffered_id -       || memcmp(id, babel_ifp->buffered_id, 8) != 0) { -        if(real_plen == 128 && memcmp(real_prefix + 8, id, 8) == 0) { -            flags |= 0x40; -        } else { -            start_message(ifp, MESSAGE_ROUTER_ID, 10); -            accumulate_short(ifp, 0); -            accumulate_bytes(ifp, id, 8); -            end_message(ifp, MESSAGE_ROUTER_ID, 10); -        } -        memcpy(babel_ifp->buffered_id, id, 16); -        babel_ifp->have_buffered_id = 1; -    } - -    start_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit + -                  channels_size); -    accumulate_byte(ifp, v4 ? 1 : 2); -    accumulate_byte(ifp, flags); -    accumulate_byte(ifp, real_plen); -    accumulate_byte(ifp, omit); -    accumulate_short(ifp, (babel_ifp->update_interval + 5) / 10); -    accumulate_short(ifp, seqno); -    accumulate_short(ifp, metric); -    accumulate_bytes(ifp, real_prefix + omit, (real_plen + 7) / 8 - omit); -    /* Note that an empty channels TLV is different from no such TLV. */ -    if(channels_len >= 0) { -        accumulate_byte(ifp, 2); -        accumulate_byte(ifp, channels_len); -        accumulate_bytes(ifp, channels, channels_len); -    } -    end_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit + -                channels_size); - -    if(flags & 0x80) { -        memcpy(babel_ifp->buffered_prefix, prefix, 16); -        babel_ifp->have_buffered_prefix = 1; -    } -} - -static int -compare_buffered_updates(const void *av, const void *bv) -{ -    const struct buffered_update *a = av, *b = bv; -    int rc, v4a, v4b, ma, mb; - -    rc = memcmp(a->id, b->id, 8); -    if(rc != 0) -        return rc; - -    v4a = (a->plen >= 96 && v4mapped(a->prefix)); -    v4b = (b->plen >= 96 && v4mapped(b->prefix)); - -    if(v4a > v4b) -        return 1; -    else if(v4a < v4b) -        return -1; - -    ma = (!v4a && a->plen == 128 && memcmp(a->prefix + 8, a->id, 8) == 0); -    mb = (!v4b && b->plen == 128 && memcmp(b->prefix + 8, b->id, 8) == 0); - -    if(ma > mb) -        return -1; -    else if(mb > ma) -        return 1; - -    if(a->plen < b->plen) -        return 1; -    else if(a->plen > b->plen) -        return -1; - -    return memcmp(a->prefix, b->prefix, 16); -} - -void -flushupdates(struct interface *ifp) -{ -    babel_interface_nfo *babel_ifp = NULL; -    struct xroute *xroute; -    struct babel_route *route; -    const unsigned char *last_prefix = NULL; -    unsigned char last_plen = 0xFF; -    int i; - -    if(ifp == NULL) { -      struct interface *ifp_aux; -      struct listnode *linklist_node = NULL; -        FOR_ALL_INTERFACES(ifp_aux, linklist_node) -            flushupdates(ifp_aux); -        return; -    } - -    babel_ifp = babel_get_if_nfo(ifp); -    if(babel_ifp->num_buffered_updates > 0) { -        struct buffered_update *b = babel_ifp->buffered_updates; -        int n = babel_ifp->num_buffered_updates; - -        babel_ifp->buffered_updates = NULL; -        babel_ifp->update_bufsize = 0; -        babel_ifp->num_buffered_updates = 0; - -        if(!if_up(ifp)) -            goto done; - -        debugf(BABEL_DEBUG_COMMON,"  (flushing %d buffered updates on %s (%d))", -               n, ifp->name, ifp->ifindex); - -        /* In order to send fewer update messages, we want to send updates -           with the same router-id together, with IPv6 going out before IPv4. */ - -        for(i = 0; i < n; i++) { -            route = find_installed_route(b[i].prefix, b[i].plen); -            if(route) -                memcpy(b[i].id, route->src->id, 8); -            else -                memcpy(b[i].id, myid, 8); -        } - -        qsort(b, n, sizeof(struct buffered_update), compare_buffered_updates); - -        for(i = 0; i < n; i++) { -            /* The same update may be scheduled multiple times before it is -               sent out.  Since our buffer is now sorted, it is enough to -               compare with the previous update. */ - -            if(last_prefix) { -                if(b[i].plen == last_plen && -                   memcmp(b[i].prefix, last_prefix, 16) == 0) -                    continue; -            } - -            xroute = find_xroute(b[i].prefix, b[i].plen); -            route = find_installed_route(b[i].prefix, b[i].plen); - -            if(xroute && (!route || xroute->metric <= kernel_metric)) { -                really_send_update(ifp, myid, -                                   xroute->prefix, xroute->plen, -                                   myseqno, xroute->metric, -                                   NULL, 0); -                last_prefix = xroute->prefix; -                last_plen = xroute->plen; -            } else if(route) { -                unsigned char channels[DIVERSITY_HOPS]; -                int chlen; -                struct interface *route_ifp = route->neigh->ifp; -                struct babel_interface *babel_route_ifp = NULL; -                unsigned short metric; -                unsigned short seqno; - -                seqno = route->seqno; -                metric = -                    route_interferes(route, ifp) ? -                    route_metric(route) : -                    route_metric_noninterfering(route); - -                if(metric < INFINITY) -                    satisfy_request(route->src->prefix, route->src->plen, -                                    seqno, route->src->id, ifp); -                if((babel_ifp->flags & BABEL_IF_SPLIT_HORIZON) && -                   route->neigh->ifp == ifp) -                    continue; - -                babel_route_ifp = babel_get_if_nfo(route_ifp); -                if(babel_route_ifp->channel ==BABEL_IF_CHANNEL_NONINTERFERING) { -                    memcpy(channels, route->channels, DIVERSITY_HOPS); -                } else { -                    if(babel_route_ifp->channel == BABEL_IF_CHANNEL_UNKNOWN) -                        channels[0] = BABEL_IF_CHANNEL_INTERFERING; -                    else { -                        assert(babel_route_ifp->channel > 0 && -                               babel_route_ifp->channel <= 255); -                        channels[0] = babel_route_ifp->channel; -                    } -                    memcpy(channels + 1, route->channels, DIVERSITY_HOPS - 1); -                } - -                chlen = channels_len(channels); -                really_send_update(ifp, route->src->id, -                                   route->src->prefix, -                                   route->src->plen, -                                   seqno, metric, -                                   channels, chlen); -                update_source(route->src, seqno, metric); -                last_prefix = route->src->prefix; -                last_plen = route->src->plen; -            } else { -            /* There's no route for this prefix.  This can happen shortly -               after an xroute has been retracted, so send a retraction. */ -                really_send_update(ifp, myid, b[i].prefix, b[i].plen, -                                   myseqno, INFINITY, NULL, -1); -            } -        } -        schedule_flush_now(ifp); -    done: -        free(b); -    } -    babel_ifp->update_flush_timeout.tv_sec = 0; -    babel_ifp->update_flush_timeout.tv_usec = 0; -} - -static void -schedule_update_flush(struct interface *ifp, int urgent) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    unsigned msecs; -    msecs = update_jitter(babel_ifp, urgent); -    if(babel_ifp->update_flush_timeout.tv_sec != 0 && -       timeval_minus_msec(&babel_ifp->update_flush_timeout, &babel_now) < msecs) -        return; -    set_timeout(&babel_ifp->update_flush_timeout, msecs); -} - -static void -buffer_update(struct interface *ifp, -              const unsigned char *prefix, unsigned char plen) -{ -    babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp); -    if(babel_ifp->num_buffered_updates > 0 && -       babel_ifp->num_buffered_updates >= babel_ifp->update_bufsize) -        flushupdates(ifp); - -    if(babel_ifp->update_bufsize == 0) { -        int n; -        assert(babel_ifp->buffered_updates == NULL); -        /* Allocate enough space to hold a full update.  Since the -           number of installed routes will grow over time, make sure we -           have enough space to send a full-ish frame. */ -        n = installed_routes_estimate() + xroutes_estimate() + 4; -        n = MAX(n, babel_ifp->bufsize / 16); -    again: -        babel_ifp->buffered_updates = malloc(n *sizeof(struct buffered_update)); -        if(babel_ifp->buffered_updates == NULL) { -            zlog_err("malloc(buffered_updates): %s", safe_strerror(errno)); -            if(n > 4) { -                /* Try again with a tiny buffer. */ -                n = 4; -                goto again; -            } -            return; -        } -        babel_ifp->update_bufsize = n; -        babel_ifp->num_buffered_updates = 0; -    } - -    memcpy(babel_ifp->buffered_updates[babel_ifp->num_buffered_updates].prefix, -           prefix, 16); -    babel_ifp->buffered_updates[babel_ifp->num_buffered_updates].plen = plen; -    babel_ifp->num_buffered_updates++; -} - -static void -buffer_update_callback(struct babel_route *route, void *closure) -{ -    buffer_update((struct interface*)closure, -                  route->src->prefix, route->src->plen); -} - -void -send_update(struct interface *ifp, int urgent, -            const unsigned char *prefix, unsigned char plen) -{ -    babel_interface_nfo *babel_ifp = NULL; - -    if(ifp == NULL) { -      struct interface *ifp_aux; -      struct listnode *linklist_node = NULL; -        struct babel_route *route; -        FOR_ALL_INTERFACES(ifp_aux, linklist_node) -            send_update(ifp_aux, urgent, prefix, plen); -        if(prefix) { -            /* Since flushupdates only deals with non-wildcard interfaces, we -               need to do this now. */ -            route = find_installed_route(prefix, plen); -            if(route && route_metric(route) < INFINITY) -                satisfy_request(prefix, plen, route->src->seqno, route->src->id, -                                NULL); -        } -        return; -    } - -    if(!if_up(ifp)) -        return; - -    babel_ifp = babel_get_if_nfo(ifp); -    if(prefix) { -        debugf(BABEL_DEBUG_COMMON,"Sending update to %s for %s.", -               ifp->name, format_prefix(prefix, plen)); -        buffer_update(ifp, prefix, plen); -    } else { -        send_self_update(ifp); -        debugf(BABEL_DEBUG_COMMON,"Sending update to %s for any.", ifp->name); -        for_all_installed_routes(buffer_update_callback, ifp); -        set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval); -        babel_ifp->last_update_time = babel_now.tv_sec; -    } -    schedule_update_flush(ifp, urgent); -} - -void -send_update_resend(struct interface *ifp, -                   const unsigned char *prefix, unsigned char plen) -{ -    assert(prefix != NULL); - -    send_update(ifp, 1, prefix, plen); -    record_resend(RESEND_UPDATE, prefix, plen, 0, 0, NULL, resend_delay); -} - -void -send_wildcard_retraction(struct interface *ifp) -{ -    babel_interface_nfo *babel_ifp = NULL; -    if(ifp == NULL) { -      struct interface *ifp_aux; -      struct listnode *linklist_node = NULL; -        FOR_ALL_INTERFACES(ifp_aux, linklist_node) -            send_wildcard_retraction(ifp_aux); -        return; -    } - -    if(!if_up(ifp)) -        return; - -    babel_ifp = babel_get_if_nfo(ifp); -    start_message(ifp, MESSAGE_UPDATE, 10); -    accumulate_byte(ifp, 0); -    accumulate_byte(ifp, 0x40); -    accumulate_byte(ifp, 0); -    accumulate_byte(ifp, 0); -    accumulate_short(ifp, 0xFFFF); -    accumulate_short(ifp, myseqno); -    accumulate_short(ifp, 0xFFFF); -    end_message(ifp, MESSAGE_UPDATE, 10); - -    babel_ifp->have_buffered_id = 0; -} - -void -update_myseqno() -{ -    myseqno = seqno_plus(myseqno, 1); -    seqno_time = babel_now; -} - -static void -send_xroute_update_callback(struct xroute *xroute, void *closure) -{ -    struct interface *ifp = (struct interface*)closure; -    send_update(ifp, 0, xroute->prefix, xroute->plen); -} - -void -send_self_update(struct interface *ifp) -{ -    if(ifp == NULL) { -      struct interface *ifp_aux; -      struct listnode *linklist_node = NULL; -        FOR_ALL_INTERFACES(ifp_aux, linklist_node) { -            if(!if_up(ifp_aux)) -                continue; -            send_self_update(ifp_aux); -        } -        return; -    } - -    debugf(BABEL_DEBUG_COMMON,"Sending self update to %s.", ifp->name); -    for_all_xroutes(send_xroute_update_callback, ifp); -} - -void -send_ihu(struct neighbour *neigh, struct interface *ifp) -{ -    babel_interface_nfo *babel_ifp = NULL; -    int rxcost, interval; -    int ll; - -    if(neigh == NULL && ifp == NULL) { -      struct interface *ifp_aux; -      struct listnode *linklist_node = NULL; -        FOR_ALL_INTERFACES(ifp_aux, linklist_node) { -            if(if_up(ifp_aux)) -                continue; -            send_ihu(NULL, ifp_aux); -        } -        return; -    } - -    if(neigh == NULL) { -        struct neighbour *ngh; -        FOR_ALL_NEIGHBOURS(ngh) { -            if(ngh->ifp == ifp) -                send_ihu(ngh, ifp); -        } -        return; -    } - - -    if(ifp && neigh->ifp != ifp) -        return; - -    ifp = neigh->ifp; -    babel_ifp = babel_get_if_nfo(ifp); -    if(!if_up(ifp)) -        return; - -    rxcost = neighbour_rxcost(neigh); -    interval = (babel_ifp->hello_interval * 3 + 9) / 10; - -    /* Conceptually, an IHU is a unicast message.  We usually send them as -       multicast, since this allows aggregation into a single packet and -       avoids an ARP exchange.  If we already have a unicast message queued -       for this neighbour, however, we might as well piggyback the IHU. */ -    debugf(BABEL_DEBUG_COMMON,"Sending %sihu %d on %s to %s.", -           unicast_neighbour == neigh ? "unicast " : "", -           rxcost, -           neigh->ifp->name, -           format_address(neigh->address)); - -    ll = linklocal(neigh->address); - -    if(unicast_neighbour != neigh) { -        start_message(ifp, MESSAGE_IHU, ll ? 14 : 22); -        accumulate_byte(ifp, ll ? 3 : 2); -        accumulate_byte(ifp, 0); -        accumulate_short(ifp, rxcost); -        accumulate_short(ifp, interval); -        if(ll) -            accumulate_bytes(ifp, neigh->address + 8, 8); -        else -            accumulate_bytes(ifp, neigh->address, 16); -        end_message(ifp, MESSAGE_IHU, ll ? 14 : 22); -    } else { -        int rc; -        rc = start_unicast_message(neigh, MESSAGE_IHU, ll ? 14 : 22); -        if(rc < 0) return; -        accumulate_unicast_byte(neigh, ll ? 3 : 2); -        accumulate_unicast_byte(neigh, 0); -        accumulate_unicast_short(neigh, rxcost); -        accumulate_unicast_short(neigh, interval); -        if(ll) -            accumulate_unicast_bytes(neigh, neigh->address + 8, 8); -        else -            accumulate_unicast_bytes(neigh, neigh->address, 16); -        end_unicast_message(neigh, MESSAGE_IHU, ll ? 14 : 22); -    } -} - -/* Send IHUs to all marginal neighbours */ -void -send_marginal_ihu(struct interface *ifp) -{ -    struct neighbour *neigh; -    FOR_ALL_NEIGHBOURS(neigh) { -        if(ifp && neigh->ifp != ifp) -            continue; -        if(neigh->txcost >= 384 || (neigh->reach & 0xF000) != 0xF000) -            send_ihu(neigh, ifp); -    } -} - -void -send_request(struct interface *ifp, -             const unsigned char *prefix, unsigned char plen) -{ -    int v4, len; - -    if(ifp == NULL) { -      struct interface *ifp_aux; -      struct listnode *linklist_node = NULL; -        FOR_ALL_INTERFACES(ifp_aux, linklist_node) { -            if(if_up(ifp_aux)) -                continue; -            send_request(ifp_aux, prefix, plen); -        } -        return; -    } - -    /* make sure any buffered updates go out before this request. */ -    flushupdates(ifp); - -    if(!if_up(ifp)) -        return; - -    debugf(BABEL_DEBUG_COMMON,"sending request to %s for %s.", -           ifp->name, prefix ? format_prefix(prefix, plen) : "any"); -    v4 = plen >= 96 && v4mapped(prefix); -    len = !prefix ? 2 : v4 ? 6 : 18; - -    start_message(ifp, MESSAGE_REQUEST, len); -    accumulate_byte(ifp, !prefix ? 0 : v4 ? 1 : 2); -    accumulate_byte(ifp, !prefix ? 0 : v4 ? plen - 96 : plen); -    if(prefix) { -        if(v4) -            accumulate_bytes(ifp, prefix + 12, 4); -        else -            accumulate_bytes(ifp, prefix, 16); -    } -    end_message(ifp, MESSAGE_REQUEST, len); -} - -void -send_unicast_request(struct neighbour *neigh, -                     const unsigned char *prefix, unsigned char plen) -{ -    int rc, v4, len; - -    /* make sure any buffered updates go out before this request. */ -    flushupdates(neigh->ifp); - -    debugf(BABEL_DEBUG_COMMON,"sending unicast request to %s for %s.", -           format_address(neigh->address), -           prefix ? format_prefix(prefix, plen) : "any"); -    v4 = plen >= 96 && v4mapped(prefix); -    len = !prefix ? 2 : v4 ? 6 : 18; - -    rc = start_unicast_message(neigh, MESSAGE_REQUEST, len); -    if(rc < 0) return; -    accumulate_unicast_byte(neigh, !prefix ? 0 : v4 ? 1 : 2); -    accumulate_unicast_byte(neigh, !prefix ? 0 : v4 ? plen - 96 : plen); -    if(prefix) { -        if(v4) -            accumulate_unicast_bytes(neigh, prefix + 12, 4); -        else -            accumulate_unicast_bytes(neigh, prefix, 16); -    } -    end_unicast_message(neigh, MESSAGE_REQUEST, len); -} - -void -send_multihop_request(struct interface *ifp, -                      const unsigned char *prefix, unsigned char plen, -                      unsigned short seqno, const unsigned char *id, -                      unsigned short hop_count) -{ -    int v4, pb, len; - -    /* Make sure any buffered updates go out before this request. */ -    flushupdates(ifp); - -    if(ifp == NULL) { -      struct interface *ifp_aux; -      struct listnode *linklist_node = NULL; -        FOR_ALL_INTERFACES(ifp_aux, linklist_node) { -            if(!if_up(ifp_aux)) -                continue; -            send_multihop_request(ifp_aux, prefix, plen, seqno, id, hop_count); -        } -        return; -    } - -    if(!if_up(ifp)) -        return; - -    debugf(BABEL_DEBUG_COMMON,"Sending request (%d) on %s for %s.", -           hop_count, ifp->name, format_prefix(prefix, plen)); -    v4 = plen >= 96 && v4mapped(prefix); -    pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; -    len = 6 + 8 + pb; - -    start_message(ifp, MESSAGE_MH_REQUEST, len); -    accumulate_byte(ifp, v4 ? 1 : 2); -    accumulate_byte(ifp, v4 ? plen - 96 : plen); -    accumulate_short(ifp, seqno); -    accumulate_byte(ifp, hop_count); -    accumulate_byte(ifp, 0); -    accumulate_bytes(ifp, id, 8); -    if(prefix) { -        if(v4) -            accumulate_bytes(ifp, prefix + 12, pb); -        else -            accumulate_bytes(ifp, prefix, pb); -    } -    end_message(ifp, MESSAGE_MH_REQUEST, len); -} - -void -send_unicast_multihop_request(struct neighbour *neigh, -                              const unsigned char *prefix, unsigned char plen, -                              unsigned short seqno, const unsigned char *id, -                              unsigned short hop_count) -{ -    int rc, v4, pb, len; - -    /* Make sure any buffered updates go out before this request. */ -    flushupdates(neigh->ifp); - -    debugf(BABEL_DEBUG_COMMON,"Sending multi-hop request to %s for %s (%d hops).", -           format_address(neigh->address), -           format_prefix(prefix, plen), hop_count); -    v4 = plen >= 96 && v4mapped(prefix); -    pb = v4 ? ((plen - 96) + 7) / 8 : (plen + 7) / 8; -    len = 6 + 8 + pb; - -    rc = start_unicast_message(neigh, MESSAGE_MH_REQUEST, len); -    if(rc < 0) return; -    accumulate_unicast_byte(neigh, v4 ? 1 : 2); -    accumulate_unicast_byte(neigh, v4 ? plen - 96 : plen); -    accumulate_unicast_short(neigh, seqno); -    accumulate_unicast_byte(neigh, hop_count); -    accumulate_unicast_byte(neigh, 0); -    accumulate_unicast_bytes(neigh, id, 8); -    if(prefix) { -        if(v4) -            accumulate_unicast_bytes(neigh, prefix + 12, pb); -        else -            accumulate_unicast_bytes(neigh, prefix, pb); -    } -    end_unicast_message(neigh, MESSAGE_MH_REQUEST, len); -} - -void -send_request_resend(struct neighbour *neigh, -                    const unsigned char *prefix, unsigned char plen, -                    unsigned short seqno, unsigned char *id) -{ -    if(neigh) -        send_unicast_multihop_request(neigh, prefix, plen, seqno, id, 127); -    else -        send_multihop_request(NULL, prefix, plen, seqno, id, 127); - -    record_resend(RESEND_REQUEST, prefix, plen, seqno, id, -                  neigh ? neigh->ifp : NULL, resend_delay); -} - -void -handle_request(struct neighbour *neigh, const unsigned char *prefix, -               unsigned char plen, unsigned char hop_count, -               unsigned short seqno, const unsigned char *id) -{ -    struct xroute *xroute; -    struct babel_route *route; -    struct neighbour *successor = NULL; - -    xroute = find_xroute(prefix, plen); -    route = find_installed_route(prefix, plen); - -    if(xroute && (!route || xroute->metric <= kernel_metric)) { -        if(hop_count > 0 && memcmp(id, myid, 8) == 0) { -            if(seqno_compare(seqno, myseqno) > 0) { -                if(seqno_minus(seqno, myseqno) > 100) { -                    /* Hopelessly out-of-date request */ -                    return; -                } -                update_myseqno(); -            } -        } -        send_update(neigh->ifp, 1, prefix, plen); -        return; -    } - -    if(route && -       (memcmp(id, route->src->id, 8) != 0 || -        seqno_compare(seqno, route->seqno) <= 0)) { -        send_update(neigh->ifp, 1, prefix, plen); -        return; -    } - -    if(hop_count <= 1) -        return; - -    if(route && memcmp(id, route->src->id, 8) == 0 && -       seqno_minus(seqno, route->seqno) > 100) { -        /* Hopelessly out-of-date */ -        return; -    } - -    if(request_redundant(neigh->ifp, prefix, plen, seqno, id)) -        return; - -    /* Let's try to forward this request. */ -    if(route && route_metric(route) < INFINITY) -        successor = route->neigh; - -    if(!successor || successor == neigh) { -        /* We were about to forward a request to its requestor.  Try to -           find a different neighbour to forward the request to. */ -        struct babel_route *other_route; - -        other_route = find_best_route(prefix, plen, 0, neigh); -        if(other_route && route_metric(other_route) < INFINITY) -            successor = other_route->neigh; -    } - -    if(!successor || successor == neigh) -        /* Give up */ -        return; - -    send_unicast_multihop_request(successor, prefix, plen, seqno, id, -                                  hop_count - 1); -    record_resend(RESEND_REQUEST, prefix, plen, seqno, id, -                  neigh->ifp, 0); -} diff --git a/babeld/message.h b/babeld/message.h deleted file mode 100644 index 6a9aa10466..0000000000 --- a/babeld/message.h +++ /dev/null @@ -1,111 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef BABEL_MESSAGE_H -#define BABEL_MESSAGE_H - -#include "babel_interface.h" - -#define MAX_BUFFERED_UPDATES 200 - -#define BUCKET_TOKENS_MAX 200 -#define BUCKET_TOKENS_PER_SEC 40 - -#define MESSAGE_PAD1 0 -#define MESSAGE_PADN 1 -#define MESSAGE_ACK_REQ 2 -#define MESSAGE_ACK 3 -#define MESSAGE_HELLO 4 -#define MESSAGE_IHU 5 -#define MESSAGE_ROUTER_ID 6 -#define MESSAGE_NH 7 -#define MESSAGE_UPDATE 8 -#define MESSAGE_REQUEST 9 -#define MESSAGE_MH_REQUEST 10 - - -extern unsigned short myseqno; -extern struct timeval seqno_time; - -extern int broadcast_ihu; -extern int split_horizon; - -extern unsigned char packet_header[4]; - -extern struct neighbour *unicast_neighbour; -extern struct timeval unicast_flush_timeout; - -void parse_packet(const unsigned char *from, struct interface *ifp, -                  const unsigned char *packet, int packetlen); -void flushbuf(struct interface *ifp); -void flushupdates(struct interface *ifp); -void send_ack(struct neighbour *neigh, unsigned short nonce, -              unsigned short interval); -void send_hello_noupdate(struct interface *ifp, unsigned interval); -void send_hello(struct interface *ifp); -void flush_unicast(int dofree); -void send_update(struct interface *ifp, int urgent, -                 const unsigned char *prefix, unsigned char plen); -void send_update_resend(struct interface *ifp, -                        const unsigned char *prefix, unsigned char plen); -void send_wildcard_retraction(struct interface *ifp); -void update_myseqno(void); -void send_self_update(struct interface *ifp); -void send_ihu(struct neighbour *neigh, struct interface *ifp); -void send_marginal_ihu(struct interface *ifp); -void send_request(struct interface *ifp, -                  const unsigned char *prefix, unsigned char plen); -void send_unicast_request(struct neighbour *neigh, -                          const unsigned char *prefix, unsigned char plen); -void send_multihop_request(struct interface *ifp, -                           const unsigned char *prefix, unsigned char plen, -                           unsigned short seqno, const unsigned char *id, -                           unsigned short hop_count); -void -send_unicast_multihop_request(struct neighbour *neigh, -                              const unsigned char *prefix, unsigned char plen, -                              unsigned short seqno, const unsigned char *id, -                              unsigned short hop_count); -void send_request_resend(struct neighbour *neigh, -                         const unsigned char *prefix, unsigned char plen, -                         unsigned short seqno, unsigned char *id); -void handle_request(struct neighbour *neigh, const unsigned char *prefix, -                    unsigned char plen, unsigned char hop_count, -                    unsigned short seqno, const unsigned char *id); - -#endif diff --git a/babeld/neighbour.c b/babeld/neighbour.c deleted file mode 100644 index 5a327dfe91..0000000000 --- a/babeld/neighbour.c +++ /dev/null @@ -1,343 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - * -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <sys/time.h> -#include <time.h> - -#include <zebra.h> -#include "if.h" - -#include "babel_main.h" -#include "babeld.h" -#include "util.h" -#include "babel_interface.h" -#include "neighbour.h" -#include "source.h" -#include "route.h" -#include "message.h" -#include "resend.h" - -struct neighbour *neighs = NULL; - -static struct neighbour * -find_neighbour_nocreate(const unsigned char *address, struct interface *ifp) -{ -    struct neighbour *neigh; -    FOR_ALL_NEIGHBOURS(neigh) { -        if(memcmp(address, neigh->address, 16) == 0 && -           neigh->ifp == ifp) -            return neigh; -    } -    return NULL; -} - -void -flush_neighbour(struct neighbour *neigh) -{ -    flush_neighbour_routes(neigh); -    if(unicast_neighbour == neigh) -        flush_unicast(1); -    flush_resends(neigh); - -    if(neighs == neigh) { -        neighs = neigh->next; -    } else { -        struct neighbour *previous = neighs; -        while(previous->next != neigh) -            previous = previous->next; -        previous->next = neigh->next; -    } -    free(neigh); -} - -struct neighbour * -find_neighbour(const unsigned char *address, struct interface *ifp) -{ -    struct neighbour *neigh; -    const struct timeval zero = {0, 0}; - -    neigh = find_neighbour_nocreate(address, ifp); -    if(neigh) -        return neigh; - -    debugf(BABEL_DEBUG_COMMON,"Creating neighbour %s on %s.", -           format_address(address), ifp->name); - -    neigh = malloc(sizeof(struct neighbour)); -    if(neigh == NULL) { -        zlog_err("malloc(neighbour): %s", safe_strerror(errno)); -        return NULL; -    } - -    neigh->hello_seqno = -1; -    memcpy(neigh->address, address, 16); -    neigh->reach = 0; -    neigh->txcost = INFINITY; -    neigh->ihu_time = babel_now; -    neigh->hello_time = zero; -    neigh->hello_interval = 0; -    neigh->ihu_interval = 0; -    neigh->ifp = ifp; -    neigh->next = neighs; -    neighs = neigh; -    send_hello(ifp); -    return neigh; -} - -/* Recompute a neighbour's rxcost.  Return true if anything changed. -   This does not call local_notify_neighbour, see update_neighbour_metric. */ -int -update_neighbour(struct neighbour *neigh, int hello, int hello_interval) -{ -    int missed_hellos; -    int rc = 0; - -    if(hello < 0) { -        if(neigh->hello_interval <= 0) -            return rc; -        missed_hellos = -            ((int)timeval_minus_msec(&babel_now, &neigh->hello_time) - -             neigh->hello_interval * 7) / -            (neigh->hello_interval * 10); -        if(missed_hellos <= 0) -            return rc; -        timeval_add_msec(&neigh->hello_time, &neigh->hello_time, -                          missed_hellos * neigh->hello_interval * 10); -    } else { -        if(neigh->hello_seqno >= 0 && neigh->reach > 0) { -            missed_hellos = seqno_minus(hello, neigh->hello_seqno) - 1; -            if(missed_hellos < -8) { -                /* Probably a neighbour that rebooted and lost its seqno. -                   Reboot the universe. */ -                neigh->reach = 0; -                missed_hellos = 0; -                rc = 1; -            } else if(missed_hellos < 0) { -                if(hello_interval > neigh->hello_interval) { -                    /* This neighbour has increased its hello interval, -                       and we didn't notice. */ -                    neigh->reach <<= -missed_hellos; -                    missed_hellos = 0; -                } else { -                    /* Late hello.  Probably due to the link layer buffering -                       packets during a link outage.  Ignore it, but reset -                       the expected seqno. */ -                    neigh->hello_seqno = hello; -                    hello = -1; -                    missed_hellos = 0; -                } -                rc = 1; -            } -        } else { -            missed_hellos = 0; -        } -        neigh->hello_time = babel_now; -        neigh->hello_interval = hello_interval; -    } - -    if(missed_hellos > 0) { -        neigh->reach >>= missed_hellos; -        neigh->hello_seqno = seqno_plus(neigh->hello_seqno, missed_hellos); -        missed_hellos = 0; -        rc = 1; -    } - -    if(hello >= 0) { -        neigh->hello_seqno = hello; -        neigh->reach >>= 1; -        neigh->reach |= 0x8000; -        if((neigh->reach & 0xFC00) != 0xFC00) -            rc = 1; -    } - -    /* Make sure to give neighbours some feedback early after association */ -    if((neigh->reach & 0xBF00) == 0x8000) { -        /* A new neighbour */ -        send_hello(neigh->ifp); -    } else { -        /* Don't send hellos, in order to avoid a positive feedback loop. */ -        int a = (neigh->reach & 0xC000); -        int b = (neigh->reach & 0x3000); -        if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) { -            /* Reachability is either 1100 or 0011 */ -            send_self_update(neigh->ifp); -        } -    } - -    if((neigh->reach & 0xFC00) == 0xC000) { -        /* This is a newish neighbour, let's request a full route dump. -           We ought to avoid this when the network is dense */ -        send_unicast_request(neigh, NULL, 0); -        send_ihu(neigh, NULL); -    } -    return rc; -} - -static int -reset_txcost(struct neighbour *neigh) -{ -    unsigned delay; - -    delay = timeval_minus_msec(&babel_now, &neigh->ihu_time); - -    if(neigh->ihu_interval > 0 && delay < neigh->ihu_interval * 10U * 3U) -        return 0; - -    /* If we're losing a lot of packets, we probably lost an IHU too */ -    if(delay >= 180000 || (neigh->reach & 0xFFF0) == 0 || -       (neigh->ihu_interval > 0 && -        delay >= neigh->ihu_interval * 10U * 10U)) { -        neigh->txcost = INFINITY; -        neigh->ihu_time = babel_now; -        return 1; -    } - -    return 0; -} - -unsigned -neighbour_txcost(struct neighbour *neigh) -{ -    return neigh->txcost; -} - -unsigned -check_neighbours() -{ -    struct neighbour *neigh; -    int changed, rc; -    unsigned msecs = 50000; - -    debugf(BABEL_DEBUG_COMMON,"Checking neighbours."); - -    neigh = neighs; -    while(neigh) { -        changed = update_neighbour(neigh, -1, 0); - -        if(neigh->reach == 0 || -           neigh->hello_time.tv_sec > babel_now.tv_sec || /* clock stepped */ -           timeval_minus_msec(&babel_now, &neigh->hello_time) > 300000) { -            struct neighbour *old = neigh; -            neigh = neigh->next; -            flush_neighbour(old); -            continue; -        } - -        rc = reset_txcost(neigh); -        changed = changed || rc; - -        update_neighbour_metric(neigh, changed); - -        if(neigh->hello_interval > 0) -            msecs = MIN(msecs, neigh->hello_interval * 10U); -        if(neigh->ihu_interval > 0) -            msecs = MIN(msecs, neigh->ihu_interval * 10U); -        neigh = neigh->next; -    } - -    return msecs; -} - -unsigned -neighbour_rxcost(struct neighbour *neigh) -{ -    unsigned delay; -    unsigned short reach = neigh->reach; - -    delay = timeval_minus_msec(&babel_now, &neigh->hello_time); - -    if((reach & 0xFFF0) == 0 || delay >= 180000) { -        return INFINITY; -    } else if(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ) { -        int sreach = -            ((reach & 0x8000) >> 2) + -            ((reach & 0x4000) >> 1) + -            (reach & 0x3FFF); -        /* 0 <= sreach <= 0x7FFF */ -        int cost = (0x8000 * babel_get_if_nfo(neigh->ifp)->cost) / (sreach + 1); -        /* cost >= interface->cost */ -        if(delay >= 40000) -            cost = (cost * (delay - 20000) + 10000) / 20000; -        return MIN(cost, INFINITY); -    } else { -        /* To lose one hello is a misfortune, to lose two is carelessness. */ -        if((reach & 0xC000) == 0xC000) -            return babel_get_if_nfo(neigh->ifp)->cost; -        else if((reach & 0xC000) == 0) -            return INFINITY; -        else if((reach & 0x2000)) -            return babel_get_if_nfo(neigh->ifp)->cost; -        else -            return INFINITY; -    } -} - -unsigned -neighbour_cost(struct neighbour *neigh) -{ -    unsigned a, b; - -    if(!if_up(neigh->ifp)) -        return INFINITY; - -    a = neighbour_txcost(neigh); - -    if(a >= INFINITY) -        return INFINITY; - -    b = neighbour_rxcost(neigh); -    if(b >= INFINITY) -        return INFINITY; - -    if(!(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ) -       || (a < 256 && b < 256)) { -        return a; -    } else { -        /* a = 256/alpha, b = 256/beta, where alpha and beta are the expected -           probabilities of a packet getting through in the direct and reverse -           directions. */ -        a = MAX(a, 256); -        b = MAX(b, 256); -        /* 1/(alpha * beta), which is just plain ETX. */ -        /* Since a and b are capped to 16 bits, overflow is impossible. */ -        return (a * b + 128) >> 8; -    } -} diff --git a/babeld/neighbour.h b/babeld/neighbour.h deleted file mode 100644 index cf8c0f0b23..0000000000 --- a/babeld/neighbour.h +++ /dev/null @@ -1,66 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -struct neighbour { -    struct neighbour *next; -    /* This is -1 when unknown, so don't make it unsigned */ -    int hello_seqno; -    unsigned char address[16]; -    unsigned short reach; -    unsigned short txcost; -    struct timeval hello_time; -    struct timeval ihu_time; -    unsigned short hello_interval; /* in centiseconds */ -    unsigned short ihu_interval;   /* in centiseconds */ -    struct interface *ifp; -}; - -extern struct neighbour *neighs; - -#define FOR_ALL_NEIGHBOURS(_neigh) \ -    for(_neigh = neighs; _neigh; _neigh = _neigh->next) - -int neighbour_valid(struct neighbour *neigh); -void flush_neighbour(struct neighbour *neigh); -struct neighbour *find_neighbour(const unsigned char *address, -                                 struct interface *ifp); -int update_neighbour(struct neighbour *neigh, int hello, int hello_interval); -unsigned check_neighbours(void); -unsigned neighbour_txcost(struct neighbour *neigh); -unsigned neighbour_rxcost(struct neighbour *neigh); -unsigned neighbour_cost(struct neighbour *neigh); diff --git a/babeld/net.c b/babeld/net.c deleted file mode 100644 index 5e0200b0ab..0000000000 --- a/babeld/net.c +++ /dev/null @@ -1,239 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/uio.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <errno.h> - -#include "babeld.h" -#include "util.h" -#include "net.h" - -int -babel_socket(int port) -{ -    struct sockaddr_in6 sin6; -    int s, rc; -    int saved_errno; -    int one = 1, zero = 0; -    const int ds = 0xc0;        /* CS6 - Network Control */ - -    s = socket(PF_INET6, SOCK_DGRAM, 0); -    if(s < 0) -        return -1; - -    rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); -    if(rc < 0) -        goto fail; - -    rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); -    if(rc < 0) -        goto fail; - -    rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, -                    &zero, sizeof(zero)); -    if(rc < 0) -        goto fail; - -    rc = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, -                    &one, sizeof(one)); -    if(rc < 0) -        goto fail; - -    rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, -                    &one, sizeof(one)); -    if(rc < 0) -        goto fail; - -#ifdef IPV6_TCLASS -    rc = setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &ds, sizeof(ds)); -#else -    rc = -1; -    errno = ENOSYS; -#endif -    if(rc < 0) -        perror("Couldn't set traffic class"); - -    rc = fcntl(s, F_GETFL, 0); -    if(rc < 0) -        goto fail; - -    rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK)); -    if(rc < 0) -        goto fail; - -    rc = fcntl(s, F_GETFD, 0); -    if(rc < 0) -        goto fail; - -    rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC); -    if(rc < 0) -        goto fail; - -    memset(&sin6, 0, sizeof(sin6)); -    sin6.sin6_family = AF_INET6; -    sin6.sin6_port = htons(port); -    rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6)); -    if(rc < 0) -        goto fail; - -    return s; - - fail: -    saved_errno = errno; -    close(s); -    errno = saved_errno; -    return -1; -} - -int -babel_recv(int s, void *buf, int buflen, struct sockaddr *sin, int slen) -{ -    struct iovec iovec; -    struct msghdr msg; -    int rc; - -    memset(&msg, 0, sizeof(msg)); -    iovec.iov_base = buf; -    iovec.iov_len = buflen; -    msg.msg_name = sin; -    msg.msg_namelen = slen; -    msg.msg_iov = &iovec; -    msg.msg_iovlen = 1; - -    rc = recvmsg(s, &msg, 0); -    return rc; -} - -int -babel_send(int s, -           void *buf1, int buflen1, void *buf2, int buflen2, -           struct sockaddr *sin, int slen) -{ -    struct iovec iovec[2]; -    struct msghdr msg; -    int rc; - -    iovec[0].iov_base = buf1; -    iovec[0].iov_len = buflen1; -    iovec[1].iov_base = buf2; -    iovec[1].iov_len = buflen2; -    memset(&msg, 0, sizeof(msg)); -    msg.msg_name = (struct sockaddr*)sin; -    msg.msg_namelen = slen; -    msg.msg_iov = iovec; -    msg.msg_iovlen = 2; - - again: -    rc = sendmsg(s, &msg, 0); -    if(rc < 0) { -        if(errno == EINTR) -            goto again; -        else if(errno == EAGAIN) { -            int rc2; -            rc2 = wait_for_fd(1, s, 5); -            if(rc2 > 0) -                goto again; -            errno = EAGAIN; -        } -    } -    return rc; -} - -int -tcp_server_socket(int port, int local) -{ -    struct sockaddr_in6 sin6; -    int s, rc, saved_errno; -    int one = 1; - -    s = socket(PF_INET6, SOCK_STREAM, 0); -    if(s < 0) -        return -1; - -    rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); -    if(rc < 0) -        goto fail; - -    rc = fcntl(s, F_GETFL, 0); -    if(rc < 0) -        goto fail; - -    rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK)); -    if(rc < 0) -        goto fail; - -    rc = fcntl(s, F_GETFD, 0); -    if(rc < 0) -        goto fail; - -    rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC); -    if(rc < 0) -        goto fail; - -    memset(&sin6, 0, sizeof(sin6)); -    sin6.sin6_family = AF_INET6; -    sin6.sin6_port = htons(port); -    if(local) { -        rc = inet_pton(AF_INET6, "::1", &sin6.sin6_addr); -        if(rc < 0) -            goto fail; -    } -    rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6)); -    if(rc < 0) -        goto fail; - -    rc = listen(s, 2); -    if(rc < 0) -        goto fail; - -    return s; - - fail: -    saved_errno = errno; -    close(s); -    errno = saved_errno; -    return -1; -} diff --git a/babeld/net.h b/babeld/net.h deleted file mode 100644 index 4bd0f04f96..0000000000 --- a/babeld/net.h +++ /dev/null @@ -1,44 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -int babel_socket(int port); -int babel_recv(int s, void *buf, int buflen, struct sockaddr *sin, int slen); -int babel_send(int s, -               void *buf1, int buflen1, void *buf2, int buflen2, -               struct sockaddr *sin, int slen); -int tcp_server_socket(int port, int local); diff --git a/babeld/resend.c b/babeld/resend.c deleted file mode 100644 index 1cc6290e78..0000000000 --- a/babeld/resend.c +++ /dev/null @@ -1,330 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <sys/time.h> -#include <time.h> -#include <string.h> -#include <stdlib.h> - -#include <zebra.h> -#include "if.h" - -#include "babel_main.h" -#include "babeld.h" -#include "util.h" -#include "neighbour.h" -#include "resend.h" -#include "message.h" -#include "babel_interface.h" - -struct timeval resend_time = {0, 0}; -struct resend *to_resend = NULL; - -static int -resend_match(struct resend *resend, -             int kind, const unsigned char *prefix, unsigned char plen) -{ -    return (resend->kind == kind && -            resend->plen == plen && memcmp(resend->prefix, prefix, 16) == 0); -} - -/* This is called by neigh.c when a neighbour is flushed */ - -void -flush_resends(struct neighbour *neigh) -{ -    /* Nothing for now */ -} - -static struct resend * -find_resend(int kind, const unsigned char *prefix, unsigned char plen, -             struct resend **previous_return) -{ -    struct resend *current, *previous; - -    previous = NULL; -    current = to_resend; -    while(current) { -        if(resend_match(current, kind, prefix, plen)) { -            if(previous_return) -                *previous_return = previous; -            return current; -        } -        previous = current; -        current = current->next; -    } - -    return NULL; -} - -struct resend * -find_request(const unsigned char *prefix, unsigned char plen, -             struct resend **previous_return) -{ -    return find_resend(RESEND_REQUEST, prefix, plen, previous_return); -} - -int -record_resend(int kind, const unsigned char *prefix, unsigned char plen, -              unsigned short seqno, const unsigned char *id, -              struct interface *ifp, int delay) -{ -    struct resend *resend; -    unsigned int ifindex = ifp ? ifp->ifindex : 0; - -    if((kind == RESEND_REQUEST && -        input_filter(NULL, prefix, plen, NULL, ifindex) >= INFINITY) || -       (kind == RESEND_UPDATE && -        output_filter(NULL, prefix, plen, ifindex) >= INFINITY)) -        return 0; - -    if(delay >= 0xFFFF) -        delay = 0xFFFF; - -    resend = find_resend(kind, prefix, plen, NULL); -    if(resend) { -        if(resend->delay && delay) -            resend->delay = MIN(resend->delay, delay); -        else if(delay) -            resend->delay = delay; -        resend->time = babel_now; -        resend->max = RESEND_MAX; -        if(id && memcmp(resend->id, id, 8) == 0 && -           seqno_compare(resend->seqno, seqno) > 0) { -            return 0; -        } -        if(id) -            memcpy(resend->id, id, 8); -        else -            memset(resend->id, 0, 8); -        resend->seqno = seqno; -        if(resend->ifp != ifp) -            resend->ifp = NULL; -    } else { -        resend = malloc(sizeof(struct resend)); -        if(resend == NULL) -            return -1; -        resend->kind = kind; -        resend->max = RESEND_MAX; -        resend->delay = delay; -        memcpy(resend->prefix, prefix, 16); -        resend->plen = plen; -        resend->seqno = seqno; -        if(id) -            memcpy(resend->id, id, 8); -        else -            memset(resend->id, 0, 8); -        resend->ifp = ifp; -        resend->time = babel_now; -        resend->next = to_resend; -        to_resend = resend; -    } - -    if(resend->delay) { -        struct timeval timeout; -        timeval_add_msec(&timeout, &resend->time, resend->delay); -        timeval_min(&resend_time, &timeout); -    } -    return 1; -} - -static int -resend_expired(struct resend *resend) -{ -    switch(resend->kind) { -    case RESEND_REQUEST: -        return timeval_minus_msec(&babel_now, &resend->time) >= REQUEST_TIMEOUT; -    default: -        return resend->max <= 0; -    } -} - -int -unsatisfied_request(const unsigned char *prefix, unsigned char plen, -                    unsigned short seqno, const unsigned char *id) -{ -    struct resend *request; - -    request = find_request(prefix, plen, NULL); -    if(request == NULL || resend_expired(request)) -        return 0; - -    if(memcmp(request->id, id, 8) != 0 || -       seqno_compare(request->seqno, seqno) <= 0) -        return 1; - -    return 0; -} - -/* Determine whether a given request should be forwarded. */ -int -request_redundant(struct interface *ifp, -                  const unsigned char *prefix, unsigned char plen, -                  unsigned short seqno, const unsigned char *id) -{ -    struct resend *request; - -    request = find_request(prefix, plen, NULL); -    if(request == NULL || resend_expired(request)) -        return 0; - -    if(memcmp(request->id, id, 8) == 0 && -       seqno_compare(request->seqno, seqno) > 0) -        return 0; - -    if(request->ifp != NULL && request->ifp != ifp) -        return 0; - -    if(request->max > 0) -        /* Will be resent. */ -        return 1; - -    if(timeval_minus_msec(&babel_now, &request->time) < -       (ifp ? MIN(babel_get_if_nfo(ifp)->hello_interval, 1000) : 1000)) -        /* Fairly recent. */ -        return 1; - -    return 0; -} - -int -satisfy_request(const unsigned char *prefix, unsigned char plen, -                unsigned short seqno, const unsigned char *id, -                struct interface *ifp) -{ -    struct resend *request, *previous; - -    request = find_request(prefix, plen, &previous); -    if(request == NULL) -        return 0; - -    if(ifp != NULL && request->ifp != ifp) -        return 0; - -    if(memcmp(request->id, id, 8) != 0 || -       seqno_compare(request->seqno, seqno) <= 0) { -        /* We cannot remove the request, as we may be walking the list right -           now.  Mark it as expired, so that expire_resend will remove it. */ -        request->max = 0; -        request->time.tv_sec = 0; -        recompute_resend_time(); -        return 1; -    } - -    return 0; -} - -void -expire_resend() -{ -    struct resend *current, *previous; -    int recompute = 0; - -    previous = NULL; -    current = to_resend; -    while(current) { -        if(resend_expired(current)) { -            if(previous == NULL) { -                to_resend = current->next; -                free(current); -                current = to_resend; -            } else { -                previous->next = current->next; -                free(current); -                current = previous->next; -            } -            recompute = 1; -        } else { -            previous = current; -            current = current->next; -        } -    } -    if(recompute) -        recompute_resend_time(); -} - -void -recompute_resend_time() -{ -    struct resend *request; -    struct timeval resend = {0, 0}; - -    request = to_resend; -    while(request) { -        if(!resend_expired(request) && request->delay > 0 && request->max > 0) { -            struct timeval timeout; -            timeval_add_msec(&timeout, &request->time, request->delay); -            timeval_min(&resend, &timeout); -        } -        request = request->next; -    } - -    resend_time = resend; -} - -void -do_resend() -{ -    struct resend *resend; - -    resend = to_resend; -    while(resend) { -        if(!resend_expired(resend) && resend->delay > 0 && resend->max > 0) { -            struct timeval timeout; -            timeval_add_msec(&timeout, &resend->time, resend->delay); -            if(timeval_compare(&babel_now, &timeout) >= 0) { -                switch(resend->kind) { -                case RESEND_REQUEST: -                    send_multihop_request(resend->ifp, -                                          resend->prefix, resend->plen, -                                          resend->seqno, resend->id, 127); -                    break; -                case RESEND_UPDATE: -                    send_update(resend->ifp, 1, -                                resend->prefix, resend->plen); -                    break; -                default: abort(); -                } -                resend->delay = MIN(0xFFFF, resend->delay * 2); -                resend->max--; -            } -        } -        resend = resend->next; -    } -    recompute_resend_time(); -} diff --git a/babeld/resend.h b/babeld/resend.h deleted file mode 100644 index a6755c0eba..0000000000 --- a/babeld/resend.h +++ /dev/null @@ -1,77 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#define REQUEST_TIMEOUT 65000 -#define RESEND_MAX 3 - -#define RESEND_REQUEST 1 -#define RESEND_UPDATE 2 - -struct resend { -    unsigned char kind; -    unsigned char max; -    unsigned short delay; -    struct timeval time; -    unsigned char prefix[16]; -    unsigned char plen; -    unsigned short seqno; -    unsigned char id[8]; -    struct interface *ifp; -    struct resend *next; -}; - -extern struct timeval resend_time; - -struct resend *find_request(const unsigned char *prefix, unsigned char plen, -                            struct resend **previous_return); -void flush_resends(struct neighbour *neigh); -int record_resend(int kind, const unsigned char *prefix, unsigned char plen, -                   unsigned short seqno, const unsigned char *id, -                   struct interface *ifp, int delay); -int unsatisfied_request(const unsigned char *prefix, unsigned char plen, -                        unsigned short seqno, const unsigned char *id); -int request_redundant(struct interface *ifp, -                      const unsigned char *prefix, unsigned char plen, -                      unsigned short seqno, const unsigned char *id); -int satisfy_request(const unsigned char *prefix, unsigned char plen, -                    unsigned short seqno, const unsigned char *id, -                    struct interface *ifp); - -void expire_resend(void); -void recompute_resend_time(void); -void do_resend(void); diff --git a/babeld/route.c b/babeld/route.c deleted file mode 100644 index fe2b9cebb7..0000000000 --- a/babeld/route.c +++ /dev/null @@ -1,1019 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <zebra.h> -#include "if.h" - -#include "babeld.h" -#include "util.h" -#include "kernel.h" -#include "babel_interface.h" -#include "source.h" -#include "neighbour.h" -#include "route.h" -#include "xroute.h" -#include "message.h" -#include "resend.h" - -static void consider_route(struct babel_route *route); - -struct babel_route **routes = NULL; -static int route_slots = 0, max_route_slots = 0; -int kernel_metric = 0; -int allow_duplicates = -1; -int diversity_kind = DIVERSITY_NONE; -int diversity_factor = 256;     /* in units of 1/256 */ -int keep_unfeasible = 0; - -/* We maintain a list of "slots", ordered by prefix.  Every slot -   contains a linked list of the routes to this prefix, with the -   installed route, if any, at the head of the list. */ - -static int -route_compare(const unsigned char *prefix, unsigned char plen, -               struct babel_route *route) -{ -    int i = memcmp(prefix, route->src->prefix, 16); -    if(i != 0) -        return i; - -    if(plen < route->src->plen) -        return -1; -    else if(plen > route->src->plen) -        return 1; -    else -        return 0; -} - -/* Performs binary search, returns -1 in case of failure.  In the latter -   case, new_return is the place where to insert the new element. */ - -static int -find_route_slot(const unsigned char *prefix, unsigned char plen, -                int *new_return) -{ -    int p, m, g, c; - -    if(route_slots < 1) { -        if(new_return) -            *new_return = 0; -        return -1; -    } - -    p = 0; g = route_slots - 1; - -    do { -        m = (p + g) / 2; -        c = route_compare(prefix, plen, routes[m]); -        if(c == 0) -            return m; -        else if(c < 0) -            g = m - 1; -        else -            p = m + 1; -    } while(p <= g); - -    if(new_return) -        *new_return = p; - -    return -1; -} - -struct babel_route * -find_route(const unsigned char *prefix, unsigned char plen, -           struct neighbour *neigh, const unsigned char *nexthop) -{ -    struct babel_route *route; -    int i = find_route_slot(prefix, plen, NULL); - -    if(i < 0) -        return NULL; - -    route = routes[i]; - -    while(route) { -        if(route->neigh == neigh && memcmp(route->nexthop, nexthop, 16) == 0) -            return route; -        route = route->next; -    } - -    return NULL; -} - -struct babel_route * -find_installed_route(const unsigned char *prefix, unsigned char plen) -{ -    int i = find_route_slot(prefix, plen, NULL); - -    if(i >= 0 && routes[i]->installed) -        return routes[i]; - -    return NULL; -} - -/* Returns an overestimate of the number of installed routes. */ -int -installed_routes_estimate(void) -{ -    return route_slots; -} - -static int -resize_route_table(int new_slots) -{ -    struct babel_route **new_routes; -    assert(new_slots >= route_slots); - -    if(new_slots == 0) { -        new_routes = NULL; -        free(routes); -    } else { -        new_routes = realloc(routes, new_slots * sizeof(struct babel_route*)); -        if(new_routes == NULL) -            return -1; -    } - -    max_route_slots = new_slots; -    routes = new_routes; -    return 1; -} - -/* Insert a route into the table.  If successful, retains the route. -   On failure, caller must free the route. */ -static struct babel_route * -insert_route(struct babel_route *route) -{ -    int i, n; - -    assert(!route->installed); - -    i = find_route_slot(route->src->prefix, route->src->plen, &n); - -    if(i < 0) { -        if(route_slots >= max_route_slots) -            resize_route_table(max_route_slots < 1 ? 8 : 2 * max_route_slots); -        if(route_slots >= max_route_slots) -            return NULL; -        route->next = NULL; -        if(n < route_slots) -            memmove(routes + n + 1, routes + n, -                    (route_slots - n) * sizeof(struct babel_route*)); -        route_slots++; -        routes[n] = route; -    } else { -        struct babel_route *r; -        r = routes[i]; -        while(r->next) -            r = r->next; -        r->next = route; -        route->next = NULL; -    } - -    return route; -} - -void -flush_route(struct babel_route *route) -{ -    int i; -    struct source *src; -    unsigned oldmetric; -    int lost = 0; - -    oldmetric = route_metric(route); -    src = route->src; - -    if(route->installed) { -        uninstall_route(route); -        lost = 1; -    } - -    i = find_route_slot(route->src->prefix, route->src->plen, NULL); -    assert(i >= 0 && i < route_slots); - -    if(route == routes[i]) { -        routes[i] = route->next; -        route->next = NULL; -        free(route); - -        if(routes[i] == NULL) { -            if(i < route_slots - 1) -                memmove(routes + i, routes + i + 1, -                        (route_slots - i - 1) * sizeof(struct babel_route*)); -            routes[route_slots - 1] = NULL; -            route_slots--; -        } - -        if(route_slots == 0) -            resize_route_table(0); -        else if(max_route_slots > 8 && route_slots < max_route_slots / 4) -            resize_route_table(max_route_slots / 2); -    } else { -        struct babel_route *r = routes[i]; -        while(r->next != route) -            r = r->next; -        r->next = route->next; -        route->next = NULL; -        free(route); -    } - -    if(lost) -        route_lost(src, oldmetric); - -    release_source(src); -} - -void -flush_all_routes() -{ -    int i; - -    /* Start from the end, to avoid shifting the table. */ -    i = route_slots - 1; -    while(i >= 0) { -        while(i < route_slots) { -        /* Uninstall first, to avoid calling route_lost. */ -            if(routes[i]->installed) -                uninstall_route(routes[0]); -            flush_route(routes[i]); -        } -        i--; -    } - -    check_sources_released(); -} - -void -flush_neighbour_routes(struct neighbour *neigh) -{ -    int i; - -    i = 0; -    while(i < route_slots) { -        struct babel_route *r; -        r = routes[i]; -        while(r) { -            if(r->neigh == neigh) { -                flush_route(r); -                goto again; -            } -            r = r->next; -        } -        i++; -    again: -        ; -    } -} - -void -flush_interface_routes(struct interface *ifp, int v4only) -{ -    int i; - -    i = 0; -    while(i < route_slots) { -        struct babel_route *r; -        r = routes[i]; -        while(r) { -            if(r->neigh->ifp == ifp && -               (!v4only || v4mapped(r->nexthop))) { -                flush_route(r); -                goto again; -            } -            r = r->next; -        } -        i++; -    again: -        ; -    } -} - -/* Iterate a function over all routes. */ -void -for_all_routes(void (*f)(struct babel_route*, void*), void *closure) -{ -    int i; - -    for(i = 0; i < route_slots; i++) { -        struct babel_route *r = routes[i]; -        while(r) { -            (*f)(r, closure); -            r = r->next; -        } -    } -} - -void -for_all_installed_routes(void (*f)(struct babel_route*, void*), void *closure) -{ -    int i; - -    for(i = 0; i < route_slots; i++) { -        if(routes[i]->installed) -            (*f)(routes[i], closure); -    } -} - -static int -metric_to_kernel(int metric) -{ -    return metric < INFINITY ? kernel_metric : KERNEL_INFINITY; -} - -/* This is used to maintain the invariant that the installed route is at -   the head of the list. */ -static void -move_installed_route(struct babel_route *route, int i) -{ -    assert(i >= 0 && i < route_slots); -    assert(route->installed); - -    if(route != routes[i]) { -        struct babel_route *r = routes[i]; -        while(r->next != route) -            r = r->next; -        r->next = route->next; -        route->next = routes[i]; -        routes[i] = route; -    } -} - -void -install_route(struct babel_route *route) -{ -    int i, rc; - -    if(route->installed) -        return; - -    if(!route_feasible(route)) -        zlog_err("WARNING: installing unfeasible route " -                 "(this shouldn't happen)."); - -    i = find_route_slot(route->src->prefix, route->src->plen, NULL); -    assert(i >= 0 && i < route_slots); - -    if(routes[i] != route && routes[i]->installed) { -        fprintf(stderr, "WARNING: attempting to install duplicate route " -                "(this shouldn't happen)."); -        return; -    } - -    rc = kernel_route(ROUTE_ADD, route->src->prefix, route->src->plen, -                      route->nexthop, -                      route->neigh->ifp->ifindex, -                      metric_to_kernel(route_metric(route)), NULL, 0, 0); -    if(rc < 0) { -        int save = errno; -        zlog_err("kernel_route(ADD): %s", safe_strerror(errno)); -        if(save != EEXIST) -            return; -    } -    route->installed = 1; -    move_installed_route(route, i); - -} - -void -uninstall_route(struct babel_route *route) -{ -    int rc; - -    if(!route->installed) -        return; - -    rc = kernel_route(ROUTE_FLUSH, route->src->prefix, route->src->plen, -                      route->nexthop, -                      route->neigh->ifp->ifindex, -                      metric_to_kernel(route_metric(route)), NULL, 0, 0); -    if(rc < 0) -        zlog_err("kernel_route(FLUSH): %s", safe_strerror(errno)); - -    route->installed = 0; -} - -/* This is equivalent to uninstall_route followed with install_route, -   but without the race condition.  The destination of both routes -   must be the same. */ - -static void -switch_routes(struct babel_route *old, struct babel_route *new) -{ -    int rc; - -    if(!old) { -        install_route(new); -        return; -    } - -    if(!old->installed) -        return; - -    if(!route_feasible(new)) -        zlog_err("WARNING: switching to unfeasible route " -                 "(this shouldn't happen)."); - -    rc = kernel_route(ROUTE_MODIFY, old->src->prefix, old->src->plen, -                      old->nexthop, old->neigh->ifp->ifindex, -                      metric_to_kernel(route_metric(old)), -                      new->nexthop, new->neigh->ifp->ifindex, -                      metric_to_kernel(route_metric(new))); -    if(rc < 0) { -        zlog_err("kernel_route(MODIFY): %s", safe_strerror(errno)); -        return; -    } - -    old->installed = 0; -    new->installed = 1; -    move_installed_route(new, find_route_slot(new->src->prefix, new->src->plen, -                                              NULL)); -} - -static void -change_route_metric(struct babel_route *route, -                    unsigned refmetric, unsigned cost, unsigned add) -{ -    int old, new; -    int newmetric = MIN(refmetric + cost + add, INFINITY); - -    old = metric_to_kernel(route_metric(route)); -    new = metric_to_kernel(newmetric); - -    if(route->installed && old != new) { -        int rc; -        rc = kernel_route(ROUTE_MODIFY, route->src->prefix, route->src->plen, -                          route->nexthop, route->neigh->ifp->ifindex, -                          old, -                          route->nexthop, route->neigh->ifp->ifindex, -                          new); -        if(rc < 0) { -            zlog_err("kernel_route(MODIFY metric): %s", safe_strerror(errno)); -            return; -        } -    } - -    route->refmetric = refmetric; -    route->cost = cost; -    route->add_metric = add; -} - -static void -retract_route(struct babel_route *route) -{ -    change_route_metric(route, INFINITY, INFINITY, 0); -} - -int -route_feasible(struct babel_route *route) -{ -    return update_feasible(route->src, route->seqno, route->refmetric); -} - -int -route_old(struct babel_route *route) -{ -    return route->time < babel_now.tv_sec - route->hold_time * 7 / 8; -} - -int -route_expired(struct babel_route *route) -{ -    return route->time < babel_now.tv_sec - route->hold_time; -} - -static int -channels_interfere(int ch1, int ch2) -{ -    if(ch1 == BABEL_IF_CHANNEL_NONINTERFERING -       || ch2 == BABEL_IF_CHANNEL_NONINTERFERING) -        return 0; -    if(ch1 == BABEL_IF_CHANNEL_INTERFERING -       || ch2 == BABEL_IF_CHANNEL_INTERFERING) -        return 1; -    return ch1 == ch2; -} - -int -route_interferes(struct babel_route *route, struct interface *ifp) -{ -    struct babel_interface *babel_ifp = NULL; -    switch(diversity_kind) { -    case DIVERSITY_NONE: -        return 1; -    case DIVERSITY_INTERFACE_1: -        return route->neigh->ifp == ifp; -    case DIVERSITY_CHANNEL_1: -    case DIVERSITY_CHANNEL: -        if(route->neigh->ifp == ifp) -            return 1; -        babel_ifp = babel_get_if_nfo(ifp); -        if(channels_interfere(babel_ifp->channel, -                              babel_get_if_nfo(route->neigh->ifp)->channel)) -            return 1; -        if(diversity_kind == DIVERSITY_CHANNEL) { -            int i; -            for(i = 0; i < DIVERSITY_HOPS; i++) { -                if(route->channels[i] == 0) -                    break; -                if(channels_interfere(babel_ifp->channel, route->channels[i])) -                    return 1; -            } -        } -        return 0; -    default: -        fprintf(stderr, "Unknown kind of diversity.\n"); -        return 1; -    } -} - -int -update_feasible(struct source *src, -                unsigned short seqno, unsigned short refmetric) -{ -    if(src == NULL) -        return 1; - -    if(src->time < babel_now.tv_sec - SOURCE_GC_TIME) -        /* Never mind what is probably stale data */ -        return 1; - -    if(refmetric >= INFINITY) -        /* Retractions are always feasible */ -        return 1; - -    return (seqno_compare(seqno, src->seqno) > 0 || -            (src->seqno == seqno && refmetric < src->metric)); -} - -/* This returns the feasible route with the smallest metric. */ -struct babel_route * -find_best_route(const unsigned char *prefix, unsigned char plen, int feasible, -                struct neighbour *exclude) -{ -    struct babel_route *route = NULL, *r = NULL; -    int i = find_route_slot(prefix, plen, NULL); - -    if(i < 0) -        return NULL; - -    route = routes[i]; - -    r = route->next; -    while(r) { -        if(!route_expired(r) && -           (!feasible || route_feasible(r)) && -           (!exclude || r->neigh != exclude) && -           (route_metric(r) < route_metric(route))) -            route = r; -        r = r->next; -    } -    return route; -} - -void -update_route_metric(struct babel_route *route) -{ -    int oldmetric = route_metric(route); - -    if(route_expired(route)) { -        if(route->refmetric < INFINITY) { -            route->seqno = seqno_plus(route->src->seqno, 1); -            retract_route(route); -            if(oldmetric < INFINITY) -                route_changed(route, route->src, oldmetric); -        } -    } else { -        struct neighbour *neigh = route->neigh; -        int add_metric = input_filter(route->src->id, -                                      route->src->prefix, route->src->plen, -                                      neigh->address, -                                      neigh->ifp->ifindex); -        change_route_metric(route, route->refmetric, -                            neighbour_cost(route->neigh), add_metric); -        if(route_metric(route) != oldmetric) -            route_changed(route, route->src, oldmetric); -    } -} - -/* Called whenever a neighbour's cost changes, to update the metric of -   all routes through that neighbour.  Calls local_notify_neighbour. */ -void -update_neighbour_metric(struct neighbour *neigh, int changed) -{ - -    if(changed) { -        int i; - -        for(i = 0; i < route_slots; i++) { -            struct babel_route *r = routes[i]; -            while(r) { -                if(r->neigh == neigh) -                    update_route_metric(r); -                r = r->next; -            } -        } -    } -} - -void -update_interface_metric(struct interface *ifp) -{ -    int i; - -    for(i = 0; i < route_slots; i++) { -        struct babel_route *r = routes[i]; -        while(r) { -            if(r->neigh->ifp == ifp) -                update_route_metric(r); -            r = r->next; -        } -    } -} - -/* This is called whenever we receive an update. */ -struct babel_route * -update_route(const unsigned char *router_id, -             const unsigned char *prefix, unsigned char plen, -             unsigned short seqno, unsigned short refmetric, -             unsigned short interval, -             struct neighbour *neigh, const unsigned char *nexthop, -             const unsigned char *channels, int channels_len) -{ -    struct babel_route *route; -    struct source *src; -    int metric, feasible; -    int add_metric; -    int hold_time = MAX((4 * interval) / 100 + interval / 50, 15); - -    if(memcmp(router_id, myid, 8) == 0) -        return NULL; - -    if(martian_prefix(prefix, plen)) { -        zlog_err("Rejecting martian route to %s through %s.", -                 format_prefix(prefix, plen), format_address(router_id)); -        return NULL; -    } - -    add_metric = input_filter(router_id, prefix, plen, -                              neigh->address, neigh->ifp->ifindex); -    if(add_metric >= INFINITY) -        return NULL; - -    route = find_route(prefix, plen, neigh, nexthop); - -    if(route && memcmp(route->src->id, router_id, 8) == 0) -        /* Avoid scanning the source table. */ -        src = route->src; -    else -        src = find_source(router_id, prefix, plen, 1, seqno); - -    if(src == NULL) -        return NULL; - -    feasible = update_feasible(src, seqno, refmetric); -    metric = MIN((int)refmetric + neighbour_cost(neigh) + add_metric, INFINITY); - -    if(route) { -        struct source *oldsrc; -        unsigned short oldmetric; -        int lost = 0; - -        oldsrc = route->src; -        oldmetric = route_metric(route); - -        /* If a successor switches sources, we must accept his update even -           if it makes a route unfeasible in order to break any routing loops -           in a timely manner.  If the source remains the same, we ignore -           the update. */ -        if(!feasible && route->installed) { -            debugf(BABEL_DEBUG_COMMON,"Unfeasible update for installed route to %s " -                   "(%s %d %d -> %s %d %d).", -                   format_prefix(src->prefix, src->plen), -                   format_address(route->src->id), -                   route->seqno, route->refmetric, -                   format_address(src->id), seqno, refmetric); -            if(src != route->src) { -                uninstall_route(route); -                lost = 1; -            } -        } - -        route->src = retain_source(src); -        if((feasible || keep_unfeasible) && refmetric < INFINITY) -            route->time = babel_now.tv_sec; -        route->seqno = seqno; -        change_route_metric(route, -                            refmetric, neighbour_cost(neigh), add_metric); -        route->hold_time = hold_time; - -        route_changed(route, oldsrc, oldmetric); -        if(lost) -            route_lost(oldsrc, oldmetric); - -        if(!feasible) -            send_unfeasible_request(neigh, route->installed && route_old(route), -                                    seqno, metric, src); -        release_source(oldsrc); -    } else { -        struct babel_route *new_route; - -        if(refmetric >= INFINITY) -            /* Somebody's retracting a route we never saw. */ -            return NULL; -        if(!feasible) { -            send_unfeasible_request(neigh, 0, seqno, metric, src); -            if(!keep_unfeasible) -                return NULL; -        } - -        route = malloc(sizeof(struct babel_route)); -        if(route == NULL) { -            perror("malloc(route)"); -            return NULL; -        } - -        route->src = retain_source(src); -        route->refmetric = refmetric; -        route->cost = neighbour_cost(neigh); -        route->add_metric = add_metric; -        route->seqno = seqno; -        route->neigh = neigh; -        memcpy(route->nexthop, nexthop, 16); -        route->time = babel_now.tv_sec; -        route->hold_time = hold_time; -        route->installed = 0; -        memset(&route->channels, 0, sizeof(route->channels)); -        if(channels_len > 0) -            memcpy(&route->channels, channels, -                   MIN(channels_len, DIVERSITY_HOPS)); -        route->next = NULL; -        new_route = insert_route(route); -        if(new_route == NULL) { -            fprintf(stderr, "Couldn't insert route.\n"); -            free(route); -            return NULL; -        } -        consider_route(route); -    } -    return route; -} - -/* We just received an unfeasible update.  If it's any good, send -   a request for a new seqno. */ -void -send_unfeasible_request(struct neighbour *neigh, int force, -                        unsigned short seqno, unsigned short metric, -                        struct source *src) -{ -    struct babel_route *route = find_installed_route(src->prefix, src->plen); - -    if(seqno_minus(src->seqno, seqno) > 100) { -        /* Probably a source that lost its seqno.  Let it time-out. */ -        return; -    } - -    if(force || !route || route_metric(route) >= metric + 512) { -        send_unicast_multihop_request(neigh, src->prefix, src->plen, -                                      src->metric >= INFINITY ? -                                      src->seqno : -                                      seqno_plus(src->seqno, 1), -                                      src->id, 127); -    } -} - -/* This takes a feasible route and decides whether to install it. */ -static void -consider_route(struct babel_route *route) -{ -    struct babel_route *installed; -    struct xroute *xroute; - -    if(route->installed) -        return; - -    if(!route_feasible(route)) -        return; - -    xroute = find_xroute(route->src->prefix, route->src->plen); -    if(xroute && (allow_duplicates < 0 || xroute->metric >= allow_duplicates)) -        return; - -    installed = find_installed_route(route->src->prefix, route->src->plen); - -    if(installed == NULL) -        goto install; - -    if(route_metric(route) >= INFINITY) -        return; - -    if(route_metric(installed) >= INFINITY) -        goto install; - -    if(route_metric(installed) >= route_metric(route) + 64) -        goto install; - -    return; - - install: -    switch_routes(installed, route); -    if(installed && route->installed) -        send_triggered_update(route, installed->src, route_metric(installed)); -    else -        send_update(NULL, 1, route->src->prefix, route->src->plen); -    return; -} - -void -retract_neighbour_routes(struct neighbour *neigh) -{ -    int i; - -    for(i = 0; i < route_slots; i++) { -        struct babel_route *r = routes[i]; -        while(r) { -            if(r->neigh == neigh) { -                if(r->refmetric != INFINITY) { -                    unsigned short oldmetric = route_metric(r); -                    retract_route(r); -                    if(oldmetric != INFINITY) -                        route_changed(r, r->src, oldmetric); -                } -            } -            r = r->next; -        } -        i++; -    } -} - -void -send_triggered_update(struct babel_route *route, struct source *oldsrc, -                      unsigned oldmetric) -{ -    unsigned newmetric, diff; -    /* 1 means send speedily, 2 means resend */ -    int urgent; - -    if(!route->installed) -        return; - -    newmetric = route_metric(route); -    diff = -        newmetric >= oldmetric ? newmetric - oldmetric : oldmetric - newmetric; - -    if(route->src != oldsrc || (oldmetric < INFINITY && newmetric >= INFINITY)) -        /* Switching sources can cause transient routing loops. -           Retractions can cause blackholes. */ -        urgent = 2; -    else if(newmetric > oldmetric && oldmetric < 6 * 256 && diff >= 512) -        /* Route getting significantly worse */ -        urgent = 1; -    else if(unsatisfied_request(route->src->prefix, route->src->plen, -                                route->seqno, route->src->id)) -        /* Make sure that requests are satisfied speedily */ -        urgent = 1; -    else if(oldmetric >= INFINITY && newmetric < INFINITY) -        /* New route */ -        urgent = 0; -    else if(newmetric < oldmetric && diff < 1024) -        /* Route getting better.  This may be a transient fluctuation, so -           don't advertise it to avoid making routes unfeasible later on. */ -        return; -    else if(diff < 384) -        /* Don't fret about trivialities */ -        return; -    else -        urgent = 0; - -    if(urgent >= 2) -        send_update_resend(NULL, route->src->prefix, route->src->plen); -    else -        send_update(NULL, urgent, route->src->prefix, route->src->plen); - -    if(oldmetric < INFINITY) { -        if(newmetric >= oldmetric + 512) { -            send_request_resend(NULL, route->src->prefix, route->src->plen, -                                route->src->metric >= INFINITY ? -                                route->src->seqno : -                                seqno_plus(route->src->seqno, 1), -                                route->src->id); -        } else if(newmetric >= oldmetric + 288) { -            send_request(NULL, route->src->prefix, route->src->plen); -        } -    } -} - -/* A route has just changed.  Decide whether to switch to a different route or -   send an update. */ -void -route_changed(struct babel_route *route, -              struct source *oldsrc, unsigned short oldmetric) -{ -    if(route->installed) { -        if(route_metric(route) > oldmetric) { -            struct babel_route *better_route; -            better_route = -                find_best_route(route->src->prefix, route->src->plen, 1, NULL); -            if(better_route && -               route_metric(better_route) <= route_metric(route) - 96) -                consider_route(better_route); -        } - -        if(route->installed) -            /* We didn't change routes after all. */ -            send_triggered_update(route, oldsrc, oldmetric); -    } else { -        /* Reconsider routes even when their metric didn't decrease, -           they may not have been feasible before. */ -        consider_route(route); -    } -} - -/* We just lost the installed route to a given destination. */ -void -route_lost(struct source *src, unsigned oldmetric) -{ -    struct babel_route *new_route; -    new_route = find_best_route(src->prefix, src->plen, 1, NULL); -    if(new_route) { -        consider_route(new_route); -    } else if(oldmetric < INFINITY) { -        /* Complain loudly. */ -        send_update_resend(NULL, src->prefix, src->plen); -        send_request_resend(NULL, src->prefix, src->plen, -                            src->metric >= INFINITY ? -                            src->seqno : seqno_plus(src->seqno, 1), -                            src->id); -    } -} - -/* This is called periodically to flush old routes.  It will also send -   requests for routes that are about to expire. */ -void -expire_routes(void) -{ -    struct babel_route *r; -    int i; - -    debugf(BABEL_DEBUG_COMMON,"Expiring old routes."); - -    i = 0; -    while(i < route_slots) { -        r = routes[i]; -        while(r) { -            /* Protect against clock being stepped. */ -            if(r->time > babel_now.tv_sec || route_old(r)) { -                flush_route(r); -                goto again; -            } - -            update_route_metric(r); - -            if(r->installed && r->refmetric < INFINITY) { -                if(route_old(r)) -                    /* Route about to expire, send a request. */ -                    send_unicast_request(r->neigh, -                                         r->src->prefix, r->src->plen); -            } -            r = r->next; -        } -        i++; -    again: -        ; -    } -} diff --git a/babeld/route.h b/babeld/route.h deleted file mode 100644 index b6d2d29466..0000000000 --- a/babeld/route.h +++ /dev/null @@ -1,135 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef BABEL_ROUTE_H -#define BABEL_ROUTE_H - -#include "babel_interface.h" -#include "source.h" - -#define DIVERSITY_NONE 0 -#define DIVERSITY_INTERFACE_1 1 -#define DIVERSITY_CHANNEL_1 2 -#define DIVERSITY_CHANNEL 3 - -#define DIVERSITY_HOPS 8 - -struct babel_route { -    struct source *src; -    unsigned short refmetric; -    unsigned short cost; -    unsigned short add_metric; -    unsigned short seqno; -    struct neighbour *neigh; -    unsigned char nexthop[16]; -    time_t time; -    unsigned short hold_time;    /* in seconds */ -    short installed; -    unsigned char channels[DIVERSITY_HOPS]; -    struct babel_route *next; -}; - -extern struct babel_route **routes; -extern int kernel_metric, allow_duplicates; -extern int diversity_kind, diversity_factor; -extern int keep_unfeasible; - -static inline int -route_metric(const struct babel_route *route) -{ -    int m = (int)route->refmetric + route->cost + route->add_metric; -    return MIN(m, INFINITY); -} - -static inline int -route_metric_noninterfering(const struct babel_route *route) -{ -    int m = -        (int)route->refmetric + -        (diversity_factor * route->cost + 128) / 256 + -        route->add_metric; -    m = MAX(m, route->refmetric + 1); -    return MIN(m, INFINITY); -} - -struct babel_route *find_route(const unsigned char *prefix, unsigned char plen, -                         struct neighbour *neigh, const unsigned char *nexthop); -struct babel_route *find_installed_route(const unsigned char *prefix, -                                   unsigned char plen); -int installed_routes_estimate(void); -void flush_route(struct babel_route *route); -void flush_all_routes(void); -void flush_neighbour_routes(struct neighbour *neigh); -void flush_interface_routes(struct interface *ifp, int v4only); -void for_all_routes(void (*f)(struct babel_route*, void*), void *closure); -void for_all_installed_routes(void (*f)(struct babel_route*, void*), void *closure); -void install_route(struct babel_route *route); -void uninstall_route(struct babel_route *route); -void switch_route(struct babel_route *old, struct babel_route *new); -int route_feasible(struct babel_route *route); -int route_old(struct babel_route *route); -int route_expired(struct babel_route *route); -int route_interferes(struct babel_route *route, struct interface *ifp); -int update_feasible(struct source *src, -                    unsigned short seqno, unsigned short refmetric); -struct babel_route *find_best_route(const unsigned char *prefix, unsigned char plen, -                              int feasible, struct neighbour *exclude); -struct babel_route *install_best_route(const unsigned char prefix[16], -                                 unsigned char plen); -void update_neighbour_metric(struct neighbour *neigh, int change); -void update_interface_metric(struct interface *ifp); -void update_route_metric(struct babel_route *route); -struct babel_route *update_route(const unsigned char *id, -                           const unsigned char *prefix, unsigned char plen, -                           unsigned short seqno, unsigned short refmetric, -                           unsigned short interval, struct neighbour *neigh, -                           const unsigned char *nexthop, -                           const unsigned char *channels, int channels_len); -void retract_neighbour_routes(struct neighbour *neigh); -void send_unfeasible_request(struct neighbour *neigh, int force, -                             unsigned short seqno, unsigned short metric, -                             struct source *src); -void send_triggered_update(struct babel_route *route, -                           struct source *oldsrc, unsigned oldmetric); -void route_changed(struct babel_route *route, -                   struct source *oldsrc, unsigned short oldmetric); -void route_lost(struct source *src, unsigned oldmetric); -void expire_routes(void); - -#endif diff --git a/babeld/source.c b/babeld/source.c deleted file mode 100644 index 772112d4d3..0000000000 --- a/babeld/source.c +++ /dev/null @@ -1,180 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/time.h> - -#include "babel_main.h" -#include "babeld.h" -#include "util.h" -#include "source.h" -#include "babel_interface.h" -#include "route.h" - -struct source *srcs = NULL; - -struct source* -find_source(const unsigned char *id, const unsigned char *p, unsigned char plen, -            int create, unsigned short seqno) -{ -    struct source *src; - -    for(src = srcs; src; src = src->next) { -        /* This should really be a hash table.  For now, check the -           last byte first. */ -        if(src->id[7] != id[7]) -            continue; -        if(memcmp(src->id, id, 8) != 0) -            continue; -        if(src->plen != plen) -            continue; -        if(memcmp(src->prefix, p, 16) == 0) -            return src; -    } - -    if(!create) -        return NULL; - -    src = malloc(sizeof(struct source)); -    if(src == NULL) { -        zlog_err("malloc(source): %s", safe_strerror(errno)); -        return NULL; -    } - -    memcpy(src->id, id, 8); -    memcpy(src->prefix, p, 16); -    src->plen = plen; -    src->seqno = seqno; -    src->metric = INFINITY; -    src->time = babel_now.tv_sec; -    src->route_count = 0; -    src->next = srcs; -    srcs = src; -    return src; -} - -struct source * -retain_source(struct source *src) -{ -    assert(src->route_count < 0xffff); -    src->route_count++; -    return src; -} - -void -release_source(struct source *src) -{ -    assert(src->route_count > 0); -    src->route_count--; -} - -int -flush_source(struct source *src) -{ -    if(src->route_count > 0) -        /* The source is in use by a route. */ -        return 0; - -    if(srcs == src) { -        srcs = src->next; -    } else { -        struct source *previous = srcs; -        while(previous->next != src) -            previous = previous->next; -        previous->next = src->next; -    } - -    free(src); -    return 1; -} - -void -update_source(struct source *src, -              unsigned short seqno, unsigned short metric) -{ -    if(metric >= INFINITY) -        return; - -    /* If a source is expired, pretend that it doesn't exist and update -       it unconditionally.  This makes ensures that old data will -       eventually be overridden, and prevents us from getting stuck if -       a router loses its sequence number. */ -    if(src->time < babel_now.tv_sec - SOURCE_GC_TIME || -       seqno_compare(src->seqno, seqno) < 0 || -       (src->seqno == seqno && src->metric > metric)) { -        src->seqno = seqno; -        src->metric = metric; -    } -    src->time = babel_now.tv_sec; -} - -void -expire_sources() -{ -    struct source *src; - -    src = srcs; -    while(src) { -        if(src->time > babel_now.tv_sec) -            /* clock stepped */ -            src->time = babel_now.tv_sec; -        if(src->time < babel_now.tv_sec - SOURCE_GC_TIME) { -            struct source *old = src; -            src = src->next; -            flush_source(old); -            continue; -        } -        src = src->next; -    } -} - -void -check_sources_released(void) -{ -    struct source *src; - -    for(src = srcs; src; src = src->next) { -        if(src->route_count != 0) -            fprintf(stderr, "Warning: source %s %s has refcount %d.\n", -                    format_eui64(src->id), -                    format_prefix(src->prefix, src->plen), -                    (int)src->route_count); -    } -} diff --git a/babeld/source.h b/babeld/source.h deleted file mode 100644 index 62a7e1eea3..0000000000 --- a/babeld/source.h +++ /dev/null @@ -1,67 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef BABEL_SOURCE_H -#define BABEL_SOURCE_H - -#define SOURCE_GC_TIME 200 - -struct source { -    struct source *next; -    unsigned char id[8]; -    unsigned char prefix[16]; -    unsigned char plen; -    unsigned short seqno; -    unsigned short metric; -    unsigned short route_count; -    time_t time; -}; - -struct source *find_source(const unsigned char *id, -                           const unsigned char *p, -                           unsigned char plen, -                           int create, unsigned short seqno); -struct source *retain_source(struct source *src); -void release_source(struct source *src); -int flush_source(struct source *src); -void update_source(struct source *src, -                   unsigned short seqno, unsigned short metric); -void expire_sources(void); -void check_sources_released(void); - -#endif diff --git a/babeld/util.c b/babeld/util.c deleted file mode 100644 index 011f3824eb..0000000000 --- a/babeld/util.c +++ /dev/null @@ -1,445 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <sys/time.h> -#include <time.h> -#include <stdio.h> -#include <unistd.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include "babel_main.h" -#include "babeld.h" -#include "util.h" - -unsigned -roughly(unsigned value) -{ -    return value * 3 / 4 + random() % (value / 2); -} - -/* d = s1 - s2 */ -void -timeval_minus(struct timeval *d, -              const struct timeval *s1, const struct timeval *s2) -{ -    if(s1->tv_usec >= s2->tv_usec) { -        d->tv_usec = s1->tv_usec - s2->tv_usec; -        d->tv_sec = s1->tv_sec - s2->tv_sec; -    } else { -        d->tv_usec = s1->tv_usec + 1000000 - s2->tv_usec; -        d->tv_sec = s1->tv_sec - s2->tv_sec - 1; -    } -} - -unsigned -timeval_minus_msec(const struct timeval *s1, const struct timeval *s2) -{ -    if(s1->tv_sec < s2->tv_sec) -        return 0; - -    /* Avoid overflow. */ -    if(s1->tv_sec - s2->tv_sec > 2000000) -        return 2000000000; - -    if(s1->tv_sec > s2->tv_sec) -        return -            (unsigned)((unsigned)(s1->tv_sec - s2->tv_sec) * 1000 + -                       ((int)s1->tv_usec - s2->tv_usec) / 1000); - -    if(s1->tv_usec <= s2->tv_usec) -        return 0; - -    return (unsigned)(s1->tv_usec - s2->tv_usec) / 1000u; -} - -/* d = s + msecs */ -void -timeval_add_msec(struct timeval *d, const struct timeval *s, const int msecs) -{ -    int usecs; -    d->tv_sec = s->tv_sec + msecs / 1000; -    usecs = s->tv_usec + (msecs % 1000) * 1000; -    if(usecs < 1000000) { -        d->tv_usec = usecs; -    } else { -        d->tv_usec = usecs - 1000000; -        d->tv_sec++; -    } -} - -void -set_timeout(struct timeval *timeout, int msecs) -{ -    timeval_add_msec(timeout, &babel_now, roughly(msecs)); -} - -/* returns <0 if "s1" < "s2", etc. */ -int -timeval_compare(const struct timeval *s1, const struct timeval *s2) -{ -    if(s1->tv_sec < s2->tv_sec) -        return -1; -    else if(s1->tv_sec > s2->tv_sec) -        return 1; -    else if(s1->tv_usec < s2->tv_usec) -        return -1; -    else if(s1->tv_usec > s2->tv_usec) -        return 1; -    else -        return 0; -} - -/* set d at min(d, s) */ -/* {0, 0} represents infinity */ -void -timeval_min(struct timeval *d, const struct timeval *s) -{ -    if(s->tv_sec == 0) -        return; - -    if(d->tv_sec == 0 || timeval_compare(d, s) > 0) { -        *d = *s; -    } -} - -/* set d to min(d, x) with x in [secs, secs+1] */ -void -timeval_min_sec(struct timeval *d, time_t secs) -{ -    if(d->tv_sec == 0 || d->tv_sec > secs) { -        d->tv_sec = secs; -        d->tv_usec = random() % 1000000; -    } -} - -/* parse a float value in second and return the corresponding mili-seconds. - For example: - parse_msec("12.342345") returns 12342 */ -int -parse_msec(const char *string) -{ -    unsigned int in, fl; -    int i, j; - -    in = fl = 0; -    i = 0; -    while(string[i] == ' ' || string[i] == '\t') -        i++; -    while(string[i] >= '0' && string[i] <= '9') { -        in = in * 10 + string[i] - '0'; -        i++; -    } -    if(string[i] == '.') { -        i++; -        j = 0; -        while(string[i] >= '0' && string[i] <= '9') { -            fl = fl * 10 + string[i] - '0'; -            i++; -            j++; -        } - -        while(j > 3) { -            fl /= 10; -            j--; -        } -        while(j < 3) { -            fl *= 10; -            j++; -        } -    } - -    while(string[i] == ' ' || string[i] == '\t') -        i++; - -    if(string[i] == '\0') -        return in * 1000 + fl; - -    return -1; -} - -int -in_prefix(const unsigned char *restrict address, -          const unsigned char *restrict prefix, unsigned char plen) -{ -    unsigned char m; - -    if(plen > 128) -        plen = 128; - -    if(memcmp(address, prefix, plen / 8) != 0) -        return 0; - -    if(plen % 8 == 0) -        return 1; - -    m = 0xFF << (8 - (plen % 8)); - -    return ((address[plen / 8] & m) == (prefix[plen / 8] & m)); -} - -unsigned char * -mask_prefix(unsigned char *restrict ret, -            const unsigned char *restrict prefix, unsigned char plen) -{ -    if(plen >= 128) { -        memcpy(ret, prefix, 16); -        return ret; -    } - -    memset(ret, 0, 16); -    memcpy(ret, prefix, plen / 8); -    if(plen % 8 != 0) -        ret[plen / 8] = -            (prefix[plen / 8] & ((0xFF << (8 - (plen % 8))) & 0xFF)); -    return ret; -} - -static const unsigned char v4prefix[16] = -    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }; - -static const unsigned char llprefix[16] = -    {0xFE, 0x80}; - -const char * -format_address(const unsigned char *address) -{ -    static char buf[4][INET6_ADDRSTRLEN]; -    static int i = 0; -    i = (i + 1) % 4; -    if(v4mapped(address)) -       inet_ntop(AF_INET, address + 12, buf[i], INET6_ADDRSTRLEN); -    else -       inet_ntop(AF_INET6, address, buf[i], INET6_ADDRSTRLEN); -    return buf[i]; -} - -const char * -format_prefix(const unsigned char *prefix, unsigned char plen) -{ -    static char buf[4][INET6_ADDRSTRLEN + 4]; -    static int i = 0; -    int n; -    i = (i + 1) % 4; -    if(plen >= 96 && v4mapped(prefix)) { -        inet_ntop(AF_INET, prefix + 12, buf[i], INET6_ADDRSTRLEN); -        n = strlen(buf[i]); -        snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen - 96); -    } else { -        inet_ntop(AF_INET6, prefix, buf[i], INET6_ADDRSTRLEN); -        n = strlen(buf[i]); -        snprintf(buf[i] + n, INET6_ADDRSTRLEN + 4 - n, "/%d", plen); -    } -    return buf[i]; -} - -const char * -format_eui64(const unsigned char *eui) -{ -    static char buf[4][28]; -    static int i = 0; -    i = (i + 1) % 4; -    snprintf(buf[i], 28, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", -             eui[0], eui[1], eui[2], eui[3], -             eui[4], eui[5], eui[6], eui[7]); -    return buf[i]; -} - -const char *format_bool(const int b) { -    return b ? "true" : "false"; -} - -int -parse_address(const char *address, unsigned char *addr_r, int *af_r) -{ -    struct in_addr ina; -    struct in6_addr ina6; -    int rc; - -    rc = inet_pton(AF_INET, address, &ina); -    if(rc > 0) { -        memcpy(addr_r, v4prefix, 12); -        memcpy(addr_r + 12, &ina, 4); -        if(af_r) *af_r = AF_INET; -        return 0; -    } - -    rc = inet_pton(AF_INET6, address, &ina6); -    if(rc > 0) { -        memcpy(addr_r, &ina6, 16); -        if(af_r) *af_r = AF_INET6; -        return 0; -    } - -    return -1; -} - -int -parse_eui64(const char *eui, unsigned char *eui_r) -{ -    int n; -    n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", -               &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3], -               &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]); -    if(n == 8) -        return 0; - -    n = sscanf(eui, "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx", -               &eui_r[0], &eui_r[1], &eui_r[2], &eui_r[3], -               &eui_r[4], &eui_r[5], &eui_r[6], &eui_r[7]); -    if(n == 8) -        return 0; - -    n = sscanf(eui, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", -               &eui_r[0], &eui_r[1], &eui_r[2], -               &eui_r[5], &eui_r[6], &eui_r[7]); -    if(n == 6) { -        eui_r[3] = 0xFF; -        eui_r[4] = 0xFE; -        return 0; -    } -    return -1; -} - -int -wait_for_fd(int direction, int fd, int msecs) -{ -    fd_set fds; -    int rc; -    struct timeval tv; - -    tv.tv_sec = msecs / 1000; -    tv.tv_usec = (msecs % 1000) * 1000; - -    FD_ZERO(&fds); -    FD_SET(fd, &fds); -    if(direction) -        rc = select(fd + 1, NULL, &fds, NULL, &tv); -    else -        rc = select(fd + 1, &fds, NULL, NULL, &tv); - -    return rc; -} - -int -martian_prefix(const unsigned char *prefix, int plen) -{ -    return -        (plen >= 8 && prefix[0] == 0xFF) || -        (plen >= 10 && prefix[0] == 0xFE && (prefix[1] & 0xC0) == 0x80) || -        (plen >= 128 && memcmp(prefix, zeroes, 15) == 0 && -         (prefix[15] == 0 || prefix[15] == 1)) || -        (plen >= 96 && v4mapped(prefix) && -         ((plen >= 104 && (prefix[12] == 127 || prefix[12] == 0)) || -          (plen >= 100 && (prefix[12] & 0xE0) == 0xE0))); -} - -int -linklocal(const unsigned char *address) -{ -    return memcmp(address, llprefix, 8) == 0; -} - -int -v4mapped(const unsigned char *address) -{ -    return memcmp(address, v4prefix, 12) == 0; -} - -void -v4tov6(unsigned char *dst, const unsigned char *src) -{ -    memcpy(dst, v4prefix, 12); -    memcpy(dst + 12, src, 4); -} - -void -inaddr_to_uchar(unsigned char *dest, const struct in_addr *src) -{ -    memcpy(dest, v4prefix, 12); -    memcpy(dest + 12, src, 4); -    assert(v4mapped(dest)); -} - -void -uchar_to_inaddr(struct in_addr *dest, const unsigned char *src) -{ -    assert(v4mapped(src)); -    memcpy(dest, src + 12, 4); -} - -void -in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src) -{ -    memcpy(dest, src, 16); -} - -void -uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src) -{ -    memcpy(dest, src, 16); -} - -int -daemonise() -{ -    int rc; - -    fflush(stdout); -    fflush(stderr); - -    rc = fork(); -    if(rc < 0) -        return -1; - -    if(rc > 0) -        exit(0); - -    rc = setsid(); -    if(rc < 0) -        return -1; - -    return 1; -} diff --git a/babeld/util.h b/babeld/util.h deleted file mode 100644 index 5d9d2f5dab..0000000000 --- a/babeld/util.h +++ /dev/null @@ -1,165 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include "babeld.h" -#include "babel_main.h" -#include "log.h" - -#if defined(i386) || defined(__mc68020__) || defined(__x86_64__) -#define DO_NTOHS(_d, _s) do{ _d = ntohs(*(const unsigned short*)(_s)); }while(0) -#define DO_NTOHL(_d, _s) do{ _d = ntohl(*(const unsigned*)(_s)); } while(0) -#define DO_HTONS(_d, _s) do{ *(unsigned short*)(_d) = htons(_s); } while(0) -#define DO_HTONL(_d, _s) do{ *(unsigned*)(_d) = htonl(_s); } while(0) -/* Some versions of gcc seem to be buggy, and ignore the packed attribute. -   Disable this code until the issue is clarified. */ -/* #elif defined __GNUC__*/ -#elif 0 -struct __us { unsigned short x __attribute__((packed)); }; -#define DO_NTOHS(_d, _s) \ -    do { _d = ntohs(((const struct __us*)(_s))->x); } while(0) -#define DO_HTONS(_d, _s) \ -    do { ((struct __us*)(_d))->x = htons(_s); } while(0) -#else -#define DO_NTOHS(_d, _s) \ -    do { short _dd; \ -         memcpy(&(_dd), (_s), 2); \ -         _d = ntohs(_dd); } while(0) -#define DO_HTONS(_d, _s) \ -    do { unsigned short _dd; \ -         _dd = htons(_s); \ -         memcpy((_d), &(_dd), 2); } while(0) -#endif - -static inline int -seqno_compare(unsigned short s1, unsigned short s2) -{ -    if(s1 == s2) -        return 0; -    else -        return ((s2 - s1) & 0x8000) ? 1 : -1; -} - -static inline short -seqno_minus(unsigned short s1, unsigned short s2) -{ -    return (short)((s1 - s2) & 0xFFFF); -} - -static inline unsigned short -seqno_plus(unsigned short s, int plus) -{ -    return ((s + plus) & 0xFFFF); -} - -unsigned roughly(unsigned value); -void timeval_minus(struct timeval *d, -                   const struct timeval *s1, const struct timeval *s2); -unsigned timeval_minus_msec(const struct timeval *s1, const struct timeval *s2) -    ATTRIBUTE ((pure)); -void timeval_add_msec(struct timeval *d, -                      const struct timeval *s, const int msecs); -void set_timeout (struct timeval *timeout, int msecs); -int timeval_compare(const struct timeval *s1, const struct timeval *s2) -    ATTRIBUTE ((pure)); -void timeval_min(struct timeval *d, const struct timeval *s); -void timeval_min_sec(struct timeval *d, time_t secs); -int parse_msec(const char *string) ATTRIBUTE ((pure)); -int in_prefix(const unsigned char *restrict address, -              const unsigned char *restrict prefix, unsigned char plen) -    ATTRIBUTE ((pure)); -unsigned char *mask_prefix(unsigned char *restrict ret, -                           const unsigned char *restrict prefix, -                           unsigned char plen); -const char *format_address(const unsigned char *address); -const char *format_prefix(const unsigned char *address, unsigned char prefix); -const char *format_eui64(const unsigned char *eui); -const char *format_bool(const int b); -int parse_address(const char *address, unsigned char *addr_r, int *af_r); -int parse_eui64(const char *eui, unsigned char *eui_r); -int wait_for_fd(int direction, int fd, int msecs); -int martian_prefix(const unsigned char *prefix, int plen) ATTRIBUTE ((pure)); -int linklocal(const unsigned char *address) ATTRIBUTE ((pure)); -int v4mapped(const unsigned char *address) ATTRIBUTE ((pure)); -void v4tov6(unsigned char *dst, const unsigned char *src); -void inaddr_to_uchar(unsigned char *dest, const struct in_addr *src); -void uchar_to_inaddr(struct in_addr *dest, const unsigned char *src); -void in6addr_to_uchar(unsigned char *dest, const struct in6_addr *src); -void uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src); -int daemonise(void); - -/* If debugging is disabled, we want to avoid calling format_address -   for every omitted debugging message.  So debug is a macro.  But -   vararg macros are not portable. */ -#if defined NO_DEBUG - -#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -#define debugf(...) do {} while(0) -#elif defined __GNUC__ -#define debugf(_args...) do {} while(0) -#else -static inline void debugf(int level, const char *format, ...) { return; } -#endif - -#else /* NO_DEBUG */ - -/* some levels */ -#define BABEL_DEBUG_COMMON      (1 << 0) -#define BABEL_DEBUG_KERNEL      (1 << 1) -#define BABEL_DEBUG_FILTER      (1 << 2) -#define BABEL_DEBUG_TIMEOUT     (1 << 3) -#define BABEL_DEBUG_IF          (1 << 4) -#define BABEL_DEBUG_ROUTE       (1 << 5) -#define BABEL_DEBUG_ALL         (0xFFFF) - -#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -#define debugf(level, ...) \ -do { \ -if(UNLIKELY(debug & level)) zlog_debug(__VA_ARGS__);     \ -} while(0) -#elif defined __GNUC__ -#define debugf(level, _args...) \ -do { \ -if(UNLIKELY(debug & level)) zlog_debug(_args);   \ -} while(0) -#else -static inline void debugf(int level, const char *format, ...) { return; } -#endif - -#endif /* NO_DEBUG */ - diff --git a/babeld/xroute.c b/babeld/xroute.c deleted file mode 100644 index 806516718f..0000000000 --- a/babeld/xroute.c +++ /dev/null @@ -1,237 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <zebra.h> -#include "if.h" -#include "log.h" - -#include "babeld.h" -#include "kernel.h" -#include "neighbour.h" -#include "message.h" -#include "route.h" -#include "xroute.h" -#include "util.h" -#include "babel_interface.h" - -static int xroute_add_new_route(unsigned char prefix[16], unsigned char plen, -                                unsigned short metric, unsigned int ifindex, -                                int proto, int send_updates); - -static struct xroute *xroutes; -static int numxroutes = 0, maxxroutes = 0; - -/* Add redistributed route to Babel table. */ -int -babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, -                      unsigned int ifindex, struct in_addr *nexthop) -{ -    unsigned char uchar_prefix[16]; - -    inaddr_to_uchar(uchar_prefix, &prefix->prefix); -    debugf(BABEL_DEBUG_ROUTE, "Adding new ipv4 route comming from Zebra."); -    xroute_add_new_route(uchar_prefix, prefix->prefixlen + 96, -                         api->metric, ifindex, 0, 1); -    return 0; -} - -/* Remove redistributed route from Babel table. */ -int -babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, -                         unsigned int ifindex) -{ -    unsigned char uchar_prefix[16]; -    struct xroute *xroute = NULL; - -    inaddr_to_uchar(uchar_prefix, &prefix->prefix); -    xroute = find_xroute(uchar_prefix, prefix->prefixlen + 96); -    if (xroute != NULL) { -        debugf(BABEL_DEBUG_ROUTE, "Removing ipv4 route (from zebra)."); -        flush_xroute(xroute); -    } -    return 0; -} - -/* Add redistributed route to Babel table. */ -int -babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, -                      unsigned int ifindex, struct in6_addr *nexthop) -{ -    unsigned char uchar_prefix[16]; - -    in6addr_to_uchar(uchar_prefix, &prefix->prefix); -    debugf(BABEL_DEBUG_ROUTE, "Adding new route comming from Zebra."); -    xroute_add_new_route(uchar_prefix, prefix->prefixlen, api->metric, ifindex, -                         0, 1); -    return 0; -} - -/* Remove redistributed route from Babel table. */ -int -babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, -                         unsigned int ifindex) -{ -    unsigned char uchar_prefix[16]; -    struct xroute *xroute = NULL; - -    in6addr_to_uchar(uchar_prefix, &prefix->prefix); -    xroute = find_xroute(uchar_prefix, prefix->prefixlen); -    if (xroute != NULL) { -        debugf(BABEL_DEBUG_ROUTE, "Removing route (from zebra)."); -        flush_xroute(xroute); -    } -    return 0; -} - -struct xroute * -find_xroute(const unsigned char *prefix, unsigned char plen) -{ -    int i; -    for(i = 0; i < numxroutes; i++) { -        if(xroutes[i].plen == plen && -           memcmp(xroutes[i].prefix, prefix, 16) == 0) -            return &xroutes[i]; -    } -    return NULL; -} - -void -flush_xroute(struct xroute *xroute) -{ -    int i; - -    i = xroute - xroutes; -    assert(i >= 0 && i < numxroutes); - -    if(i != numxroutes - 1) -        memcpy(xroutes + i, xroutes + numxroutes - 1, sizeof(struct xroute)); -    numxroutes--; -    VALGRIND_MAKE_MEM_UNDEFINED(xroutes + numxroutes, sizeof(struct xroute)); - -    if(numxroutes == 0) { -        free(xroutes); -        xroutes = NULL; -        maxxroutes = 0; -    } else if(maxxroutes > 8 && numxroutes < maxxroutes / 4) { -        struct xroute *new_xroutes; -        int n = maxxroutes / 2; -        new_xroutes = realloc(xroutes, n * sizeof(struct xroute)); -        if(new_xroutes == NULL) -            return; -        xroutes = new_xroutes; -        maxxroutes = n; -    } -} - -static int -add_xroute(unsigned char prefix[16], unsigned char plen, -           unsigned short metric, unsigned int ifindex, int proto) -{ -    struct xroute *xroute = find_xroute(prefix, plen); -    if(xroute) { -        if(xroute->metric <= metric) -            return 0; -        xroute->metric = metric; -        return 1; -    } - -    if(numxroutes >= maxxroutes) { -        struct xroute *new_xroutes; -        int n = maxxroutes < 1 ? 8 : 2 * maxxroutes; -        new_xroutes = xroutes == NULL ? -            malloc(n * sizeof(struct xroute)) : -            realloc(xroutes, n * sizeof(struct xroute)); -        if(new_xroutes == NULL) -            return -1; -        maxxroutes = n; -        xroutes = new_xroutes; -    } - -    memcpy(xroutes[numxroutes].prefix, prefix, 16); -    xroutes[numxroutes].plen = plen; -    xroutes[numxroutes].metric = metric; -    xroutes[numxroutes].ifindex = ifindex; -    xroutes[numxroutes].proto = proto; -    numxroutes++; -    return 1; -} - -/* Returns an overestimate of the number of xroutes. */ -int -xroutes_estimate() -{ -    return numxroutes; -} - -void -for_all_xroutes(void (*f)(struct xroute*, void*), void *closure) -{ -    int i; - -    for(i = 0; i < numxroutes; i++) -        (*f)(&xroutes[i], closure); -} - -/* add an xroute, verifying some conditions; return 0 if there is no changes */ -static int -xroute_add_new_route(unsigned char prefix[16], unsigned char plen, -                     unsigned short metric, unsigned int ifindex, -                     int proto, int send_updates) -{ -    int rc; -    if(martian_prefix(prefix, plen)) -        return 0; -    metric = redistribute_filter(prefix, plen, ifindex, proto); -    if(metric < INFINITY) { -        rc = add_xroute(prefix, plen, metric, ifindex, proto); -        if(rc > 0) { -            struct babel_route *route; -            route = find_installed_route(prefix, plen); -            if(route) { -                if(allow_duplicates < 0 || -                   metric < allow_duplicates) -                    uninstall_route(route); -            } -            if(send_updates) -                send_update(NULL, 0, prefix, plen); -            return 1; -        } -    } -    return 0; -} diff --git a/babeld/xroute.h b/babeld/xroute.h deleted file mode 100644 index 4d4ab99d03..0000000000 --- a/babeld/xroute.h +++ /dev/null @@ -1,59 +0,0 @@ -/*   - *  This file is free software: you may copy, redistribute 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 file 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.   - *   - *  You should have received a copy of the GNU General Public License   - *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   - *   - * This file incorporates work covered by the following copyright and   - * permission notice:   - *   -Copyright (c) 2007, 2008 by Juliusz Chroboczek -Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -struct xroute { -    unsigned char prefix[16]; -    unsigned char plen; -    unsigned short metric; -    unsigned int ifindex; -    int proto; -}; - -struct xroute *find_xroute(const unsigned char *prefix, unsigned char plen); -void flush_xroute(struct xroute *xroute); -int babel_ipv4_route_add (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, -                          unsigned int ifindex, struct in_addr *nexthop); -int babel_ipv4_route_delete (struct zapi_ipv4 *api, struct prefix_ipv4 *prefix, -                             unsigned int ifindex); -int babel_ipv6_route_add (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, -                          unsigned int ifindex, struct in6_addr *nexthop); -int babel_ipv6_route_delete (struct zapi_ipv6 *api, struct prefix_ipv6 *prefix, -                             unsigned int ifindex); -int xroutes_estimate(void); -void for_all_xroutes(void (*f)(struct xroute*, void*), void *closure);  | 
