Annotation of embedaddon/quagga/ospfd/ospf_zebra.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * Zebra connect library for OSPFd
                      3:  * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
                      4:  *
                      5:  * This file is part of GNU Zebra.
                      6:  *
                      7:  * GNU Zebra is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2, or (at your option) any
                     10:  * later version.
                     11:  *
                     12:  * GNU Zebra is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU General Public License
                     18:  * along with GNU Zebra; see the file COPYING.  If not, write to the
                     19:  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
                     20:  * Boston, MA 02111-1307, USA. 
                     21:  */
                     22: 
                     23: #include <zebra.h>
                     24: 
                     25: #include "thread.h"
                     26: #include "command.h"
                     27: #include "network.h"
                     28: #include "prefix.h"
                     29: #include "routemap.h"
                     30: #include "table.h"
                     31: #include "stream.h"
                     32: #include "memory.h"
                     33: #include "zclient.h"
                     34: #include "filter.h"
                     35: #include "plist.h"
                     36: #include "log.h"
                     37: 
                     38: #include "ospfd/ospfd.h"
                     39: #include "ospfd/ospf_interface.h"
                     40: #include "ospfd/ospf_ism.h"
                     41: #include "ospfd/ospf_asbr.h"
                     42: #include "ospfd/ospf_asbr.h"
                     43: #include "ospfd/ospf_abr.h"
                     44: #include "ospfd/ospf_lsa.h"
                     45: #include "ospfd/ospf_dump.h"
                     46: #include "ospfd/ospf_route.h"
                     47: #include "ospfd/ospf_zebra.h"
                     48: #ifdef HAVE_SNMP
                     49: #include "ospfd/ospf_snmp.h"
                     50: #endif /* HAVE_SNMP */
                     51: 
                     52: /* Zebra structure to hold current status. */
                     53: struct zclient *zclient = NULL;
                     54: 
                     55: /* For registering threads. */
                     56: extern struct thread_master *master;
                     57: struct in_addr router_id_zebra;
                     58: 
                     59: /* Router-id update message from zebra. */
                     60: static int
                     61: ospf_router_id_update_zebra (int command, struct zclient *zclient,
                     62:                             zebra_size_t length)
                     63: {
                     64:   struct ospf *ospf;
                     65:   struct prefix router_id;
                     66:   zebra_router_id_update_read(zclient->ibuf,&router_id);
                     67: 
                     68:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                     69:     {
                     70:       char buf[128];
                     71:       prefix2str(&router_id, buf, sizeof(buf));
                     72:       zlog_debug("Zebra rcvd: router id update %s", buf);
                     73:     }
                     74: 
                     75:   router_id_zebra = router_id.u.prefix4;
                     76: 
                     77:   ospf = ospf_lookup ();
                     78:   
                     79:   if (ospf != NULL)
                     80:     ospf_router_id_update (ospf);
                     81:   
                     82:   return 0;
                     83: }
                     84: 
                     85: /* Inteface addition message from zebra. */
                     86: static int
                     87: ospf_interface_add (int command, struct zclient *zclient, zebra_size_t length)
                     88: {
                     89:   struct interface *ifp;
                     90: 
                     91:   ifp = zebra_interface_add_read (zclient->ibuf);
                     92: 
                     93:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                     94:     zlog_debug ("Zebra: interface add %s index %d flags %llx metric %d mtu %d",
                     95:                ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
                     96:                ifp->metric, ifp->mtu);
                     97: 
                     98:   assert (ifp->info);
                     99: 
                    100:   if (!OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
                    101:     {
                    102:       SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
                    103:       IF_DEF_PARAMS (ifp)->type = ospf_default_iftype(ifp);
                    104:     }
                    105: 
                    106:   ospf_if_update (NULL, ifp);
                    107: 
                    108: #ifdef HAVE_SNMP
                    109:   ospf_snmp_if_update (ifp);
                    110: #endif /* HAVE_SNMP */
                    111: 
                    112:   return 0;
                    113: }
                    114: 
                    115: static int
                    116: ospf_interface_delete (int command, struct zclient *zclient,
                    117:                        zebra_size_t length)
                    118: {
                    119:   struct interface *ifp;
                    120:   struct stream *s;
                    121:   struct route_node *rn;
                    122: 
                    123:   s = zclient->ibuf;
                    124:   /* zebra_interface_state_read() updates interface structure in iflist */
                    125:   ifp = zebra_interface_state_read (s);
                    126: 
                    127:   if (ifp == NULL)
                    128:     return 0;
                    129: 
                    130:   if (if_is_up (ifp))
                    131:     zlog_warn ("Zebra: got delete of %s, but interface is still up",
                    132:                ifp->name);
                    133: 
                    134:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    135:     zlog_debug
                    136:       ("Zebra: interface delete %s index %d flags %lld metric %d mtu %d",
                    137:        ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
                    138: 
                    139: #ifdef HAVE_SNMP
                    140:   ospf_snmp_if_delete (ifp);
                    141: #endif /* HAVE_SNMP */
                    142: 
                    143:   for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
                    144:     if (rn->info)
                    145:       ospf_if_free ((struct ospf_interface *) rn->info);
                    146: 
                    147:   ifp->ifindex = IFINDEX_INTERNAL;
                    148:   return 0;
                    149: }
                    150: 
                    151: static struct interface *
                    152: zebra_interface_if_lookup (struct stream *s)
                    153: {
                    154:   char ifname_tmp[INTERFACE_NAMSIZ];
                    155: 
                    156:   /* Read interface name. */
                    157:   stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
                    158: 
                    159:   /* And look it up. */
                    160:   return if_lookup_by_name_len(ifname_tmp,
                    161:                               strnlen(ifname_tmp, INTERFACE_NAMSIZ));
                    162: }
                    163: 
                    164: static int
                    165: ospf_interface_state_up (int command, struct zclient *zclient,
                    166:                          zebra_size_t length)
                    167: {
                    168:   struct interface *ifp;
                    169:   struct ospf_interface *oi;
                    170:   struct route_node *rn;
                    171: 
                    172:   ifp = zebra_interface_if_lookup (zclient->ibuf);
                    173: 
                    174:   if (ifp == NULL)
                    175:     return 0;
                    176: 
                    177:   /* Interface is already up. */
                    178:   if (if_is_operative (ifp))
                    179:     {
                    180:       /* Temporarily keep ifp values. */
                    181:       struct interface if_tmp;
                    182:       memcpy (&if_tmp, ifp, sizeof (struct interface));
                    183: 
                    184:       zebra_interface_if_set_value (zclient->ibuf, ifp);
                    185: 
                    186:       if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    187:         zlog_debug ("Zebra: Interface[%s] state update.", ifp->name);
                    188: 
                    189:       if (if_tmp.bandwidth != ifp->bandwidth)
                    190:         {
                    191:           if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    192:             zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.",
                    193:                        ifp->name, if_tmp.bandwidth, ifp->bandwidth);
                    194: 
                    195:           ospf_if_recalculate_output_cost (ifp);
                    196:         }
                    197: 
                    198:       if (if_tmp.mtu != ifp->mtu)
                    199:         {
                    200:           if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    201:             zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.",
                    202:                        ifp->name, if_tmp.mtu, ifp->mtu);
                    203: 
                    204:          /* Must reset the interface (simulate down/up) when MTU changes. */
                    205:           ospf_if_reset(ifp);
                    206:        }
                    207:       return 0;
                    208:     }
                    209: 
                    210:   zebra_interface_if_set_value (zclient->ibuf, ifp);
                    211: 
                    212:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    213:     zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name);
                    214: 
                    215:   for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
                    216:     {
                    217:       if ((oi = rn->info) == NULL)
                    218:         continue;
                    219: 
                    220:       ospf_if_up (oi);
                    221:     }
                    222: 
                    223:   return 0;
                    224: }
                    225: 
                    226: static int
                    227: ospf_interface_state_down (int command, struct zclient *zclient,
                    228:                            zebra_size_t length)
                    229: {
                    230:   struct interface *ifp;
                    231:   struct ospf_interface *oi;
                    232:   struct route_node *node;
                    233: 
                    234:   ifp = zebra_interface_state_read (zclient->ibuf);
                    235: 
                    236:   if (ifp == NULL)
                    237:     return 0;
                    238: 
                    239:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    240:     zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name);
                    241: 
                    242:   for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
                    243:     {
                    244:       if ((oi = node->info) == NULL)
                    245:         continue;
                    246:       ospf_if_down (oi);
                    247:     }
                    248: 
                    249:   return 0;
                    250: }
                    251: 
                    252: static int
                    253: ospf_interface_address_add (int command, struct zclient *zclient,
                    254:                             zebra_size_t length)
                    255: {
                    256:   struct connected *c;
                    257: 
                    258:   c = zebra_interface_address_read (command, zclient->ibuf);
                    259: 
                    260:   if (c == NULL)
                    261:     return 0;
                    262: 
                    263:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    264:     {
                    265:       char buf[128];
                    266:       prefix2str(c->address, buf, sizeof(buf));
                    267:       zlog_debug("Zebra: interface %s address add %s", c->ifp->name, buf);
                    268:     }
                    269: 
                    270:   ospf_if_update (NULL, c->ifp);
                    271: 
                    272: #ifdef HAVE_SNMP
                    273:   ospf_snmp_if_update (c->ifp);
                    274: #endif /* HAVE_SNMP */
                    275: 
                    276:   return 0;
                    277: }
                    278: 
                    279: static int
                    280: ospf_interface_address_delete (int command, struct zclient *zclient,
                    281:                                zebra_size_t length)
                    282: {
                    283:   struct connected *c;
                    284:   struct interface *ifp;
                    285:   struct ospf_interface *oi;
                    286:   struct route_node *rn;
                    287:   struct prefix p;
                    288: 
                    289:   c = zebra_interface_address_read (command, zclient->ibuf);
                    290: 
                    291:   if (c == NULL)
                    292:     return 0;
                    293: 
                    294:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    295:     {
                    296:       char buf[128];
                    297:       prefix2str(c->address, buf, sizeof(buf));
                    298:       zlog_debug("Zebra: interface %s address delete %s", c->ifp->name, buf);
                    299:     }
                    300: 
                    301:   ifp = c->ifp;
                    302:   p = *c->address;
                    303:   p.prefixlen = IPV4_MAX_PREFIXLEN;
                    304: 
                    305:   rn = route_node_lookup (IF_OIFS (ifp), &p);
                    306:   if (!rn)
                    307:     {
                    308:       connected_free (c);
                    309:       return 0;
                    310:     }
                    311: 
                    312:   assert (rn->info);
                    313:   oi = rn->info;
                    314: 
                    315:   /* Call interface hook functions to clean up */
                    316:   ospf_if_free (oi);
                    317: 
                    318: #ifdef HAVE_SNMP
                    319:   ospf_snmp_if_update (c->ifp);
                    320: #endif /* HAVE_SNMP */
                    321: 
                    322:   connected_free (c);
                    323: 
                    324:   return 0;
                    325: }
                    326: 
                    327: void
                    328: ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
                    329: {
                    330:   u_char message;
                    331:   u_char distance;
                    332:   u_char flags;
                    333:   int psize;
                    334:   struct stream *s;
                    335:   struct ospf_path *path;
                    336:   struct listnode *node;
                    337: 
                    338:   if (zclient->redist[ZEBRA_ROUTE_OSPF])
                    339:     {
                    340:       message = 0;
                    341:       flags = 0;
                    342: 
                    343:       /* OSPF pass nexthop and metric */
                    344:       SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
                    345:       SET_FLAG (message, ZAPI_MESSAGE_METRIC);
                    346: 
                    347:       /* Distance value. */
                    348:       distance = ospf_distance_apply (p, or);
                    349:       if (distance)
                    350:         SET_FLAG (message, ZAPI_MESSAGE_DISTANCE);
                    351: 
                    352:       /* Make packet. */
                    353:       s = zclient->obuf;
                    354:       stream_reset (s);
                    355: 
                    356:       /* Put command, type, flags, message. */
                    357:       zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD);
                    358:       stream_putc (s, ZEBRA_ROUTE_OSPF);
                    359:       stream_putc (s, flags);
                    360:       stream_putc (s, message);
1.1.1.2 ! misho     361:       stream_putw (s, SAFI_UNICAST);
1.1       misho     362: 
                    363:       /* Put prefix information. */
                    364:       psize = PSIZE (p->prefixlen);
                    365:       stream_putc (s, p->prefixlen);
                    366:       stream_write (s, (u_char *) & p->prefix, psize);
                    367: 
                    368:       /* Nexthop count. */
                    369:       stream_putc (s, or->paths->count);
                    370: 
                    371:       /* Nexthop, ifindex, distance and metric information. */
                    372:       for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
                    373:         {
                    374:           if (path->nexthop.s_addr != INADDR_ANY)
                    375:             {
                    376:               stream_putc (s, ZEBRA_NEXTHOP_IPV4);
                    377:               stream_put_in_addr (s, &path->nexthop);
                    378:             }
                    379:           else
                    380:             {
                    381:               stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
                    382:               if (path->ifindex)
                    383:                 stream_putl (s, path->ifindex);
                    384:               else
                    385:                 stream_putl (s, 0);
                    386:             }
                    387: 
                    388:           if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    389:             {
                    390:              char buf[2][INET_ADDRSTRLEN];
                    391:              zlog_debug("Zebra: Route add %s/%d nexthop %s",
                    392:                         inet_ntop(AF_INET, &p->prefix,
                    393:                                   buf[0], sizeof(buf[0])),
                    394:                         p->prefixlen,
                    395:                         inet_ntop(AF_INET, &path->nexthop,
                    396:                                   buf[1], sizeof(buf[1])));
                    397:             }
                    398:         }
                    399: 
                    400:       if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
                    401:         stream_putc (s, distance);
                    402:       if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
                    403:         {
                    404:           if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
                    405:             stream_putl (s, or->cost + or->u.ext.type2_cost);
                    406:           else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
                    407:             stream_putl (s, or->u.ext.type2_cost);
                    408:           else
                    409:             stream_putl (s, or->cost);
                    410:         }
                    411: 
                    412:       stream_putw_at (s, 0, stream_get_endp (s));
                    413: 
                    414:       zclient_send_message(zclient);
                    415:     }
                    416: }
                    417: 
                    418: void
                    419: ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
                    420: {
                    421:   struct zapi_ipv4 api;
                    422:   struct ospf_path *path;
                    423:   struct in_addr *nexthop;
                    424:   struct listnode *node, *nnode;
                    425: 
                    426:   if (zclient->redist[ZEBRA_ROUTE_OSPF])
                    427:     {
                    428:       api.type = ZEBRA_ROUTE_OSPF;
                    429:       api.flags = 0;
                    430:       api.message = 0;
1.1.1.2 ! misho     431:       api.safi = SAFI_UNICAST;
1.1       misho     432:       api.ifindex_num = 0;
                    433:       api.nexthop_num = 0;
                    434: 
                    435:       for (ALL_LIST_ELEMENTS (or->paths, node, nnode, path))
                    436:         {
                    437:           if (path->nexthop.s_addr != INADDR_ANY)
                    438:             {
                    439:               SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
                    440:               api.nexthop_num = 1;
                    441:               nexthop = &path->nexthop;
                    442:               api.nexthop = &nexthop;
                    443:             }
                    444:           else if (if_lookup_by_index(path->ifindex))
                    445:             {
                    446:               SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
                    447:               api.ifindex_num = 1;
                    448:               api.ifindex = &path->ifindex;
                    449:             }
                    450:           else if ( IS_DEBUG_OSPF(zebra,ZEBRA_REDISTRIBUTE) )
                    451:             {
                    452:               zlog_debug("Zebra: no ifp %s %d",
                    453:                          inet_ntoa(p->prefix),
                    454:                          p->prefixlen);
                    455:             }
                    456: 
                    457:           zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
                    458: 
                    459:           if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.nexthop_num)
                    460:             {
                    461:              char buf[2][INET_ADDRSTRLEN];
                    462:              zlog_debug("Zebra: Route delete %s/%d nexthop %s",
                    463:                         inet_ntop(AF_INET, &p->prefix, buf[0], sizeof(buf[0])),
                    464:                         p->prefixlen,
                    465:                         inet_ntop(AF_INET, *api.nexthop,
                    466:                                   buf[1], sizeof(buf[1])));
                    467:             }
                    468:           if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE) && api.ifindex_num)
                    469:             {
                    470:               zlog_debug ("Zebra: Route delete %s/%d ifindex %d",
                    471:                          inet_ntoa (p->prefix),
                    472:                          p->prefixlen, *api.ifindex);
                    473:             }
                    474:         }
                    475:     }
                    476: }
                    477: 
                    478: void
                    479: ospf_zebra_add_discard (struct prefix_ipv4 *p)
                    480: {
                    481:   struct zapi_ipv4 api;
                    482: 
                    483:   if (zclient->redist[ZEBRA_ROUTE_OSPF])
                    484:     {
                    485:       api.type = ZEBRA_ROUTE_OSPF;
                    486:       api.flags = ZEBRA_FLAG_BLACKHOLE;
                    487:       api.message = 0;
1.1.1.2 ! misho     488:       api.safi = SAFI_UNICAST;
1.1       misho     489:       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
                    490:       api.nexthop_num = 0;
                    491:       api.ifindex_num = 0;
                    492: 
                    493:       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
                    494: 
                    495:       if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    496:         zlog_debug ("Zebra: Route add discard %s/%d",
                    497:                    inet_ntoa (p->prefix), p->prefixlen);
                    498:     }
                    499: }
                    500: 
                    501: void
                    502: ospf_zebra_delete_discard (struct prefix_ipv4 *p)
                    503: {
                    504:   struct zapi_ipv4 api;
                    505: 
                    506:   if (zclient->redist[ZEBRA_ROUTE_OSPF])
                    507:     {
                    508:       api.type = ZEBRA_ROUTE_OSPF;
                    509:       api.flags = ZEBRA_FLAG_BLACKHOLE;
                    510:       api.message = 0;
1.1.1.2 ! misho     511:       api.safi = SAFI_UNICAST;
1.1       misho     512:       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
                    513:       api.nexthop_num = 0;
                    514:       api.ifindex_num = 0;
                    515: 
                    516:       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
                    517: 
                    518:       if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    519:         zlog_debug ("Zebra: Route delete discard %s/%d",
                    520:                    inet_ntoa (p->prefix), p->prefixlen);
                    521: 
                    522:     }
                    523: }
                    524: 
                    525: int
                    526: ospf_is_type_redistributed (int type)
                    527: {
                    528:   return (DEFAULT_ROUTE_TYPE (type)) ?
                    529:     zclient->default_information : zclient->redist[type];
                    530: }
                    531: 
                    532: int
                    533: ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue)
                    534: {
                    535:   int force = 0;
                    536: 
                    537:   if (ospf_is_type_redistributed (type))
                    538:     {
                    539:       if (mtype != ospf->dmetric[type].type)
                    540:         {
                    541:           ospf->dmetric[type].type = mtype;
                    542:           force = LSA_REFRESH_FORCE;
                    543:         }
                    544:       if (mvalue != ospf->dmetric[type].value)
                    545:         {
                    546:           ospf->dmetric[type].value = mvalue;
                    547:           force = LSA_REFRESH_FORCE;
                    548:         }
                    549: 
                    550:       ospf_external_lsa_refresh_type (ospf, type, force);
                    551: 
                    552:       if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    553:         zlog_debug ("Redistribute[%s]: Refresh  Type[%d], Metric[%d]",
                    554:                    ospf_redist_string(type),
                    555:                    metric_type (ospf, type), metric_value (ospf, type));
                    556: 
                    557:       return CMD_SUCCESS;
                    558:     }
                    559: 
                    560:   ospf->dmetric[type].type = mtype;
                    561:   ospf->dmetric[type].value = mvalue;
                    562: 
                    563:   zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
                    564: 
                    565:   if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    566:     zlog_debug ("Redistribute[%s]: Start  Type[%d], Metric[%d]",
                    567:                ospf_redist_string(type),
                    568:                metric_type (ospf, type), metric_value (ospf, type));
                    569: 
                    570:   ospf_asbr_status_update (ospf, ++ospf->redistribute);
                    571: 
                    572:   return CMD_SUCCESS;
                    573: }
                    574: 
                    575: int
                    576: ospf_redistribute_unset (struct ospf *ospf, int type)
                    577: {
                    578:   if (type == zclient->redist_default)
                    579:     return CMD_SUCCESS;
                    580: 
                    581:   if (!ospf_is_type_redistributed (type))
                    582:     return CMD_SUCCESS;
                    583: 
                    584:   zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
                    585: 
                    586:   if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    587:     zlog_debug ("Redistribute[%s]: Stop",
                    588:                ospf_redist_string(type));
                    589: 
                    590:   ospf->dmetric[type].type = -1;
                    591:   ospf->dmetric[type].value = -1;
                    592: 
                    593:   /* Remove the routes from OSPF table. */
                    594:   ospf_redistribute_withdraw (ospf, type);
                    595: 
                    596:   ospf_asbr_status_update (ospf, --ospf->redistribute);
                    597: 
                    598:   return CMD_SUCCESS;
                    599: }
                    600: 
                    601: int
                    602: ospf_redistribute_default_set (struct ospf *ospf, int originate,
                    603:                                int mtype, int mvalue)
                    604: {
                    605:   ospf->default_originate = originate;
                    606:   ospf->dmetric[DEFAULT_ROUTE].type = mtype;
                    607:   ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
                    608: 
                    609:   if (ospf_is_type_redistributed (DEFAULT_ROUTE))
                    610:     {
                    611:       /* if ospf->default_originate changes value, is calling
                    612:         ospf_external_lsa_refresh_default sufficient to implement
                    613:         the change? */
                    614:       ospf_external_lsa_refresh_default (ospf);
                    615: 
                    616:       if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    617:         zlog_debug ("Redistribute[%s]: Refresh  Type[%d], Metric[%d]",
                    618:                    ospf_redist_string(DEFAULT_ROUTE),
                    619:                    metric_type (ospf, DEFAULT_ROUTE),
                    620:                    metric_value (ospf, DEFAULT_ROUTE));
                    621:       return CMD_SUCCESS;
                    622:     }
                    623: 
                    624:   zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient);
                    625: 
                    626:   if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    627:     zlog_debug ("Redistribute[DEFAULT]: Start  Type[%d], Metric[%d]",
                    628:                metric_type (ospf, DEFAULT_ROUTE),
                    629:                metric_value (ospf, DEFAULT_ROUTE));
                    630: 
                    631:   if (ospf->router_id.s_addr == 0)
                    632:     ospf->external_origin |= (1 << DEFAULT_ROUTE);
                    633:   else
                    634:     thread_add_timer (master, ospf_default_originate_timer, ospf, 1);
                    635: 
                    636:   ospf_asbr_status_update (ospf, ++ospf->redistribute);
                    637: 
                    638:   return CMD_SUCCESS;
                    639: }
                    640: 
                    641: int
                    642: ospf_redistribute_default_unset (struct ospf *ospf)
                    643: {
                    644:   if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
                    645:     return CMD_SUCCESS;
                    646: 
                    647:   ospf->default_originate = DEFAULT_ORIGINATE_NONE;
                    648:   ospf->dmetric[DEFAULT_ROUTE].type = -1;
                    649:   ospf->dmetric[DEFAULT_ROUTE].value = -1;
                    650: 
                    651:   zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient);
                    652: 
                    653:   if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    654:     zlog_debug ("Redistribute[DEFAULT]: Stop");
                    655: 
                    656:   ospf_asbr_status_update (ospf, --ospf->redistribute);
                    657: 
                    658:   return CMD_SUCCESS;
                    659: }
                    660: 
                    661: static int
                    662: ospf_external_lsa_originate_check (struct ospf *ospf,
                    663:                                    struct external_info *ei)
                    664: {
                    665:   /* If prefix is multicast, then do not originate LSA. */
                    666:   if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
                    667:     {
                    668:       zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
                    669:                  "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
                    670:       return 0;
                    671:     }
                    672: 
                    673:   /* Take care of default-originate. */
                    674:   if (is_prefix_default (&ei->p))
                    675:     if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
                    676:       {
                    677:         zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA "
                    678:                    "for default");
                    679:         return 0;
                    680:       }
                    681: 
                    682:   return 1;
                    683: }
                    684: 
                    685: /* If connected prefix is OSPF enable interface, then do not announce. */
                    686: int
                    687: ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei)
                    688: {
                    689:   struct listnode *node;
                    690:   struct ospf_interface *oi;
                    691: 
                    692: 
                    693:   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
                    694:       if (prefix_match (oi->address, (struct prefix *) &ei->p))
                    695:           return 0;
                    696:   return 1;
                    697: }
                    698: 
                    699: /* return 1 if external LSA must be originated, 0 otherwise */
                    700: int
                    701: ospf_redistribute_check (struct ospf *ospf,
                    702:                          struct external_info *ei, int *changed)
                    703: {
                    704:   struct route_map_set_values save_values;
                    705:   struct prefix_ipv4 *p = &ei->p;
                    706:   u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
                    707: 
                    708:   if (changed)
                    709:     *changed = 0;
                    710: 
                    711:   if (!ospf_external_lsa_originate_check (ospf, ei))
                    712:     return 0;
                    713: 
                    714:   /* Take care connected route. */
                    715:   if (type == ZEBRA_ROUTE_CONNECT &&
                    716:       !ospf_distribute_check_connected (ospf, ei))
                    717:     return 0;
                    718: 
                    719:   if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type))
                    720:     /* distirbute-list exists, but access-list may not? */
                    721:     if (DISTRIBUTE_LIST (ospf, type))
                    722:       if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
                    723:         {
                    724:           if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    725:             zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
                    726:                        ospf_redist_string(type),
                    727:                        inet_ntoa (p->prefix), p->prefixlen);
                    728:           return 0;
                    729:         }
                    730: 
                    731:   save_values = ei->route_map_set;
                    732:   ospf_reset_route_map_set_values (&ei->route_map_set);
                    733: 
                    734:   /* apply route-map if needed */
                    735:   if (ROUTEMAP_NAME (ospf, type))
                    736:     {
                    737:       int ret;
                    738: 
                    739:       ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p,
                    740:                              RMAP_OSPF, ei);
                    741: 
                    742:       if (ret == RMAP_DENYMATCH)
                    743:         {
                    744:           ei->route_map_set = save_values;
                    745:           if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
                    746:             zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.",
                    747:                        ospf_redist_string(type),
                    748:                        inet_ntoa (p->prefix), p->prefixlen);
                    749:           return 0;
                    750:         }
                    751: 
                    752:       /* check if 'route-map set' changed something */
                    753:       if (changed)
                    754:         *changed = !ospf_route_map_set_compare (&ei->route_map_set,
                    755:                                                 &save_values);
                    756:     }
                    757: 
                    758:   return 1;
                    759: }
                    760: 
                    761: /* OSPF route-map set for redistribution */
                    762: void
                    763: ospf_routemap_set (struct ospf *ospf, int type, const char *name)
                    764: {
                    765:   if (ROUTEMAP_NAME (ospf, type))
                    766:     free (ROUTEMAP_NAME (ospf, type));
                    767: 
                    768:   ROUTEMAP_NAME (ospf, type) = strdup (name);
                    769:   ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);
                    770: }
                    771: 
                    772: void
                    773: ospf_routemap_unset (struct ospf *ospf, int type)
                    774: {
                    775:   if (ROUTEMAP_NAME (ospf, type))
                    776:     free (ROUTEMAP_NAME (ospf, type));
                    777: 
                    778:   ROUTEMAP_NAME (ospf, type) = NULL;
                    779:   ROUTEMAP (ospf, type) = NULL;
                    780: }
                    781: 
                    782: /* Zebra route add and delete treatment. */
                    783: static int
                    784: ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
                    785:                       zebra_size_t length)
                    786: {
                    787:   struct stream *s;
                    788:   struct zapi_ipv4 api;
                    789:   unsigned long ifindex;
                    790:   struct in_addr nexthop;
                    791:   struct prefix_ipv4 p;
                    792:   struct external_info *ei;
                    793:   struct ospf *ospf;
                    794: 
                    795:   s = zclient->ibuf;
                    796:   ifindex = 0;
                    797:   nexthop.s_addr = 0;
                    798: 
                    799:   /* Type, flags, message. */
                    800:   api.type = stream_getc (s);
                    801:   api.flags = stream_getc (s);
                    802:   api.message = stream_getc (s);
                    803: 
                    804:   /* IPv4 prefix. */
                    805:   memset (&p, 0, sizeof (struct prefix_ipv4));
                    806:   p.family = AF_INET;
                    807:   p.prefixlen = stream_getc (s);
                    808:   stream_get (&p.prefix, s, PSIZE (p.prefixlen));
                    809: 
                    810:   if (IPV4_NET127(ntohl(p.prefix.s_addr)))
                    811:     return 0;
                    812: 
                    813:   /* Nexthop, ifindex, distance, metric. */
                    814:   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
                    815:     {
                    816:       api.nexthop_num = stream_getc (s);
                    817:       nexthop.s_addr = stream_get_ipv4 (s);
                    818:     }
                    819:   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
                    820:     {
                    821:       api.ifindex_num = stream_getc (s);
                    822:       /* XXX assert(api.ifindex_num == 1); */
                    823:       ifindex = stream_getl (s);
                    824:     }
                    825:   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
                    826:     api.distance = stream_getc (s);
                    827:   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
                    828:     api.metric = stream_getl (s);
                    829: 
                    830:   ospf = ospf_lookup ();
                    831:   if (ospf == NULL)
                    832:     return 0;
                    833: 
                    834:   if (command == ZEBRA_IPV4_ROUTE_ADD)
                    835:     {
                    836:       /* XXX|HACK|TODO|FIXME:
                    837:        * Maybe we should ignore reject/blackhole routes? Testing shows that
                    838:        * there is no problems though and this is only way to "summarize"
                    839:        * routes in ASBR at the moment. Maybe we need just a better generalised
                    840:        * solution for these types?
                    841:        *
                    842:        * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE)
                    843:        *     || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
                    844:        * return 0;
                    845:        */
                    846:         
                    847:       ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
                    848: 
                    849:       if (ospf->router_id.s_addr == 0)
                    850:         /* Set flags to generate AS-external-LSA originate event
                    851:            for each redistributed protocols later. */
                    852:         ospf->external_origin |= (1 << api.type);
                    853:       else
                    854:         {
                    855:           if (ei)
                    856:             {
                    857:               if (is_prefix_default (&p))
                    858:                 ospf_external_lsa_refresh_default (ospf);
                    859:               else
                    860:                 {
                    861:                   struct ospf_lsa *current;
                    862: 
                    863:                   current = ospf_external_info_find_lsa (ospf, &ei->p);
                    864:                   if (!current)
                    865:                     ospf_external_lsa_originate (ospf, ei);
                    866:                   else if (IS_LSA_MAXAGE (current))
                    867:                     ospf_external_lsa_refresh (ospf, current,
                    868:                                                ei, LSA_REFRESH_FORCE);
                    869:                   else
                    870:                     zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
                    871:                                inet_ntoa (p.prefix));
                    872:                 }
                    873:             }
                    874:         }
                    875:     }
                    876:   else                          /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
                    877:     {
                    878:       ospf_external_info_delete (api.type, p);
                    879:       if (is_prefix_default (&p))
                    880:         ospf_external_lsa_refresh_default (ospf);
                    881:       else
                    882:         ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */);
                    883:     }
                    884: 
                    885:   return 0;
                    886: }
                    887: 
                    888: 
                    889: int
                    890: ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name)
                    891: {
                    892:   /* Lookup access-list for distribute-list. */
                    893:   DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
                    894: 
                    895:   /* Clear previous distribute-name. */
                    896:   if (DISTRIBUTE_NAME (ospf, type))
                    897:     free (DISTRIBUTE_NAME (ospf, type));
                    898: 
                    899:   /* Set distribute-name. */
                    900:   DISTRIBUTE_NAME (ospf, type) = strdup (name);
                    901: 
                    902:   /* If access-list have been set, schedule update timer. */
                    903:   if (DISTRIBUTE_LIST (ospf, type))
                    904:     ospf_distribute_list_update (ospf, type);
                    905: 
                    906:   return CMD_SUCCESS;
                    907: }
                    908: 
                    909: int
                    910: ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name)
                    911: {
                    912:   /* Schedule update timer. */
                    913:   if (DISTRIBUTE_LIST (ospf, type))
                    914:     ospf_distribute_list_update (ospf, type);
                    915: 
                    916:   /* Unset distribute-list. */
                    917:   DISTRIBUTE_LIST (ospf, type) = NULL;
                    918: 
                    919:   /* Clear distribute-name. */
                    920:   if (DISTRIBUTE_NAME (ospf, type))
                    921:     free (DISTRIBUTE_NAME (ospf, type));
                    922: 
                    923:   DISTRIBUTE_NAME (ospf, type) = NULL;
                    924: 
                    925:   return CMD_SUCCESS;
                    926: }
                    927: 
                    928: /* distribute-list update timer. */
                    929: static int
                    930: ospf_distribute_list_update_timer (struct thread *thread)
                    931: {
                    932:   struct route_node *rn;
                    933:   struct external_info *ei;
                    934:   struct route_table *rt;
                    935:   struct ospf_lsa *lsa;
                    936:   int type, default_refresh = 0;
                    937:   struct ospf *ospf;
                    938: 
                    939:   ospf = ospf_lookup ();
                    940:   if (ospf == NULL)
                    941:     return 0;
                    942: 
                    943:   ospf->t_distribute_update = NULL;
                    944: 
                    945:   zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
                    946: 
                    947:   /* foreach all external info. */
                    948:   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
                    949:     {
                    950:       rt = EXTERNAL_INFO (type);
                    951:       if (!rt)
                    952:        continue;
                    953:       for (rn = route_top (rt); rn; rn = route_next (rn))
                    954:        if ((ei = rn->info) != NULL)
                    955:          {
                    956:            if (is_prefix_default (&ei->p))
                    957:              default_refresh = 1;
                    958:            else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
                    959:              ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
                    960:            else
                    961:              ospf_external_lsa_originate (ospf, ei);
                    962:          }
                    963:     }
                    964:   if (default_refresh)
                    965:     ospf_external_lsa_refresh_default (ospf);
                    966:   return 0;
                    967: }
                    968: 
                    969: #define OSPF_DISTRIBUTE_UPDATE_DELAY 5
                    970: 
                    971: /* Update distribute-list and set timer to apply access-list. */
                    972: void
                    973: ospf_distribute_list_update (struct ospf *ospf, int type)
                    974: {
                    975:   struct route_table *rt;
                    976: 
                    977:   /* External info does not exist. */
                    978:   if (!(rt = EXTERNAL_INFO (type)))
                    979:     return;
                    980: 
                    981:   /* If exists previously invoked thread, then let it continue. */
                    982:   if (ospf->t_distribute_update)
                    983:     return;
                    984: 
                    985:   /* Set timer. */
                    986:   ospf->t_distribute_update =
                    987:     thread_add_timer (master, ospf_distribute_list_update_timer,
                    988:                       (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
                    989: }
                    990: 
                    991: /* If access-list is updated, apply some check. */
                    992: static void
                    993: ospf_filter_update (struct access_list *access)
                    994: {
                    995:   struct ospf *ospf;
                    996:   int type;
                    997:   int abr_inv = 0;
                    998:   struct ospf_area *area;
                    999:   struct listnode *node;
                   1000: 
                   1001:   /* If OSPF instatnce does not exist, return right now. */
                   1002:   ospf = ospf_lookup ();
                   1003:   if (ospf == NULL)
                   1004:     return;
                   1005: 
                   1006:   /* Update distribute-list, and apply filter. */
                   1007:   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
                   1008:     {
                   1009:       if (ROUTEMAP (ospf, type) != NULL)
                   1010:         {
                   1011:           /* if route-map is not NULL it may be using this access list */
                   1012:           ospf_distribute_list_update (ospf, type);
                   1013:           continue;
                   1014:         }
                   1015: 
                   1016:       /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX),
                   1017:        * but no distribute list. */
                   1018:       if (type == ZEBRA_ROUTE_MAX)
                   1019:        break;
                   1020: 
                   1021:       if (DISTRIBUTE_NAME (ospf, type))
                   1022:         {
                   1023:           /* Keep old access-list for distribute-list. */
                   1024:           struct access_list *old = DISTRIBUTE_LIST (ospf, type);
                   1025: 
                   1026:           /* Update access-list for distribute-list. */
                   1027:           DISTRIBUTE_LIST (ospf, type) =
                   1028:             access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type));
                   1029: 
                   1030:           /* No update for this distribute type. */
                   1031:           if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL)
                   1032:             continue;
                   1033: 
                   1034:           /* Schedule distribute-list update timer. */
                   1035:           if (DISTRIBUTE_LIST (ospf, type) == NULL ||
                   1036:               strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
                   1037:             ospf_distribute_list_update (ospf, type);
                   1038:         }
                   1039:     }
                   1040: 
                   1041:   /* Update Area access-list. */
                   1042:   for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
                   1043:     {
                   1044:       if (EXPORT_NAME (area))
                   1045:         {
                   1046:           EXPORT_LIST (area) = NULL;
                   1047:           abr_inv++;
                   1048:         }
                   1049: 
                   1050:       if (IMPORT_NAME (area))
                   1051:         {
                   1052:           IMPORT_LIST (area) = NULL;
                   1053:           abr_inv++;
                   1054:         }
                   1055:     }
                   1056: 
                   1057:   /* Schedule ABR tasks -- this will be changed -- takada. */
                   1058:   if (IS_OSPF_ABR (ospf) && abr_inv)
                   1059:     ospf_schedule_abr_task (ospf);
                   1060: }
                   1061: 
                   1062: /* If prefix-list is updated, do some updates. */
                   1063: void
                   1064: ospf_prefix_list_update (struct prefix_list *plist)
                   1065: {
                   1066:   struct ospf *ospf;
                   1067:   int type;
                   1068:   int abr_inv = 0;
                   1069:   struct ospf_area *area;
                   1070:   struct listnode *node;
                   1071: 
                   1072:   /* If OSPF instatnce does not exist, return right now. */
                   1073:   ospf = ospf_lookup ();
                   1074:   if (ospf == NULL)
                   1075:     return;
                   1076: 
                   1077:   /* Update all route-maps which are used as redistribution filters.
                   1078:    * They might use prefix-list.
                   1079:    */
                   1080:   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
                   1081:     {
                   1082:       if (ROUTEMAP (ospf, type) != NULL)
                   1083:         {
                   1084:           /* If route-map is not NULL it may be using this prefix list */
                   1085:           ospf_distribute_list_update (ospf, type);
                   1086:           continue;
                   1087:         }
                   1088:     }
                   1089: 
                   1090:   /* Update area filter-lists. */
                   1091:   for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
                   1092:     {
                   1093:       /* Update filter-list in. */
                   1094:       if (PREFIX_NAME_IN (area))
                   1095:         if (strcmp (PREFIX_NAME_IN (area), plist->name) == 0)
                   1096:           {
                   1097:             PREFIX_LIST_IN (area) =
                   1098:               prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
                   1099:             abr_inv++;
                   1100:           }
                   1101: 
                   1102:       /* Update filter-list out. */
                   1103:       if (PREFIX_NAME_OUT (area))
                   1104:         if (strcmp (PREFIX_NAME_OUT (area), plist->name) == 0)
                   1105:           {
                   1106:             PREFIX_LIST_IN (area) =
                   1107:               prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
                   1108:             abr_inv++;
                   1109:           }
                   1110:     }
                   1111: 
                   1112:   /* Schedule ABR task. */
                   1113:   if (IS_OSPF_ABR (ospf) && abr_inv)
                   1114:     ospf_schedule_abr_task (ospf);
                   1115: }
                   1116: 
                   1117: static struct ospf_distance *
                   1118: ospf_distance_new (void)
                   1119: {
                   1120:   return XCALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
                   1121: }
                   1122: 
                   1123: static void
                   1124: ospf_distance_free (struct ospf_distance *odistance)
                   1125: {
                   1126:   XFREE (MTYPE_OSPF_DISTANCE, odistance);
                   1127: }
                   1128: 
                   1129: int
                   1130: ospf_distance_set (struct vty *vty, struct ospf *ospf, 
                   1131:                    const char *distance_str,
                   1132:                    const char *ip_str, 
                   1133:                    const char *access_list_str)
                   1134: {
                   1135:   int ret;
                   1136:   struct prefix_ipv4 p;
                   1137:   u_char distance;
                   1138:   struct route_node *rn;
                   1139:   struct ospf_distance *odistance;
                   1140: 
                   1141:   ret = str2prefix_ipv4 (ip_str, &p);
                   1142:   if (ret == 0)
                   1143:     {
                   1144:       vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
                   1145:       return CMD_WARNING;
                   1146:     }
                   1147: 
                   1148:   distance = atoi (distance_str);
                   1149: 
                   1150:   /* Get OSPF distance node. */
                   1151:   rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
                   1152:   if (rn->info)
                   1153:     {
                   1154:       odistance = rn->info;
                   1155:       route_unlock_node (rn);
                   1156:     }
                   1157:   else
                   1158:     {
                   1159:       odistance = ospf_distance_new ();
                   1160:       rn->info = odistance;
                   1161:     }
                   1162: 
                   1163:   /* Set distance value. */
                   1164:   odistance->distance = distance;
                   1165: 
                   1166:   /* Reset access-list configuration. */
                   1167:   if (odistance->access_list)
                   1168:     {
                   1169:       free (odistance->access_list);
                   1170:       odistance->access_list = NULL;
                   1171:     }
                   1172:   if (access_list_str)
                   1173:     odistance->access_list = strdup (access_list_str);
                   1174: 
                   1175:   return CMD_SUCCESS;
                   1176: }
                   1177: 
                   1178: int
                   1179: ospf_distance_unset (struct vty *vty, struct ospf *ospf, 
                   1180:                      const char *distance_str,
                   1181:                      const char *ip_str, char 
                   1182:                      const *access_list_str)
                   1183: {
                   1184:   int ret;
                   1185:   struct prefix_ipv4 p;
                   1186:   u_char distance;
                   1187:   struct route_node *rn;
                   1188:   struct ospf_distance *odistance;
                   1189: 
                   1190:   ret = str2prefix_ipv4 (ip_str, &p);
                   1191:   if (ret == 0)
                   1192:     {
                   1193:       vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
                   1194:       return CMD_WARNING;
                   1195:     }
                   1196: 
                   1197:   distance = atoi (distance_str);
                   1198: 
                   1199:   rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p);
                   1200:   if (!rn)
                   1201:     {
                   1202:       vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
                   1203:       return CMD_WARNING;
                   1204:     }
                   1205: 
                   1206:   odistance = rn->info;
                   1207: 
                   1208:   if (odistance->access_list)
                   1209:     free (odistance->access_list);
                   1210:   ospf_distance_free (odistance);
                   1211: 
                   1212:   rn->info = NULL;
                   1213:   route_unlock_node (rn);
                   1214:   route_unlock_node (rn);
                   1215: 
                   1216:   return CMD_SUCCESS;
                   1217: }
                   1218: 
                   1219: void
                   1220: ospf_distance_reset (struct ospf *ospf)
                   1221: {
                   1222:   struct route_node *rn;
                   1223:   struct ospf_distance *odistance;
                   1224: 
                   1225:   for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
                   1226:     if ((odistance = rn->info) != NULL)
                   1227:       {
                   1228:         if (odistance->access_list)
                   1229:           free (odistance->access_list);
                   1230:         ospf_distance_free (odistance);
                   1231:         rn->info = NULL;
                   1232:         route_unlock_node (rn);
                   1233:       }
                   1234: }
                   1235: 
                   1236: u_char
                   1237: ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
                   1238: {
                   1239:   struct ospf *ospf;
                   1240: 
                   1241:   ospf = ospf_lookup ();
                   1242:   if (ospf == NULL)
                   1243:     return 0;
                   1244: 
                   1245:   if (ospf->distance_intra)
                   1246:     if (or->path_type == OSPF_PATH_INTRA_AREA)
                   1247:       return ospf->distance_intra;
                   1248: 
                   1249:   if (ospf->distance_inter)
                   1250:     if (or->path_type == OSPF_PATH_INTER_AREA)
                   1251:       return ospf->distance_inter;
                   1252: 
                   1253:   if (ospf->distance_external)
                   1254:     if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
                   1255:         || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
                   1256:       return ospf->distance_external;
                   1257: 
                   1258:   if (ospf->distance_all)
                   1259:     return ospf->distance_all;
                   1260: 
                   1261:   return 0;
                   1262: }
                   1263: 
                   1264: void
                   1265: ospf_zebra_init ()
                   1266: {
                   1267:   /* Allocate zebra structure. */
                   1268:   zclient = zclient_new ();
                   1269:   zclient_init (zclient, ZEBRA_ROUTE_OSPF);
                   1270:   zclient->router_id_update = ospf_router_id_update_zebra;
                   1271:   zclient->interface_add = ospf_interface_add;
                   1272:   zclient->interface_delete = ospf_interface_delete;
                   1273:   zclient->interface_up = ospf_interface_state_up;
                   1274:   zclient->interface_down = ospf_interface_state_down;
                   1275:   zclient->interface_address_add = ospf_interface_address_add;
                   1276:   zclient->interface_address_delete = ospf_interface_address_delete;
                   1277:   zclient->ipv4_route_add = ospf_zebra_read_ipv4;
                   1278:   zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
                   1279: 
                   1280:   access_list_add_hook (ospf_filter_update);
                   1281:   access_list_delete_hook (ospf_filter_update);
                   1282:   prefix_list_add_hook (ospf_prefix_list_update);
                   1283:   prefix_list_delete_hook (ospf_prefix_list_update);
                   1284: }

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