Annotation of embedaddon/quagga/babeld/babeld.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 "command.h"
                     42: #include "prefix.h"
                     43: #include "memory.h"
                     44: #include "memtypes.h"
                     45: #include "table.h"
                     46: #include "distribute.h"
                     47: #include "prefix.h"
                     48: #include "filter.h"
                     49: #include "plist.h"
                     50: 
                     51: #include "babel_main.h"
                     52: #include "babeld.h"
                     53: #include "util.h"
                     54: #include "net.h"
                     55: #include "kernel.h"
                     56: #include "babel_interface.h"
                     57: #include "neighbour.h"
                     58: #include "route.h"
                     59: #include "message.h"
                     60: #include "resend.h"
                     61: #include "babel_filter.h"
                     62: #include "babel_zebra.h"
                     63: 
                     64: 
                     65: static int babel_init_routing_process(struct thread *thread);
                     66: static void babel_get_myid(void);
                     67: static void babel_initial_noise(void);
                     68: static int babel_read_protocol (struct thread *thread);
                     69: static int babel_main_loop(struct thread *thread);
                     70: static void babel_set_timer(struct timeval *timeout);
                     71: static void babel_fill_with_next_timeout(struct timeval *tv);
                     72: 
                     73: 
                     74: /* Informations relative to the babel running daemon. */
                     75: static struct babel *babel_routing_process = NULL;
                     76: static unsigned char *receive_buffer = NULL;
                     77: static int receive_buffer_size = 0;
                     78: 
                     79: /* timeouts */
                     80: struct timeval check_neighbours_timeout;
                     81: static time_t expiry_time;
                     82: static time_t source_expiry_time;
                     83: 
                     84: /* Babel node structure. */
                     85: static struct cmd_node cmd_babel_node =
                     86: {
                     87:     .node   = BABEL_NODE,
                     88:     .prompt = "%s(config-router)# ",
                     89:     .vtysh  = 1,
                     90: };
                     91: 
                     92: /* print current babel configuration on vty */
                     93: static int
                     94: babel_config_write (struct vty *vty)
                     95: {
                     96:     int lines = 0;
                     97:     int i;
                     98: 
                     99:     /* list enabled debug modes */
                    100:     lines += debug_babel_config_write (vty);
                    101: 
                    102:     if (!babel_routing_process)
                    103:         return lines;
                    104:     vty_out (vty, "router babel%s", VTY_NEWLINE);
                    105:     if (resend_delay != BABEL_DEFAULT_RESEND_DELAY)
                    106:     {
                    107:         vty_out (vty, " babel resend-delay %u%s", resend_delay, VTY_NEWLINE);
                    108:         lines++;
                    109:     }
                    110:     /* list enabled interfaces */
                    111:     lines = 1 + babel_enable_if_config_write (vty);
                    112:     /* list redistributed protocols */
                    113:     for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
                    114:         if (i != zclient->redist_default && zclient->redist[i])
                    115:         {
                    116:             vty_out (vty, " redistribute %s%s", zebra_route_string (i), VTY_NEWLINE);
                    117:             lines++;
                    118:         }
                    119: 
                    120:     return lines;
                    121: }
                    122: 
                    123: 
                    124: static int
                    125: babel_create_routing_process (void)
                    126: {
                    127:     assert (babel_routing_process == NULL);
                    128: 
                    129:     /* Allocaste Babel instance. */
                    130:     babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));
                    131: 
                    132:     /* Initialize timeouts */
                    133:     gettime(&babel_now);
                    134:     expiry_time = babel_now.tv_sec + roughly(30);
                    135:     source_expiry_time = babel_now.tv_sec + roughly(300);
                    136: 
                    137:     /* Make socket for Babel protocol. */
                    138:     protocol_socket = babel_socket(protocol_port);
                    139:     if (protocol_socket < 0) {
                    140:         zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
                    141:         goto fail;
                    142:     }
                    143: 
                    144:     /* Threads. */
                    145:     babel_routing_process->t_read =
                    146:     thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
                    147:     /* wait a little: zebra will announce interfaces, addresses, routes... */
                    148:     babel_routing_process->t_update =
                    149:     thread_add_timer_msec(master, &babel_init_routing_process, NULL, 200L);
                    150:     return 0;
                    151: 
                    152: fail:
                    153:     XFREE(MTYPE_BABEL, babel_routing_process);
                    154:     babel_routing_process = NULL;
                    155:     return -1;
                    156: }
                    157: 
                    158: /* thread reading entries form others babel daemons */
                    159: static int
                    160: babel_read_protocol (struct thread *thread)
                    161: {
                    162:     int rc;
                    163:     struct interface *ifp = NULL;
                    164:     struct sockaddr_in6 sin6;
                    165:     struct listnode *linklist_node = NULL;
                    166: 
                    167:     assert(babel_routing_process != NULL);
                    168:     assert(protocol_socket >= 0);
                    169: 
                    170:     rc = babel_recv(protocol_socket,
                    171:                     receive_buffer, receive_buffer_size,
                    172:                     (struct sockaddr*)&sin6, sizeof(sin6));
                    173:     if(rc < 0) {
                    174:         if(errno != EAGAIN && errno != EINTR) {
                    175:             zlog_err("recv: %s", safe_strerror(errno));
                    176:         }
                    177:     } else {
                    178:         FOR_ALL_INTERFACES(ifp, linklist_node) {
                    179:             if(!if_up(ifp))
                    180:                 continue;
                    181:             if(ifp->ifindex == sin6.sin6_scope_id) {
                    182:                 parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
                    183:                              receive_buffer, rc);
                    184:                 break;
                    185:             }
                    186:         }
                    187:     }
                    188: 
                    189:     /* re-add thread */
                    190:     babel_routing_process->t_read =
                    191:     thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
                    192:     return 0;
                    193: }
                    194: 
                    195: /* Zebra will give some information, especially about interfaces. This function
                    196:  must be call with a litte timeout wich may give zebra the time to do his job,
                    197:  making these inits have sense. */
                    198: static int
                    199: babel_init_routing_process(struct thread *thread)
                    200: {
                    201:     myseqno = (random() & 0xFFFF);
                    202:     babel_get_myid();
                    203:     babel_load_state_file();
                    204:     debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
                    205:     babel_initial_noise();
                    206:     babel_main_loop(thread);/* this function self-add to the t_update thread */
                    207:     return 0;
                    208: }
                    209: 
                    210: /* fill "myid" with an unique id (only if myid != {0}). */
                    211: static void
                    212: babel_get_myid(void)
                    213: {
                    214:     struct interface *ifp = NULL;
                    215:     struct listnode *linklist_node = NULL;
                    216:     int rc;
                    217:     int i;
                    218: 
                    219:     /* if we already have an id (from state file), we return. */
                    220:     if (memcmp(myid, zeroes, 8) != 0) {
                    221:         return;
                    222:     }
                    223: 
                    224:     FOR_ALL_INTERFACES(ifp, linklist_node) {
                    225:         /* ifp->ifindex is not necessarily valid at this point */
                    226:         int ifindex = if_nametoindex(ifp->name);
                    227:         if(ifindex > 0) {
                    228:             unsigned char eui[8];
                    229:             rc = if_eui64(ifp->name, ifindex, eui);
                    230:             if(rc < 0)
                    231:                 continue;
                    232:             memcpy(myid, eui, 8);
                    233:             return;
                    234:         }
                    235:     }
                    236: 
                    237:     /* We failed to get a global EUI64 from the interfaces we were given.
                    238:      Let's try to find an interface with a MAC address. */
                    239:     for(i = 1; i < 256; i++) {
                    240:         char buf[IF_NAMESIZE], *ifname;
                    241:         unsigned char eui[8];
                    242:         ifname = if_indextoname(i, buf);
                    243:         if(ifname == NULL)
                    244:             continue;
                    245:         rc = if_eui64(ifname, i, eui);
                    246:         if(rc < 0)
                    247:             continue;
                    248:         memcpy(myid, eui, 8);
                    249:         return;
                    250:     }
                    251: 
                    252:     zlog_err("Warning: couldn't find router id -- using random value.");
                    253: 
                    254:     rc = read_random_bytes(myid, 8);
                    255:     if(rc < 0) {
                    256:         zlog_err("read(random): %s (cannot assign an ID)",safe_strerror(errno));
                    257:         exit(1);
                    258:     }
                    259:     /* Clear group and global bits */
                    260:     myid[0] &= ~3;
                    261: }
                    262: 
                    263: /* Make some noise so that others notice us, and send retractions in
                    264:  case we were restarted recently */
                    265: static void
                    266: babel_initial_noise(void)
                    267: {
                    268:     struct interface *ifp = NULL;
                    269:     struct listnode *linklist_node = NULL;
                    270: 
                    271:     FOR_ALL_INTERFACES(ifp, linklist_node) {
                    272:         if(!if_up(ifp))
                    273:             continue;
                    274:         /* Apply jitter before we send the first message. */
                    275:         usleep(roughly(10000));
                    276:         gettime(&babel_now);
                    277:         send_hello(ifp);
                    278:         send_wildcard_retraction(ifp);
                    279:     }
                    280: 
                    281:     FOR_ALL_INTERFACES(ifp, linklist_node) {
                    282:         if(!if_up(ifp))
                    283:             continue;
                    284:         usleep(roughly(10000));
                    285:         gettime(&babel_now);
                    286:         send_hello(ifp);
                    287:         send_wildcard_retraction(ifp);
                    288:         send_self_update(ifp);
                    289:         send_request(ifp, NULL, 0);
                    290:         flushupdates(ifp);
                    291:         flushbuf(ifp);
                    292:     }
                    293: }
                    294: 
                    295: /* Delete all the added babel routes, make babeld only speak to zebra. */
                    296: static void
                    297: babel_clean_routing_process()
                    298: {
                    299:     flush_all_routes();
                    300:     babel_interface_close_all();
                    301: 
                    302:     /* cancel threads */
                    303:     if (babel_routing_process->t_read != NULL) {
                    304:         thread_cancel(babel_routing_process->t_read);
                    305:     }
                    306:     if (babel_routing_process->t_update != NULL) {
                    307:         thread_cancel(babel_routing_process->t_update);
                    308:     }
                    309: 
                    310:     XFREE(MTYPE_BABEL, babel_routing_process);
                    311:     babel_routing_process = NULL;
                    312: }
                    313: 
                    314: /* Function used with timeout. */
                    315: static int
                    316: babel_main_loop(struct thread *thread)
                    317: {
                    318:     struct timeval tv;
                    319:     struct interface *ifp = NULL;
                    320:     struct listnode *linklist_node = NULL;
                    321: 
                    322:     while(1) {
                    323:         gettime(&babel_now);
                    324: 
                    325:         /* timeouts --------------------------------------------------------- */
                    326:         /* get the next timeout */
                    327:         babel_fill_with_next_timeout(&tv);
                    328:         /* if there is no timeout, we must wait. */
                    329:         if(timeval_compare(&tv, &babel_now) > 0) {
                    330:             timeval_minus(&tv, &tv, &babel_now);
                    331:             debugf(BABEL_DEBUG_TIMEOUT, "babel main loop : timeout: %ld msecs",
                    332:                    tv.tv_sec * 1000 + tv.tv_usec / 1000);
                    333:             /* it happens often to have less than 1 ms, it's bad. */
                    334:             timeval_add_msec(&tv, &tv, 300);
                    335:             babel_set_timer(&tv);
                    336:             return 0;
                    337:         }
                    338: 
                    339:         gettime(&babel_now);
                    340: 
                    341:         /* update database -------------------------------------------------- */
                    342:         if(timeval_compare(&check_neighbours_timeout, &babel_now) < 0) {
                    343:             int msecs;
                    344:             msecs = check_neighbours();
                    345:             msecs = MAX(msecs, 10);
                    346:             schedule_neighbours_check(msecs, 1);
                    347:         }
                    348: 
                    349:         if(babel_now.tv_sec >= expiry_time) {
                    350:             expire_routes();
                    351:             expire_resend();
                    352:             expiry_time = babel_now.tv_sec + roughly(30);
                    353:         }
                    354: 
                    355:         if(babel_now.tv_sec >= source_expiry_time) {
                    356:             expire_sources();
                    357:             source_expiry_time = babel_now.tv_sec + roughly(300);
                    358:         }
                    359: 
                    360:         FOR_ALL_INTERFACES(ifp, linklist_node) {
                    361:             babel_interface_nfo *babel_ifp = NULL;
                    362:             if(!if_up(ifp))
                    363:                 continue;
                    364:             babel_ifp = babel_get_if_nfo(ifp);
                    365:             if(timeval_compare(&babel_now, &babel_ifp->hello_timeout) >= 0)
                    366:                 send_hello(ifp);
                    367:             if(timeval_compare(&babel_now, &babel_ifp->update_timeout) >= 0)
                    368:                 send_update(ifp, 0, NULL, 0);
                    369:             if(timeval_compare(&babel_now,
                    370:                                &babel_ifp->update_flush_timeout) >= 0)
                    371:                 flushupdates(ifp);
                    372:         }
                    373: 
                    374:         if(resend_time.tv_sec != 0) {
                    375:             if(timeval_compare(&babel_now, &resend_time) >= 0)
                    376:                 do_resend();
                    377:         }
                    378: 
                    379:         if(unicast_flush_timeout.tv_sec != 0) {
                    380:             if(timeval_compare(&babel_now, &unicast_flush_timeout) >= 0)
                    381:                 flush_unicast(1);
                    382:         }
                    383: 
                    384:         FOR_ALL_INTERFACES(ifp, linklist_node) {
                    385:             babel_interface_nfo *babel_ifp = NULL;
                    386:             if(!if_up(ifp))
                    387:                 continue;
                    388:             babel_ifp = babel_get_if_nfo(ifp);
                    389:             if(babel_ifp->flush_timeout.tv_sec != 0) {
                    390:                 if(timeval_compare(&babel_now, &babel_ifp->flush_timeout) >= 0)
                    391:                     flushbuf(ifp);
                    392:             }
                    393:         }
                    394:     }
                    395: 
                    396:     assert(0); /* this line should never be reach */
                    397: }
                    398: 
                    399: static void
                    400: printIfMin(struct timeval *tv, int cmd, const char *tag, const char *ifname)
                    401: {
                    402:     static struct timeval curr_tv;
                    403:     static char buffer[200];
                    404:     static const char *curr_tag = NULL;
                    405: 
                    406:     switch (cmd) {
                    407:         case 0: /* reset timeval */
                    408:             curr_tv = *tv;
                    409:             if(ifname != NULL) {
                    410:                 snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
                    411:                 curr_tag = buffer;
                    412:             } else {
                    413:                 curr_tag = tag;
                    414:             }
                    415:             break;
                    416:         case 1: /* take the min */
                    417:             if (tv->tv_sec == 0 && tv->tv_usec == 0) { /* if (tv == ∞) */
                    418:                 break;
                    419:             }
                    420:             if (tv->tv_sec < curr_tv.tv_sec ||(tv->tv_sec == curr_tv.tv_sec &&
                    421:                                                tv->tv_usec < curr_tv.tv_usec)) {
                    422:                 curr_tv = *tv;
                    423:                 if(ifname != NULL) {
                    424:                     snprintf(buffer, 200L, "interface: %s; %s", ifname, tag);
                    425:                     curr_tag = buffer;
                    426:                 } else {
                    427:                     curr_tag = tag;
                    428:                 }
                    429:             }
                    430:             break;
                    431:         case 2: /* print message */
                    432:             debugf(BABEL_DEBUG_TIMEOUT, "next timeout due to: %s", curr_tag);
                    433:             break;
                    434:         default:
                    435:             break;
                    436:     }
                    437: }
                    438: 
                    439: static void
                    440: babel_fill_with_next_timeout(struct timeval *tv)
                    441: {
                    442: #if (defined NO_DEBUG)
                    443: #define printIfMin(a,b,c,d)
                    444: #else
                    445: #define printIfMin(a,b,c,d) \
                    446:   if (UNLIKELY(debug & BABEL_DEBUG_TIMEOUT)) {printIfMin(a,b,c,d);}
                    447: 
                    448:     struct interface *ifp = NULL;
                    449:     struct listnode *linklist_node = NULL;
                    450: 
                    451:     *tv = check_neighbours_timeout;
                    452:     printIfMin(tv, 0, "check_neighbours_timeout", NULL);
                    453:     timeval_min_sec(tv, expiry_time);
                    454:     printIfMin(tv, 1, "expiry_time", NULL);
                    455:     timeval_min_sec(tv, source_expiry_time);
                    456:     printIfMin(tv, 1, "source_expiry_time", NULL);
                    457:     timeval_min(tv, &resend_time);
                    458:     printIfMin(tv, 1, "resend_time", NULL);
                    459:     FOR_ALL_INTERFACES(ifp, linklist_node) {
                    460:         babel_interface_nfo *babel_ifp = NULL;
                    461:         if(!if_up(ifp))
                    462:             continue;
                    463:         babel_ifp = babel_get_if_nfo(ifp);
                    464:         timeval_min(tv, &babel_ifp->flush_timeout);
                    465:         printIfMin(tv, 1, "flush_timeout", ifp->name);
                    466:         timeval_min(tv, &babel_ifp->hello_timeout);
                    467:         printIfMin(tv, 1, "hello_timeout", ifp->name);
                    468:         timeval_min(tv, &babel_ifp->update_timeout);
                    469:         printIfMin(tv, 1, "update_timeout", ifp->name);
                    470:         timeval_min(tv, &babel_ifp->update_flush_timeout);
                    471:         printIfMin(tv, 1, "update_flush_timeout",ifp->name);
                    472:     }
                    473:     timeval_min(tv, &unicast_flush_timeout);
                    474:     printIfMin(tv, 1, "unicast_flush_timeout", NULL);
                    475:     printIfMin(tv, 2, NULL, NULL);
                    476: #undef printIfMin
                    477: #endif
                    478: }
                    479: 
                    480: /* set the t_update thread of the babel routing process to be launch in
                    481:  'timeout' (approximate at the milisecond) */
                    482: static void
                    483: babel_set_timer(struct timeval *timeout)
                    484: {
                    485:     long msecs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
                    486:     if (babel_routing_process->t_update != NULL) {
                    487:         thread_cancel(babel_routing_process->t_update);
                    488:     }
                    489:     babel_routing_process->t_update =
                    490:     thread_add_timer_msec(master, &babel_main_loop, NULL, msecs);
                    491: }
                    492: 
                    493: /* Schedule a neighbours check after roughly 3/2 times msecs have elapsed. */
                    494: void
                    495: schedule_neighbours_check(int msecs, int override)
                    496: {
                    497:     struct timeval timeout;
                    498: 
                    499:     timeval_add_msec(&timeout, &babel_now, roughly(msecs * 3 / 2));
                    500:     if(override)
                    501:         check_neighbours_timeout = timeout;
                    502:     else
                    503:         timeval_min(&check_neighbours_timeout, &timeout);
                    504: }
                    505: 
                    506: int
                    507: resize_receive_buffer(int size)
                    508: {
                    509:     if(size <= receive_buffer_size)
                    510:         return 0;
                    511: 
                    512:     if(receive_buffer == NULL) {
                    513:         receive_buffer = malloc(size);
                    514:         if(receive_buffer == NULL) {
                    515:             zlog_err("malloc(receive_buffer): %s", safe_strerror(errno));
                    516:             return -1;
                    517:         }
                    518:         receive_buffer_size = size;
                    519:     } else {
                    520:         unsigned char *new;
                    521:         new = realloc(receive_buffer, size);
                    522:         if(new == NULL) {
                    523:             zlog_err("realloc(receive_buffer): %s", safe_strerror(errno));
                    524:             return -1;
                    525:         }
                    526:         receive_buffer = new;
                    527:         receive_buffer_size = size;
                    528:     }
                    529:     return 1;
                    530: }
                    531: 
                    532: static void
                    533: babel_distribute_update (struct distribute *dist)
                    534: {
                    535:     struct interface *ifp;
                    536:     babel_interface_nfo *babel_ifp;
                    537:     struct access_list *alist;
                    538:     struct prefix_list *plist;
                    539: 
                    540:     if (! dist->ifname)
                    541:         return;
                    542: 
                    543:     ifp = if_lookup_by_name (dist->ifname);
                    544:     if (ifp == NULL)
                    545:         return;
                    546: 
                    547:     babel_ifp = babel_get_if_nfo(ifp);
                    548: 
                    549:     if (dist->list[DISTRIBUTE_IN]) {
                    550:         alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
                    551:         if (alist)
                    552:             babel_ifp->list[BABEL_FILTER_IN] = alist;
                    553:         else
                    554:             babel_ifp->list[BABEL_FILTER_IN] = NULL;
                    555:     } else {
                    556:         babel_ifp->list[BABEL_FILTER_IN] = NULL;
                    557:     }
                    558: 
                    559:     if (dist->list[DISTRIBUTE_OUT]) {
                    560:         alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
                    561:         if (alist)
                    562:             babel_ifp->list[BABEL_FILTER_OUT] = alist;
                    563:         else
                    564:             babel_ifp->list[BABEL_FILTER_OUT] = NULL;
                    565:     } else {
                    566:         babel_ifp->list[BABEL_FILTER_OUT] = NULL;
                    567:     }
                    568: 
                    569:     if (dist->prefix[DISTRIBUTE_IN]) {
                    570:         plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
                    571:         if (plist)
                    572:             babel_ifp->prefix[BABEL_FILTER_IN] = plist;
                    573:         else
                    574:             babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
                    575:     } else {
                    576:         babel_ifp->prefix[BABEL_FILTER_IN] = NULL;
                    577:     }
                    578: 
                    579:     if (dist->prefix[DISTRIBUTE_OUT]) {
                    580:         plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
                    581:         if (plist)
                    582:             babel_ifp->prefix[BABEL_FILTER_OUT] = plist;
                    583:         else
                    584:             babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
                    585:     } else {
                    586:         babel_ifp->prefix[BABEL_FILTER_OUT] = NULL;
                    587:     }
                    588: }
                    589: 
                    590: static void
                    591: babel_distribute_update_interface (struct interface *ifp)
                    592: {
                    593:     struct distribute *dist;
                    594: 
                    595:     dist = distribute_lookup (ifp->name);
                    596:     if (dist)
                    597:         babel_distribute_update (dist);
                    598: }
                    599: 
                    600: /* Update all interface's distribute list. */
                    601: static void
                    602: babel_distribute_update_all (struct prefix_list *notused)
                    603: {
                    604:     struct interface *ifp;
                    605:     struct listnode *node;
                    606: 
                    607:     for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
                    608:         babel_distribute_update_interface (ifp);
                    609: }
                    610: 
                    611: static void
                    612: babel_distribute_update_all_wrapper (struct access_list *notused)
                    613: {
                    614:     babel_distribute_update_all(NULL);
                    615: }
                    616: 
                    617: 
                    618: /* [Command] */
                    619: DEFUN (router_babel,
                    620:        router_babel_cmd,
                    621:        "router babel",
                    622:        "Enable a routing process\n"
                    623:        "Make Babel instance command\n"
                    624:        "No attributes\n")
                    625: {
                    626:     int ret;
                    627: 
                    628:     vty->node = BABEL_NODE;
                    629: 
                    630:     if (!babel_routing_process) {
                    631:         ret = babel_create_routing_process ();
                    632: 
                    633:         /* Notice to user we couldn't create Babel. */
                    634:         if (ret < 0) {
                    635:             zlog_warn ("can't create Babel");
                    636:             return CMD_WARNING;
                    637:         }
                    638:     }
                    639: 
                    640:     return CMD_SUCCESS;
                    641: }
                    642: 
                    643: /* [Command] */
                    644: DEFUN (no_router_babel,
                    645:        no_router_babel_cmd,
                    646:        "no router babel",
                    647:        NO_STR
                    648:        "Disable a routing process\n"
                    649:        "Remove Babel instance command\n"
                    650:        "No attributes\n")
                    651: {
                    652:     if(babel_routing_process)
                    653:         babel_clean_routing_process();
                    654:     return CMD_SUCCESS;
                    655: }
                    656: 
                    657: /* [Babel Command] */
                    658: DEFUN (babel_set_resend_delay,
                    659:        babel_set_resend_delay_cmd,
                    660:        "babel resend-delay <20-655340>",
                    661:        "Babel commands\n"
                    662:        "Time before resending a message\n"
                    663:        "Milliseconds\n")
                    664: {
                    665:     int interval;
                    666: 
                    667:     VTY_GET_INTEGER_RANGE("milliseconds", interval, argv[0], 20, 10 * 0xFFFE);
                    668: 
                    669:     resend_delay = interval;
                    670:     return CMD_SUCCESS;
                    671: }
                    672: 
                    673: void
                    674: babeld_quagga_init(void)
                    675: {
                    676: 
                    677:     install_node(&cmd_babel_node, &babel_config_write);
                    678: 
                    679:     install_element(CONFIG_NODE, &router_babel_cmd);
                    680:     install_element(CONFIG_NODE, &no_router_babel_cmd);
                    681: 
                    682:     install_default(BABEL_NODE);
                    683:     install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
                    684: 
                    685:     babel_if_init();
                    686: 
                    687:     /* Access list install. */
                    688:     access_list_init ();
                    689:     access_list_add_hook (babel_distribute_update_all_wrapper);
                    690:     access_list_delete_hook (babel_distribute_update_all_wrapper);
                    691: 
                    692:     /* Prefix list initialize.*/
                    693:     prefix_list_init ();
                    694:     prefix_list_add_hook (babel_distribute_update_all);
                    695:     prefix_list_delete_hook (babel_distribute_update_all);
                    696: 
                    697:     /* Distribute list install. */
                    698:     distribute_list_init (BABEL_NODE);
                    699:     distribute_list_add_hook (babel_distribute_update);
                    700:     distribute_list_delete_hook (babel_distribute_update);
                    701: }
                    702: 
                    703: /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
                    704: 
                    705: int
                    706: input_filter(const unsigned char *id,
                    707:              const unsigned char *prefix, unsigned short plen,
                    708:              const unsigned char *neigh, unsigned int ifindex)
                    709: {
                    710:     return babel_filter(0, prefix, plen, ifindex);
                    711: }
                    712: 
                    713: int
                    714: output_filter(const unsigned char *id, const unsigned char *prefix,
                    715:               unsigned short plen, unsigned int ifindex)
                    716: {
                    717:     return babel_filter(1, prefix, plen, ifindex);
                    718: }
                    719: 
                    720: /* There's no redistribute filter in Quagga -- the zebra daemon does its
                    721:    own filtering. */
                    722: int
                    723: redistribute_filter(const unsigned char *prefix, unsigned short plen,
                    724:                     unsigned int ifindex, int proto)
                    725: {
                    726:     return 0;
                    727: }
                    728: 

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