File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospfd / ospf_zebra.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:12 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

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