Annotation of embedaddon/quagga/babeld/babel_interface.c, revision 1.1.1.1

1.1       misho       1: /*  
                      2:  *  This file is free software: you may copy, redistribute and/or modify it  
                      3:  *  under the terms of the GNU General Public License as published by the  
                      4:  *  Free Software Foundation, either version 2 of the License, or (at your  
                      5:  *  option) any later version.  
                      6:  *  
                      7:  *  This file is distributed in the hope that it will be useful, but  
                      8:  *  WITHOUT ANY WARRANTY; without even the implied warranty of  
                      9:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
                     10:  *  General Public License for more details.  
                     11:  *  
                     12:  *  You should have received a copy of the GNU General Public License  
                     13:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
                     14:  *  
                     15:  * This file incorporates work covered by the following copyright and  
                     16:  * permission notice:  
                     17:  *  
                     18: 
                     19: Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
                     20: 
                     21: Permission is hereby granted, free of charge, to any person obtaining a copy
                     22: of this software and associated documentation files (the "Software"), to deal
                     23: in the Software without restriction, including without limitation the rights
                     24: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     25: copies of the Software, and to permit persons to whom the Software is
                     26: furnished to do so, subject to the following conditions:
                     27: 
                     28: The above copyright notice and this permission notice shall be included in
                     29: all copies or substantial portions of the Software.
                     30: 
                     31: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     32: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     33: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
                     34: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     35: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     36: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     37: THE SOFTWARE.
                     38: */
                     39: 
                     40: #include <zebra.h>
                     41: #include "memory.h"
                     42: #include "log.h"
                     43: #include "command.h"
                     44: #include "prefix.h"
                     45: #include "vector.h"
                     46: #include "distribute.h"
                     47: 
                     48: #include "babel_main.h"
                     49: #include "util.h"
                     50: #include "kernel.h"
                     51: #include "babel_interface.h"
                     52: #include "message.h"
                     53: #include "route.h"
                     54: #include "babel_zebra.h"
                     55: #include "neighbour.h"
                     56: #include "route.h"
                     57: #include "xroute.h"
                     58: 
                     59: 
                     60: #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
                     61: 
                     62: static int babel_enable_if_lookup (const char *ifname);
                     63: static int babel_enable_if_add (const char *ifname);
                     64: static int babel_enable_if_delete (const char *ifname);
                     65: static int interface_recalculate(struct interface *ifp);
                     66: static int interface_reset(struct interface *ifp);
                     67: static int babel_if_new_hook    (struct interface *ifp);
                     68: static int babel_if_delete_hook (struct interface *ifp);
                     69: static int interface_config_write (struct vty *vty);
                     70: static babel_interface_nfo * babel_interface_allocate (void);
                     71: static void babel_interface_free (babel_interface_nfo *bi);
                     72: 
                     73: 
                     74: static vector babel_enable_if;                 /* enable interfaces (by cmd). */
                     75: static struct cmd_node babel_interface_node =  /* babeld's interface node.    */
                     76: {
                     77:     INTERFACE_NODE,
                     78:     "%s(config-if)# ",
                     79:     1 /* VTYSH */
                     80: };
                     81: 
                     82: 
                     83: int
                     84: babel_interface_up (int cmd, struct zclient *client, zebra_size_t length)
                     85: {
                     86:     struct stream *s = NULL;
                     87:     struct interface *ifp = NULL;
                     88: 
                     89:     debugf(BABEL_DEBUG_IF, "receive a 'interface up'");
                     90: 
                     91:     s = zclient->ibuf;
                     92:     ifp = zebra_interface_state_read(s); /* it updates iflist */
                     93: 
                     94:     if (ifp == NULL) {
                     95:         return 0;
                     96:     }
                     97: 
                     98:     interface_recalculate(ifp);
                     99:     return 0;
                    100: }
                    101: 
                    102: int
                    103: babel_interface_down (int cmd, struct zclient *client, zebra_size_t length)
                    104: {
                    105:     struct stream *s = NULL;
                    106:     struct interface *ifp = NULL;
                    107: 
                    108:     debugf(BABEL_DEBUG_IF, "receive a 'interface down'");
                    109: 
                    110:     s = zclient->ibuf;
                    111:     ifp = zebra_interface_state_read(s); /* it updates iflist */
                    112: 
                    113:     if (ifp == NULL) {
                    114:         return 0;
                    115:     }
                    116: 
                    117:     interface_reset(ifp);
                    118:     return 0;
                    119: }
                    120: 
                    121: int
                    122: babel_interface_add (int cmd, struct zclient *client, zebra_size_t length)
                    123: {
                    124:     struct interface *ifp = NULL;
                    125: 
                    126:     debugf(BABEL_DEBUG_IF, "receive a 'interface add'");
                    127: 
                    128:     /* read and add the interface in the iflist. */
                    129:     ifp = zebra_interface_add_read (zclient->ibuf);
                    130: 
                    131:     if (ifp == NULL) {
                    132:         return 0;
                    133:     }
                    134: 
                    135:     interface_recalculate(ifp);
                    136:     return 0;
                    137: }
                    138: 
                    139: int
                    140: babel_interface_delete (int cmd, struct zclient *client, zebra_size_t length)
                    141: {
                    142:     struct interface *ifp;
                    143:     struct stream *s;
                    144: 
                    145:     debugf(BABEL_DEBUG_IF, "receive a 'interface delete'");
                    146: 
                    147:     s = zclient->ibuf;
                    148:     ifp = zebra_interface_state_read(s); /* it updates iflist */
                    149: 
                    150:     if (ifp == NULL)
                    151:         return 0;
                    152: 
                    153:     if (IS_ENABLE(ifp))
                    154:         interface_reset(ifp);
                    155: 
                    156:     /* To support pseudo interface do not free interface structure.  */
                    157:     /* if_delete(ifp); */
                    158:     ifp->ifindex = IFINDEX_INTERNAL;
                    159: 
                    160:     return 0;
                    161: }
                    162: 
                    163: int
                    164: babel_interface_address_add (int cmd, struct zclient *client,
                    165:                              zebra_size_t length)
                    166: {
                    167:     babel_interface_nfo *babel_ifp;
                    168:     struct connected *ifc;
                    169:     struct prefix *prefix;
                    170: 
                    171:     debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
                    172: 
                    173:     ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
                    174:                                         zclient->ibuf);
                    175: 
                    176:     if (ifc == NULL)
                    177:         return 0;
                    178: 
                    179:     prefix = ifc->address;
                    180: 
                    181:     if (prefix->family == AF_INET) {
                    182:         flush_interface_routes(ifc->ifp, 0);
                    183:         babel_ifp = babel_get_if_nfo(ifc->ifp);
                    184:         if (babel_ifp->ipv4 == NULL) {
                    185:             babel_ifp->ipv4 = malloc(4);
                    186:             if (babel_ifp->ipv4 == NULL) {
                    187:                 zlog_err("not einough memory");
                    188:             } else {
                    189:                 memcpy(babel_ifp->ipv4, &prefix->u.prefix4, 4);
                    190:             }
                    191:         }
                    192:     }
                    193: 
                    194:     send_request(ifc->ifp, NULL, 0);
                    195:     send_update(ifc->ifp, 0, NULL, 0);
                    196: 
                    197:     return 0;
                    198: }
                    199: 
                    200: int
                    201: babel_interface_address_delete (int cmd, struct zclient *client,
                    202:                                 zebra_size_t length)
                    203: {
                    204:     babel_interface_nfo *babel_ifp;
                    205:     struct connected *ifc;
                    206:     struct prefix *prefix;
                    207: 
                    208:     debugf(BABEL_DEBUG_IF, "receive a 'interface address add'");
                    209: 
                    210:     ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
                    211:                                         zclient->ibuf);
                    212: 
                    213:     if (ifc == NULL)
                    214:         return 0;
                    215: 
                    216:     prefix = ifc->address;
                    217: 
                    218:     if (prefix->family == AF_INET) {
                    219:         flush_interface_routes(ifc->ifp, 0);
                    220:         babel_ifp = babel_get_if_nfo(ifc->ifp);
                    221:         if (babel_ifp->ipv4 != NULL
                    222:             && memcmp(babel_ifp->ipv4, &prefix->u.prefix4, 4) == 0) {
                    223:             free(babel_ifp->ipv4);
                    224:             babel_ifp->ipv4 = NULL;
                    225:         }
                    226:     }
                    227: 
                    228:     send_request(ifc->ifp, NULL, 0);
                    229:     send_update(ifc->ifp, 0, NULL, 0);
                    230: 
                    231:     return 0;
                    232: }
                    233: 
                    234: /* Lookup function. */
                    235: static int
                    236: babel_enable_if_lookup (const char *ifname)
                    237: {
                    238:     unsigned int i;
                    239:     char *str;
                    240: 
                    241:     for (i = 0; i < vector_active (babel_enable_if); i++)
                    242:         if ((str = vector_slot (babel_enable_if, i)) != NULL)
                    243:             if (strcmp (str, ifname) == 0)
                    244:                 return i;
                    245:     return -1;
                    246: }
                    247: 
                    248: /* Add interface to babel_enable_if. */
                    249: static int
                    250: babel_enable_if_add (const char *ifname)
                    251: {
                    252:     int ret;
                    253:     struct interface *ifp = NULL;
                    254: 
                    255:     ret = babel_enable_if_lookup (ifname);
                    256:     if (ret >= 0)
                    257:         return -1;
                    258: 
                    259:     vector_set (babel_enable_if, strdup (ifname));
                    260: 
                    261:     ifp = if_lookup_by_name(ifname);
                    262:     if (ifp != NULL)
                    263:         interface_recalculate(ifp);
                    264: 
                    265:     return 1;
                    266: }
                    267: 
                    268: /* Delete interface from babel_enable_if. */
                    269: static int
                    270: babel_enable_if_delete (const char *ifname)
                    271: {
                    272:     int babel_enable_if_index;
                    273:     char *str;
                    274:     struct interface *ifp = NULL;
                    275: 
                    276:     babel_enable_if_index = babel_enable_if_lookup (ifname);
                    277:     if (babel_enable_if_index < 0)
                    278:         return -1;
                    279: 
                    280:     str = vector_slot (babel_enable_if, babel_enable_if_index);
                    281:     free (str);
                    282:     vector_unset (babel_enable_if, babel_enable_if_index);
                    283: 
                    284:     ifp = if_lookup_by_name(ifname);
                    285:     if (ifp != NULL)
                    286:         interface_reset(ifp);
                    287: 
                    288:     return 1;
                    289: }
                    290: 
                    291: /* [Babel Command] Babel enable on specified interface or matched network. */
                    292: DEFUN (babel_network,
                    293:        babel_network_cmd,
                    294:        "network IF_OR_ADDR",
                    295:        "Enable Babel protocol on specified interface or network.\n"
                    296:        "Interface or address")
                    297: {
                    298:     int ret;
                    299:     struct prefix p;
                    300: 
                    301:     ret = str2prefix (argv[0], &p);
                    302: 
                    303:     /* Given string is:               */
                    304:     if (ret) /* an IPv4 or v6 network */
                    305:         return CMD_ERR_NO_MATCH; /* not implemented yet */
                    306:     else     /* an interface name     */
                    307:         ret = babel_enable_if_add (argv[0]);
                    308: 
                    309:     if (ret < 0) {
                    310:         vty_out (vty, "There is same network configuration %s%s", argv[0],
                    311:                  VTY_NEWLINE);
                    312:         return CMD_WARNING;
                    313:     }
                    314: 
                    315:     return CMD_SUCCESS;
                    316: }
                    317: 
                    318: /* [Babel Command] Babel enable on specified interface or matched network. */
                    319: DEFUN (no_babel_network,
                    320:        no_babel_network_cmd,
                    321:        "no network IF_OR_ADDR",
                    322:        NO_STR
                    323:        "Disable Babel protocol on specified interface or network.\n"
                    324:        "Interface or address")
                    325: {
                    326:     int ret;
                    327:     struct prefix p;
                    328: 
                    329:     ret = str2prefix (argv[0], &p);
                    330: 
                    331:     /* Given string is:               */
                    332:     if (ret) /* an IPv4 or v6 network */
                    333:         return CMD_ERR_NO_MATCH; /* not implemented yet */
                    334:     else     /* an interface name     */
                    335:         ret = babel_enable_if_delete (argv[0]);
                    336: 
                    337:     if (ret < 0) {
                    338:         vty_out (vty, "can't find network %s%s", argv[0],
                    339:                  VTY_NEWLINE);
                    340:         return CMD_WARNING;
                    341:     }
                    342: 
                    343:     return CMD_SUCCESS;
                    344: }
                    345: 
                    346: /* There are a number of interface parameters that must be changed when
                    347:    an interface becomes wired/wireless.  In Quagga, they cannot be
                    348:    configured separately. */
                    349: 
                    350: static void
                    351: babel_set_wired_internal(babel_interface_nfo *babel_ifp, int wired)
                    352: {
                    353:     if(wired) {
                    354:         babel_ifp->flags |= BABEL_IF_WIRED;
                    355:         babel_ifp->cost = 96;
                    356:         babel_ifp->flags &= ~BABEL_IF_LQ;
                    357:     } else {
                    358:         babel_ifp->flags &= ~BABEL_IF_WIRED;
                    359:         babel_ifp->cost = 256;
                    360:         babel_ifp->flags |= BABEL_IF_LQ;
                    361:     }
                    362: 
                    363: }
                    364: 
                    365: /* [Interface Command] Tell the interface is wire. */
                    366: DEFUN (babel_set_wired,
                    367:        babel_set_wired_cmd,
                    368:        "babel wired",
                    369:        "Babel interface commands\n"
                    370:        "Enable wired optimisations")
                    371: {
                    372:     struct interface *ifp;
                    373:     babel_interface_nfo *babel_ifp;
                    374: 
                    375:     ifp = vty->index;
                    376:     babel_ifp = babel_get_if_nfo(ifp);
                    377: 
                    378:     assert (babel_ifp != NULL);
                    379:     babel_set_wired_internal(babel_ifp, 1);
                    380:     return CMD_SUCCESS;
                    381: }
                    382: 
                    383: /* [Interface Command] Tell the interface is wireless (default). */
                    384: DEFUN (babel_set_wireless,
                    385:        babel_set_wireless_cmd,
                    386:        "babel wireless",
                    387:        "Babel interface commands\n"
                    388:        "Disable wired optimiations (assume wireless)")
                    389: {
                    390:     struct interface *ifp;
                    391:     babel_interface_nfo *babel_ifp;
                    392: 
                    393:     ifp = vty->index;
                    394:     babel_ifp = babel_get_if_nfo(ifp);
                    395: 
                    396:     assert (babel_ifp != NULL);
                    397:     babel_set_wired_internal(babel_ifp, 0);
                    398:     return CMD_SUCCESS;
                    399: }
                    400: 
                    401: /* [Interface Command] Enable split horizon. */
                    402: DEFUN (babel_split_horizon,
                    403:        babel_split_horizon_cmd,
                    404:        "babel split-horizon",
                    405:        "Babel interface commands\n"
                    406:        "Enable split horizon processing")
                    407: {
                    408:     struct interface *ifp;
                    409:     babel_interface_nfo *babel_ifp;
                    410: 
                    411:     ifp = vty->index;
                    412:     babel_ifp = babel_get_if_nfo(ifp);
                    413: 
                    414:     assert (babel_ifp != NULL);
                    415:     babel_ifp->flags |= BABEL_IF_SPLIT_HORIZON;
                    416:     return CMD_SUCCESS;
                    417: }
                    418: 
                    419: /* [Interface Command] Disable split horizon (default). */
                    420: DEFUN (no_babel_split_horizon,
                    421:        no_babel_split_horizon_cmd,
                    422:        "no babel split-horizon",
                    423:        NO_STR
                    424:        "Babel interface commands\n"
                    425:        "Disable split horizon processing")
                    426: {
                    427:     struct interface *ifp;
                    428:     babel_interface_nfo *babel_ifp;
                    429: 
                    430:     ifp = vty->index;
                    431:     babel_ifp = babel_get_if_nfo(ifp);
                    432: 
                    433:     assert (babel_ifp != NULL);
                    434:     babel_ifp->flags &= ~BABEL_IF_SPLIT_HORIZON;
                    435:     return CMD_SUCCESS;
                    436: }
                    437: 
                    438: /* [Interface Command]. */
                    439: DEFUN (babel_set_hello_interval,
                    440:        babel_set_hello_interval_cmd,
                    441:        "babel hello-interval <20-655340>",
                    442:        "Babel interface commands\n"
                    443:        "Time between scheduled hellos\n"
                    444:        "Milliseconds\n")
                    445: {
                    446:     struct interface *ifp;
                    447:     babel_interface_nfo *babel_ifp;
                    448:     int interval;
                    449: 
                    450:     VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
                    451: 
                    452:     ifp = vty->index;
                    453:     babel_ifp = babel_get_if_nfo(ifp);
                    454:     assert (babel_ifp != NULL);
                    455: 
                    456:     babel_ifp->hello_interval = interval;
                    457:     return CMD_SUCCESS;
                    458: }
                    459: 
                    460: /* [Interface Command]. */
                    461: DEFUN (babel_set_update_interval,
                    462:        babel_set_update_interval_cmd,
                    463:        "babel update-interval <20-655340>",
                    464:        "Babel interface commands\n"
                    465:        "Time between scheduled updates\n"
                    466:        "Milliseconds\n")
                    467: {
                    468:     struct interface *ifp;
                    469:     babel_interface_nfo *babel_ifp;
                    470:     int interval;
                    471: 
                    472:     VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
                    473: 
                    474:     ifp = vty->index;
                    475:     babel_ifp = babel_get_if_nfo(ifp);
                    476:     assert (babel_ifp != NULL);
                    477: 
                    478:     babel_ifp->update_interval = interval;
                    479:     return CMD_SUCCESS;
                    480: }
                    481: 
                    482: /* This should be no more than half the hello interval, so that hellos
                    483:    aren't sent late.  The result is in milliseconds. */
                    484: unsigned
                    485: jitter(babel_interface_nfo *babel_ifp, int urgent)
                    486: {
                    487:     unsigned interval = babel_ifp->hello_interval;
                    488:     if(urgent)
                    489:         interval = MIN(interval, 100);
                    490:     else
                    491:         interval = MIN(interval, 4000);
                    492:     return roughly(interval) / 4;
                    493: }
                    494: 
                    495: unsigned
                    496: update_jitter(babel_interface_nfo *babel_ifp, int urgent)
                    497: {
                    498:     unsigned interval = babel_ifp->hello_interval;
                    499:     if(urgent)
                    500:         interval = MIN(interval, 100);
                    501:     else
                    502:         interval = MIN(interval, 4000);
                    503:     return roughly(interval);
                    504: }
                    505: 
                    506: /* calculate babeld's specific datas of an interface (change when the interface
                    507:  change) */
                    508: static int
                    509: interface_recalculate(struct interface *ifp)
                    510: {
                    511:     babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
                    512:     unsigned char *tmp = NULL;
                    513:     int mtu, rc;
                    514:     struct ipv6_mreq mreq;
                    515: 
                    516:     if (!IS_ENABLE(ifp))
                    517:         return -1;
                    518: 
                    519:     if (!if_is_operative(ifp) || !CHECK_FLAG(ifp->flags, IFF_RUNNING)) {
                    520:         interface_reset(ifp);
                    521:         return -1;
                    522:     }
                    523: 
                    524:     babel_ifp->flags |= BABEL_IF_IS_UP;
                    525: 
                    526:     mtu = MIN(ifp->mtu, ifp->mtu6);
                    527: 
                    528:     /* We need to be able to fit at least two messages into a packet,
                    529:      so MTUs below 116 require lower layer fragmentation. */
                    530:     /* In IPv6, the minimum MTU is 1280, and every host must be able
                    531:      to reassemble up to 1500 bytes, but I'd rather not rely on this. */
                    532:     if(mtu < 128) {
                    533:         debugf(BABEL_DEBUG_IF, "Suspiciously low MTU %d on interface %s (%d).",
                    534:                mtu, ifp->name, ifp->ifindex);
                    535:         mtu = 128;
                    536:     }
                    537: 
                    538:     /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
                    539:     babel_ifp->bufsize = mtu - sizeof(packet_header) - 60;
                    540:     tmp = babel_ifp->sendbuf;
                    541:     babel_ifp->sendbuf = realloc(babel_ifp->sendbuf, babel_ifp->bufsize);
                    542:     if(babel_ifp->sendbuf == NULL) {
                    543:         zlog_err("Couldn't reallocate sendbuf.");
                    544:         free(tmp);
                    545:         babel_ifp->bufsize = 0;
                    546:         return -1;
                    547:     }
                    548:     tmp = NULL;
                    549: 
                    550:     resize_receive_buffer(mtu);
                    551: 
                    552:     memset(&mreq, 0, sizeof(mreq));
                    553:     memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
                    554:     mreq.ipv6mr_interface = ifp->ifindex;
                    555: 
                    556:     rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
                    557:                     (char*)&mreq, sizeof(mreq));
                    558:     if(rc < 0) {
                    559:         zlog_err("setsockopt(IPV6_JOIN_GROUP) on interface '%s': %s",
                    560:                  ifp->name, safe_strerror(errno));
                    561:         /* This is probably due to a missing link-local address,
                    562:          so down this interface, and wait until the main loop
                    563:          tries to up it again. */
                    564:         interface_reset(ifp);
                    565:         return -1;
                    566:     }
                    567: 
                    568:     set_timeout(&babel_ifp->hello_timeout, babel_ifp->hello_interval);
                    569:     set_timeout(&babel_ifp->update_timeout, babel_ifp->update_interval);
                    570:     send_hello(ifp);
                    571:     send_request(ifp, NULL, 0);
                    572: 
                    573:     update_interface_metric(ifp);
                    574: 
                    575:     debugf(BABEL_DEBUG_COMMON,
                    576:            "Upped interface %s (%s, cost=%d, channel=%d%s).",
                    577:            ifp->name,
                    578:            (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
                    579:            babel_ifp->cost,
                    580:            babel_ifp->channel,
                    581:            babel_ifp->ipv4 ? ", IPv4" : "");
                    582: 
                    583:     if(rc > 0)
                    584:         send_update(ifp, 0, NULL, 0);
                    585: 
                    586:     return 1;
                    587: }
                    588: 
                    589: /* Reset the interface as it was new: it's not removed from the interface list,
                    590:  and may be considered as a upped interface. */
                    591: static int
                    592: interface_reset(struct interface *ifp)
                    593: {
                    594:     int rc;
                    595:     struct ipv6_mreq mreq;
                    596:     babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
                    597: 
                    598:     if (!(babel_ifp->flags & BABEL_IF_IS_UP))
                    599:         return 0;
                    600: 
                    601:     debugf(BABEL_DEBUG_IF, "interface reset: %s", ifp->name);
                    602:     babel_ifp->flags &= ~BABEL_IF_IS_UP;
                    603: 
                    604:     flush_interface_routes(ifp, 0);
                    605:     babel_ifp->buffered = 0;
                    606:     babel_ifp->bufsize = 0;
                    607:     free(babel_ifp->sendbuf);
                    608:     babel_ifp->num_buffered_updates = 0;
                    609:     babel_ifp->update_bufsize = 0;
                    610:     if(babel_ifp->buffered_updates)
                    611:         free(babel_ifp->buffered_updates);
                    612:     babel_ifp->buffered_updates = NULL;
                    613:     babel_ifp->sendbuf = NULL;
                    614: 
                    615:     if(ifp->ifindex > 0) {
                    616:         memset(&mreq, 0, sizeof(mreq));
                    617:         memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
                    618:         mreq.ipv6mr_interface = ifp->ifindex;
                    619:         rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
                    620:                         (char*)&mreq, sizeof(mreq));
                    621:         if(rc < 0)
                    622:             zlog_err("setsockopt(IPV6_LEAVE_GROUP) on interface '%s': %s",
                    623:                      ifp->name, safe_strerror(errno));
                    624:     }
                    625: 
                    626:     update_interface_metric(ifp);
                    627: 
                    628:     debugf(BABEL_DEBUG_COMMON,"Upped network %s (%s, cost=%d%s).",
                    629:            ifp->name,
                    630:            (babel_ifp->flags & BABEL_IF_WIRED) ? "wired" : "wireless",
                    631:            babel_ifp->cost,
                    632:            babel_ifp->ipv4 ? ", IPv4" : "");
                    633: 
                    634:     return 1;
                    635: }
                    636: 
                    637: /* Send retraction to all, and reset all interfaces statistics. */
                    638: void
                    639: babel_interface_close_all(void)
                    640: {
                    641:     struct interface *ifp = NULL;
                    642:     struct listnode *linklist_node = NULL;
                    643: 
                    644:     FOR_ALL_INTERFACES(ifp, linklist_node) {
                    645:         if(!if_up(ifp))
                    646:             continue;
                    647:         send_wildcard_retraction(ifp);
                    648:         /* Make sure that we expire quickly from our neighbours'
                    649:          association caches. */
                    650:         send_hello_noupdate(ifp, 10);
                    651:         flushbuf(ifp);
                    652:         usleep(roughly(1000));
                    653:         gettime(&babel_now);
                    654:     }
                    655:     FOR_ALL_INTERFACES(ifp, linklist_node) {
                    656:         if(!if_up(ifp))
                    657:             continue;
                    658:         /* Make sure they got it. */
                    659:         send_wildcard_retraction(ifp);
                    660:         send_hello_noupdate(ifp, 1);
                    661:         flushbuf(ifp);
                    662:         usleep(roughly(10000));
                    663:         gettime(&babel_now);
                    664:         interface_reset(ifp);
                    665:     }
                    666: }
                    667: 
                    668: /* return "true" if address is one of our ipv6 addresses */
                    669: int
                    670: is_interface_ll_address(struct interface *ifp, const unsigned char *address)
                    671: {
                    672:     struct connected *connected;
                    673:     struct listnode *node;
                    674: 
                    675:     if(!if_up(ifp))
                    676:         return 0;
                    677: 
                    678:     FOR_ALL_INTERFACES_ADDRESSES(ifp, connected, node) {
                    679:         if(connected->address->family == AF_INET6 &&
                    680:            memcmp(&connected->address->u.prefix6, address, 16) == 0)
                    681:             return 1;
                    682:     }
                    683: 
                    684:     return 0;
                    685: }
                    686: 
                    687: static void
                    688: show_babel_interface_sub (struct vty *vty, struct interface *ifp)
                    689: {
                    690:   int is_up;
                    691:   babel_interface_nfo *babel_ifp;
                    692: 
                    693:   vty_out (vty, "%s is %s%s", ifp->name,
                    694:     ((is_up = if_is_operative(ifp)) ? "up" : "down"), VTY_NEWLINE);
                    695:   vty_out (vty, "  ifindex %u, MTU %u bytes %s%s",
                    696:     ifp->ifindex, ifp->mtu, if_flag_dump(ifp->flags), VTY_NEWLINE);
                    697: 
                    698:   if (babel_enable_if_lookup (ifp->name) < 0)
                    699:   {
                    700:     vty_out (vty, "  Babel protocol is not enabled on this interface%s", VTY_NEWLINE);
                    701:     return;
                    702:   }
                    703:   if (!is_up)
                    704:   {
                    705:     vty_out (vty, "  Babel protocol is enabled, but not running on this interface%s", VTY_NEWLINE);
                    706:     return;
                    707:   }
                    708:   babel_ifp = babel_get_if_nfo (ifp);
                    709:   vty_out (vty, "  Babel protocol is running on this interface%s", VTY_NEWLINE);
                    710:   vty_out (vty, "  Operating mode is \"%s\"%s",
                    711:            CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED) ? "wired" : "wireless", VTY_NEWLINE);
                    712:   vty_out (vty, "  Split horizon mode is %s%s",
                    713:            CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) ? "On" : "Off", VTY_NEWLINE);
                    714:   vty_out (vty, "  Hello interval is %u ms%s", babel_ifp->hello_interval, VTY_NEWLINE);
                    715:   vty_out (vty, "  Update interval is %u ms%s", babel_ifp->update_interval, VTY_NEWLINE);
                    716: }
                    717: 
                    718: DEFUN (show_babel_interface,
                    719:        show_babel_interface_cmd,
                    720:        "show babel interface [INTERFACE]",
                    721:        SHOW_STR
                    722:        IP_STR
                    723:        "Babel information\n"
                    724:        "Interface information\n"
                    725:        "Interface name\n")
                    726: {
                    727:   struct interface *ifp;
                    728:   struct listnode *node;
                    729: 
                    730:   if (argc == 0)
                    731:   {
                    732:     for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                    733:       show_babel_interface_sub (vty, ifp);
                    734:     return CMD_SUCCESS;
                    735:   }
                    736:   if ((ifp = if_lookup_by_name (argv[0])) == NULL)
                    737:   {
                    738:     vty_out (vty, "No such interface name%s", VTY_NEWLINE);
                    739:     return CMD_WARNING;
                    740:   }
                    741:   show_babel_interface_sub (vty, ifp);
                    742:   return CMD_SUCCESS;
                    743: }
                    744: 
                    745: static void
                    746: show_babel_neighbour_sub (struct vty *vty, struct neighbour *neigh)
                    747: {
                    748:     vty_out (vty,
                    749:              "Neighbour %s dev %s reach %04x rxcost %d txcost %d %s.%s",
                    750:              format_address(neigh->address),
                    751:              neigh->ifp->name,
                    752:              neigh->reach,
                    753:              neighbour_rxcost(neigh),
                    754:              neigh->txcost,
                    755:              if_up(neigh->ifp) ? "" : " (down)",
                    756:              VTY_NEWLINE);
                    757: }
                    758: 
                    759: DEFUN (show_babel_neighbour,
                    760:        show_babel_neighbour_cmd,
                    761:        "show babel neighbour [INTERFACE]",
                    762:        SHOW_STR
                    763:        IP_STR
                    764:        "Babel information\n"
                    765:        "Print neighbours\n"
                    766:        "Interface name\n")
                    767: {
                    768:     struct neighbour *neigh;
                    769:     struct interface *ifp;
                    770: 
                    771:     if (argc == 0) {
                    772:         FOR_ALL_NEIGHBOURS(neigh) {
                    773:             show_babel_neighbour_sub(vty, neigh);
                    774:         }
                    775:         return CMD_SUCCESS;
                    776:     }
                    777:     if ((ifp = if_lookup_by_name (argv[0])) == NULL)
                    778:     {
                    779:         vty_out (vty, "No such interface name%s", VTY_NEWLINE);
                    780:         return CMD_WARNING;
                    781:     }
                    782:     FOR_ALL_NEIGHBOURS(neigh) {
                    783:         if(ifp->ifindex == neigh->ifp->ifindex) {
                    784:             show_babel_neighbour_sub(vty, neigh);
                    785:         }
                    786:     }
                    787:     return CMD_SUCCESS;
                    788: }
                    789: 
                    790: static void
                    791: show_babel_routes_sub (struct babel_route *route, void *closure)
                    792: {
                    793:     struct vty *vty = (struct vty*) closure;
                    794:     const unsigned char *nexthop =
                    795:         memcmp(route->nexthop, route->neigh->address, 16) == 0 ?
                    796:         NULL : route->nexthop;
                    797:     char channels[100];
                    798: 
                    799:     if(route->channels[0] == 0)
                    800:         channels[0] = '\0';
                    801:     else {
                    802:         int k, j = 0;
                    803:         snprintf(channels, 100, " chan (");
                    804:         j = strlen(channels);
                    805:         for(k = 0; k < DIVERSITY_HOPS; k++) {
                    806:             if(route->channels[k] == 0)
                    807:                 break;
                    808:             if(k > 0)
                    809:                 channels[j++] = ',';
                    810:             snprintf(channels + j, 100 - j, "%d", route->channels[k]);
                    811:             j = strlen(channels);
                    812:         }
                    813:         snprintf(channels + j, 100 - j, ")");
                    814:         if(k == 0)
                    815:             channels[0] = '\0';
                    816:     }
                    817: 
                    818:     vty_out(vty,
                    819:             "%s metric %d refmetric %d id %s seqno %d%s age %d "
                    820:             "via %s neigh %s%s%s%s%s",
                    821:             format_prefix(route->src->prefix, route->src->plen),
                    822:             route_metric(route), route->refmetric,
                    823:             format_eui64(route->src->id),
                    824:             (int)route->seqno,
                    825:             channels,
                    826:             (int)(babel_now.tv_sec - route->time),
                    827:             route->neigh->ifp->name,
                    828:             format_address(route->neigh->address),
                    829:             nexthop ? " nexthop " : "",
                    830:             nexthop ? format_address(nexthop) : "",
                    831:             route->installed ? " (installed)" :
                    832:             route_feasible(route) ? " (feasible)" : "",
                    833:             VTY_NEWLINE);
                    834: }
                    835: 
                    836: static void
                    837: show_babel_xroutes_sub (struct xroute *xroute, void *closure)
                    838: {
                    839:     struct vty *vty = (struct vty *) closure;
                    840:     vty_out(vty, "%s metric %d (exported)%s",
                    841:             format_prefix(xroute->prefix, xroute->plen),
                    842:             xroute->metric,
                    843:             VTY_NEWLINE);
                    844: }
                    845: 
                    846: DEFUN (show_babel_database,
                    847:        show_babel_database_cmd,
                    848:        "show babel database",
                    849:        SHOW_STR
                    850:        IP_STR
                    851:        "Babel information\n"
                    852:        "Database information\n"
                    853:        "No attributes\n")
                    854: {
                    855:     for_all_routes(show_babel_routes_sub, vty);
                    856:     for_all_xroutes(show_babel_xroutes_sub, vty);
                    857:     return CMD_SUCCESS;
                    858: }
                    859: 
                    860: DEFUN (show_babel_parameters,
                    861:        show_babel_parameters_cmd,
                    862:        "show babel parameters",
                    863:        SHOW_STR
                    864:        IP_STR
                    865:        "Babel information\n"
                    866:        "Configuration information\n"
                    867:        "No attributes\n")
                    868: {
                    869:     vty_out(vty, "    -- Babel running configuration --%s", VTY_NEWLINE);
                    870:     show_babel_main_configuration(vty);
                    871:     vty_out(vty, "    -- distribution lists --%s", VTY_NEWLINE);
                    872:     config_show_distribute(vty);
                    873: 
                    874:     return CMD_SUCCESS;
                    875: }
                    876: 
                    877: void
                    878: babel_if_init ()
                    879: {
                    880:     /* initialize interface list */
                    881:     if_init();
                    882:     if_add_hook (IF_NEW_HOOK,    babel_if_new_hook);
                    883:     if_add_hook (IF_DELETE_HOOK, babel_if_delete_hook);
                    884: 
                    885:     babel_enable_if = vector_init (1);
                    886: 
                    887:     /* install interface node and commands */
                    888:     install_element (CONFIG_NODE, &interface_cmd);
                    889:     install_element (CONFIG_NODE, &no_interface_cmd);
                    890:     install_node (&babel_interface_node, interface_config_write);
                    891:     install_default(INTERFACE_NODE);
                    892:     install_element(INTERFACE_NODE, &interface_cmd);
                    893:     install_element(INTERFACE_NODE, &no_interface_cmd);
                    894: 
                    895:     install_element(BABEL_NODE, &babel_network_cmd);
                    896:     install_element(BABEL_NODE, &no_babel_network_cmd);
                    897:     install_element(INTERFACE_NODE, &babel_split_horizon_cmd);
                    898:     install_element(INTERFACE_NODE, &no_babel_split_horizon_cmd);
                    899:     install_element(INTERFACE_NODE, &babel_set_wired_cmd);
                    900:     install_element(INTERFACE_NODE, &babel_set_wireless_cmd);
                    901:     install_element(INTERFACE_NODE, &babel_set_hello_interval_cmd);
                    902:     install_element(INTERFACE_NODE, &babel_set_update_interval_cmd);
                    903: 
                    904:     /* "show babel ..." commands */
                    905:     install_element(VIEW_NODE, &show_babel_interface_cmd);
                    906:     install_element(ENABLE_NODE, &show_babel_interface_cmd);
                    907:     install_element(VIEW_NODE, &show_babel_neighbour_cmd);
                    908:     install_element(ENABLE_NODE, &show_babel_neighbour_cmd);
                    909:     install_element(VIEW_NODE, &show_babel_database_cmd);
                    910:     install_element(ENABLE_NODE, &show_babel_database_cmd);
                    911:     install_element(VIEW_NODE, &show_babel_parameters_cmd);
                    912:     install_element(ENABLE_NODE, &show_babel_parameters_cmd);
                    913: }
                    914: 
                    915: /* hooks: functions called respectively when struct interface is
                    916:  created or deleted. */
                    917: static int
                    918: babel_if_new_hook (struct interface *ifp)
                    919: {
                    920:     ifp->info = babel_interface_allocate();
                    921:     return 0;
                    922: }
                    923: 
                    924: static int
                    925: babel_if_delete_hook (struct interface *ifp)
                    926: {
                    927:     babel_interface_free(ifp->info);
                    928:     ifp->info = NULL;
                    929:     return 0;
                    930: }
                    931: 
                    932: /* Output an "interface" section for each of the known interfaces with
                    933: babeld-specific statement lines where appropriate. */
                    934: static int
                    935: interface_config_write (struct vty *vty)
                    936: {
                    937:     struct listnode *node;
                    938:     struct interface *ifp;
                    939:     int write = 0;
                    940: 
                    941:     for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) {
                    942:         vty_out (vty, "interface %s%s", ifp->name,
                    943:                  VTY_NEWLINE);
                    944:         if (ifp->desc)
                    945:             vty_out (vty, " description %s%s", ifp->desc,
                    946:                      VTY_NEWLINE);
                    947:         if (IS_ENABLE (ifp))
                    948:         {
                    949:             babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp);
                    950:             /* wireless/no split-horizon is the default */
                    951:             if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_WIRED))
                    952:             {
                    953:                 vty_out (vty, " babel wired%s", VTY_NEWLINE);
                    954:                 write++;
                    955:             }
                    956:             if (CHECK_FLAG (babel_ifp->flags, BABEL_IF_SPLIT_HORIZON))
                    957:             {
                    958:                 vty_out (vty, " babel split-horizon%s", VTY_NEWLINE);
                    959:                 write++;
                    960:             }
                    961:             if (babel_ifp->hello_interval != BABEL_DEFAULT_HELLO_INTERVAL)
                    962:             {
                    963:                 vty_out (vty, " babel hello-interval %u%s", babel_ifp->hello_interval, VTY_NEWLINE);
                    964:                 write++;
                    965:             }
                    966:             if (babel_ifp->update_interval != BABEL_DEFAULT_UPDATE_INTERVAL)
                    967:             {
                    968:                 vty_out (vty, " babel update-interval %u%s", babel_ifp->update_interval, VTY_NEWLINE);
                    969:                 write++;
                    970:             }
                    971:         }
                    972:         vty_out (vty, "!%s", VTY_NEWLINE);
                    973:         write++;
                    974:     }
                    975:     return write;
                    976: }
                    977: 
                    978: /* Output a "network" statement line for each of the enabled interfaces. */
                    979: int
                    980: babel_enable_if_config_write (struct vty * vty)
                    981: {
                    982:     unsigned int i, lines = 0;
                    983:     char *str;
                    984: 
                    985:     for (i = 0; i < vector_active (babel_enable_if); i++)
                    986:         if ((str = vector_slot (babel_enable_if, i)) != NULL)
                    987:         {
                    988:             vty_out (vty, " network %s%s", str, VTY_NEWLINE);
                    989:             lines++;
                    990:         }
                    991:     return lines;
                    992: }
                    993: 
                    994: /* functions to allocate or free memory for a babel_interface_nfo, filling
                    995:  needed fields */
                    996: static babel_interface_nfo *
                    997: babel_interface_allocate (void)
                    998: {
                    999:     babel_interface_nfo *babel_ifp;
                   1000:     babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
                   1001:     if(babel_ifp == NULL)
                   1002:         return NULL;
                   1003: 
                   1004:     /* Here are set the default values for an interface. */
                   1005:     memset(babel_ifp, 0, sizeof(babel_interface_nfo));
                   1006:     /* All flags are unset */
                   1007:     babel_ifp->bucket_time = babel_now.tv_sec;
                   1008:     babel_ifp->bucket = BUCKET_TOKENS_MAX;
                   1009:     babel_ifp->hello_seqno = (random() & 0xFFFF);
                   1010:     babel_ifp->hello_interval = BABEL_DEFAULT_HELLO_INTERVAL;
                   1011:     babel_ifp->update_interval = BABEL_DEFAULT_UPDATE_INTERVAL;
                   1012:     babel_ifp->channel = BABEL_IF_CHANNEL_INTERFERING;
                   1013:     babel_set_wired_internal(babel_ifp, 0);
                   1014: 
                   1015:     return babel_ifp;
                   1016: }
                   1017: 
                   1018: static void
                   1019: babel_interface_free (babel_interface_nfo *babel_ifp)
                   1020: {
                   1021:     XFREE(MTYPE_BABEL_IF, babel_ifp);
                   1022: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>