File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ospfd / ospf_zebra.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:40 2013 UTC (11 years ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    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 %llx metric %d mtu %d",
  137:        ifp->name, ifp->ifindex, (unsigned long long)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);
  361:       stream_putw (s, SAFI_UNICAST);
  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: 	      path->ifindex != 0)
  376:             {
  377:               stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
  378:               stream_put_in_addr (s, &path->nexthop);
  379: 	      stream_putl (s, path->ifindex);
  380:             }
  381:           else if (path->nexthop.s_addr != INADDR_ANY)
  382:             {
  383:               stream_putc (s, ZEBRA_NEXTHOP_IPV4);
  384:               stream_put_in_addr (s, &path->nexthop);
  385:             }
  386:           else
  387:             {
  388:               stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
  389:               if (path->ifindex)
  390:                 stream_putl (s, path->ifindex);
  391:               else
  392:                 stream_putl (s, 0);
  393:             }
  394: 
  395:           if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  396:             {
  397: 	      char buf[2][INET_ADDRSTRLEN];
  398: 	      zlog_debug("Zebra: Route add %s/%d nexthop %s",
  399: 			 inet_ntop(AF_INET, &p->prefix,
  400: 				   buf[0], sizeof(buf[0])),
  401: 			 p->prefixlen,
  402: 			 inet_ntop(AF_INET, &path->nexthop,
  403: 				   buf[1], sizeof(buf[1])));
  404:             }
  405:         }
  406: 
  407:       if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
  408:         stream_putc (s, distance);
  409:       if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
  410:         {
  411:           if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
  412:             stream_putl (s, or->cost + or->u.ext.type2_cost);
  413:           else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
  414:             stream_putl (s, or->u.ext.type2_cost);
  415:           else
  416:             stream_putl (s, or->cost);
  417:         }
  418: 
  419:       stream_putw_at (s, 0, stream_get_endp (s));
  420: 
  421:       zclient_send_message(zclient);
  422:     }
  423: }
  424: 
  425: void
  426: ospf_zebra_delete (struct prefix_ipv4 *p, struct ospf_route *or)
  427: {
  428:   u_char message;
  429:   u_char distance;
  430:   u_char flags;
  431:   int psize;
  432:   struct stream *s;
  433:   struct ospf_path *path;
  434:   struct listnode *node;
  435: 
  436:   if (zclient->redist[ZEBRA_ROUTE_OSPF])
  437:     {
  438:       message = 0;
  439:       flags = 0;
  440:       /* Distance value. */
  441:       distance = ospf_distance_apply (p, or);
  442:       /* Make packet. */
  443:       s = zclient->obuf;
  444:       stream_reset (s);
  445: 
  446:       /* Put command, type, flags, message. */
  447:       zclient_create_header (s, ZEBRA_IPV4_ROUTE_DELETE);
  448:       stream_putc (s, ZEBRA_ROUTE_OSPF);
  449:       stream_putc (s, flags);
  450:       stream_putc (s, message);
  451:       stream_putw (s, SAFI_UNICAST);
  452: 
  453:       /* Put prefix information. */
  454:       psize = PSIZE (p->prefixlen);
  455:       stream_putc (s, p->prefixlen);
  456:       stream_write (s, (u_char *) & p->prefix, psize);
  457: 
  458:       /* Nexthop count. */
  459:       stream_putc (s, or->paths->count);
  460: 
  461:       /* Nexthop, ifindex, distance and metric information. */
  462:       for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
  463: 	{
  464: 	  if (path->nexthop.s_addr != INADDR_ANY &&
  465: 	      path->ifindex != 0)
  466: 	    {
  467: 	      stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
  468: 	      stream_put_in_addr (s, &path->nexthop);
  469: 	      stream_putl (s, path->ifindex);
  470: 	    }
  471: 	  else if (path->nexthop.s_addr != INADDR_ANY)
  472: 	    {
  473: 	      stream_putc (s, ZEBRA_NEXTHOP_IPV4);
  474: 	      stream_put_in_addr (s, &path->nexthop);
  475: 	    }
  476: 	  else
  477: 	    {
  478: 	      stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
  479: 	      stream_putl (s, path->ifindex);
  480: 	    }
  481: 
  482: 	  if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  483: 	    {
  484: 	      char buf[2][INET_ADDRSTRLEN];
  485: 	      zlog_debug("Zebra: Route add %s/%d nexthop %s",
  486: 			 inet_ntop(AF_INET, &p->prefix,
  487: 				   buf[0], sizeof(buf[0])),
  488: 			 p->prefixlen,
  489: 			 inet_ntop(AF_INET, &path->nexthop,
  490: 				   buf[1], sizeof(buf[1])));
  491: 	    }
  492: 	}
  493: 
  494:       if (CHECK_FLAG (message, ZAPI_MESSAGE_DISTANCE))
  495: 	stream_putc (s, distance);
  496:       if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
  497: 	{
  498: 	  if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
  499: 	    stream_putl (s, or->cost + or->u.ext.type2_cost);
  500: 	  else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
  501: 	    stream_putl (s, or->u.ext.type2_cost);
  502: 	  else
  503: 	    stream_putl (s, or->cost);
  504: 	}
  505: 
  506:       stream_putw_at (s, 0, stream_get_endp (s));
  507: 
  508:       zclient_send_message(zclient);
  509:     }
  510: }
  511: 
  512: void
  513: ospf_zebra_add_discard (struct prefix_ipv4 *p)
  514: {
  515:   struct zapi_ipv4 api;
  516: 
  517:   if (zclient->redist[ZEBRA_ROUTE_OSPF])
  518:     {
  519:       api.type = ZEBRA_ROUTE_OSPF;
  520:       api.flags = ZEBRA_FLAG_BLACKHOLE;
  521:       api.message = 0;
  522:       api.safi = SAFI_UNICAST;
  523:       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
  524:       api.nexthop_num = 0;
  525:       api.ifindex_num = 0;
  526: 
  527:       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api);
  528: 
  529:       if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  530:         zlog_debug ("Zebra: Route add discard %s/%d",
  531:                    inet_ntoa (p->prefix), p->prefixlen);
  532:     }
  533: }
  534: 
  535: void
  536: ospf_zebra_delete_discard (struct prefix_ipv4 *p)
  537: {
  538:   struct zapi_ipv4 api;
  539: 
  540:   if (zclient->redist[ZEBRA_ROUTE_OSPF])
  541:     {
  542:       api.type = ZEBRA_ROUTE_OSPF;
  543:       api.flags = ZEBRA_FLAG_BLACKHOLE;
  544:       api.message = 0;
  545:       api.safi = SAFI_UNICAST;
  546:       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
  547:       api.nexthop_num = 0;
  548:       api.ifindex_num = 0;
  549: 
  550:       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
  551: 
  552:       if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  553:         zlog_debug ("Zebra: Route delete discard %s/%d",
  554:                    inet_ntoa (p->prefix), p->prefixlen);
  555: 
  556:     }
  557: }
  558: 
  559: int
  560: ospf_is_type_redistributed (int type)
  561: {
  562:   return (DEFAULT_ROUTE_TYPE (type)) ?
  563:     zclient->default_information : zclient->redist[type];
  564: }
  565: 
  566: int
  567: ospf_redistribute_set (struct ospf *ospf, int type, int mtype, int mvalue)
  568: {
  569:   int force = 0;
  570: 
  571:   if (ospf_is_type_redistributed (type))
  572:     {
  573:       if (mtype != ospf->dmetric[type].type)
  574:         {
  575:           ospf->dmetric[type].type = mtype;
  576:           force = LSA_REFRESH_FORCE;
  577:         }
  578:       if (mvalue != ospf->dmetric[type].value)
  579:         {
  580:           ospf->dmetric[type].value = mvalue;
  581:           force = LSA_REFRESH_FORCE;
  582:         }
  583: 
  584:       ospf_external_lsa_refresh_type (ospf, type, force);
  585: 
  586:       if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  587:         zlog_debug ("Redistribute[%s]: Refresh  Type[%d], Metric[%d]",
  588:                    ospf_redist_string(type),
  589:                    metric_type (ospf, type), metric_value (ospf, type));
  590: 
  591:       return CMD_SUCCESS;
  592:     }
  593: 
  594:   ospf->dmetric[type].type = mtype;
  595:   ospf->dmetric[type].value = mvalue;
  596: 
  597:   zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, type);
  598: 
  599:   if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  600:     zlog_debug ("Redistribute[%s]: Start  Type[%d], Metric[%d]",
  601:                ospf_redist_string(type),
  602:                metric_type (ospf, type), metric_value (ospf, type));
  603: 
  604:   ospf_asbr_status_update (ospf, ++ospf->redistribute);
  605: 
  606:   return CMD_SUCCESS;
  607: }
  608: 
  609: int
  610: ospf_redistribute_unset (struct ospf *ospf, int type)
  611: {
  612:   if (type == zclient->redist_default)
  613:     return CMD_SUCCESS;
  614: 
  615:   if (!ospf_is_type_redistributed (type))
  616:     return CMD_SUCCESS;
  617: 
  618:   zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, type);
  619: 
  620:   if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  621:     zlog_debug ("Redistribute[%s]: Stop",
  622:                ospf_redist_string(type));
  623: 
  624:   ospf->dmetric[type].type = -1;
  625:   ospf->dmetric[type].value = -1;
  626: 
  627:   /* Remove the routes from OSPF table. */
  628:   ospf_redistribute_withdraw (ospf, type);
  629: 
  630:   ospf_asbr_status_update (ospf, --ospf->redistribute);
  631: 
  632:   return CMD_SUCCESS;
  633: }
  634: 
  635: int
  636: ospf_redistribute_default_set (struct ospf *ospf, int originate,
  637:                                int mtype, int mvalue)
  638: {
  639:   ospf->default_originate = originate;
  640:   ospf->dmetric[DEFAULT_ROUTE].type = mtype;
  641:   ospf->dmetric[DEFAULT_ROUTE].value = mvalue;
  642: 
  643:   if (ospf_is_type_redistributed (DEFAULT_ROUTE))
  644:     {
  645:       /* if ospf->default_originate changes value, is calling
  646: 	 ospf_external_lsa_refresh_default sufficient to implement
  647: 	 the change? */
  648:       ospf_external_lsa_refresh_default (ospf);
  649: 
  650:       if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  651:         zlog_debug ("Redistribute[%s]: Refresh  Type[%d], Metric[%d]",
  652:                    ospf_redist_string(DEFAULT_ROUTE),
  653:                    metric_type (ospf, DEFAULT_ROUTE),
  654:                    metric_value (ospf, DEFAULT_ROUTE));
  655:       return CMD_SUCCESS;
  656:     }
  657: 
  658:   zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient);
  659: 
  660:   if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  661:     zlog_debug ("Redistribute[DEFAULT]: Start  Type[%d], Metric[%d]",
  662:                metric_type (ospf, DEFAULT_ROUTE),
  663:                metric_value (ospf, DEFAULT_ROUTE));
  664: 
  665:   if (ospf->router_id.s_addr == 0)
  666:     ospf->external_origin |= (1 << DEFAULT_ROUTE);
  667:   else
  668:     thread_add_timer (master, ospf_default_originate_timer, ospf, 1);
  669: 
  670:   ospf_asbr_status_update (ospf, ++ospf->redistribute);
  671: 
  672:   return CMD_SUCCESS;
  673: }
  674: 
  675: int
  676: ospf_redistribute_default_unset (struct ospf *ospf)
  677: {
  678:   if (!ospf_is_type_redistributed (DEFAULT_ROUTE))
  679:     return CMD_SUCCESS;
  680: 
  681:   ospf->default_originate = DEFAULT_ORIGINATE_NONE;
  682:   ospf->dmetric[DEFAULT_ROUTE].type = -1;
  683:   ospf->dmetric[DEFAULT_ROUTE].value = -1;
  684: 
  685:   zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient);
  686: 
  687:   if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  688:     zlog_debug ("Redistribute[DEFAULT]: Stop");
  689: 
  690:   ospf_asbr_status_update (ospf, --ospf->redistribute);
  691: 
  692:   return CMD_SUCCESS;
  693: }
  694: 
  695: static int
  696: ospf_external_lsa_originate_check (struct ospf *ospf,
  697:                                    struct external_info *ei)
  698: {
  699:   /* If prefix is multicast, then do not originate LSA. */
  700:   if (IN_MULTICAST (htonl (ei->p.prefix.s_addr)))
  701:     {
  702:       zlog_info ("LSA[Type5:%s]: Not originate AS-external-LSA, "
  703:                  "Prefix belongs multicast", inet_ntoa (ei->p.prefix));
  704:       return 0;
  705:     }
  706: 
  707:   /* Take care of default-originate. */
  708:   if (is_prefix_default (&ei->p))
  709:     if (ospf->default_originate == DEFAULT_ORIGINATE_NONE)
  710:       {
  711:         zlog_info ("LSA[Type5:0.0.0.0]: Not originate AS-external-LSA "
  712:                    "for default");
  713:         return 0;
  714:       }
  715: 
  716:   return 1;
  717: }
  718: 
  719: /* If connected prefix is OSPF enable interface, then do not announce. */
  720: int
  721: ospf_distribute_check_connected (struct ospf *ospf, struct external_info *ei)
  722: {
  723:   struct listnode *node;
  724:   struct ospf_interface *oi;
  725: 
  726: 
  727:   for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
  728:       if (prefix_match (oi->address, (struct prefix *) &ei->p))
  729:           return 0;
  730:   return 1;
  731: }
  732: 
  733: /* return 1 if external LSA must be originated, 0 otherwise */
  734: int
  735: ospf_redistribute_check (struct ospf *ospf,
  736:                          struct external_info *ei, int *changed)
  737: {
  738:   struct route_map_set_values save_values;
  739:   struct prefix_ipv4 *p = &ei->p;
  740:   u_char type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type;
  741: 
  742:   if (changed)
  743:     *changed = 0;
  744: 
  745:   if (!ospf_external_lsa_originate_check (ospf, ei))
  746:     return 0;
  747: 
  748:   /* Take care connected route. */
  749:   if (type == ZEBRA_ROUTE_CONNECT &&
  750:       !ospf_distribute_check_connected (ospf, ei))
  751:     return 0;
  752: 
  753:   if (!DEFAULT_ROUTE_TYPE (type) && DISTRIBUTE_NAME (ospf, type))
  754:     /* distirbute-list exists, but access-list may not? */
  755:     if (DISTRIBUTE_LIST (ospf, type))
  756:       if (access_list_apply (DISTRIBUTE_LIST (ospf, type), p) == FILTER_DENY)
  757:         {
  758:           if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  759:             zlog_debug ("Redistribute[%s]: %s/%d filtered by ditribute-list.",
  760:                        ospf_redist_string(type),
  761:                        inet_ntoa (p->prefix), p->prefixlen);
  762:           return 0;
  763:         }
  764: 
  765:   save_values = ei->route_map_set;
  766:   ospf_reset_route_map_set_values (&ei->route_map_set);
  767: 
  768:   /* apply route-map if needed */
  769:   if (ROUTEMAP_NAME (ospf, type))
  770:     {
  771:       int ret;
  772: 
  773:       ret = route_map_apply (ROUTEMAP (ospf, type), (struct prefix *) p,
  774:                              RMAP_OSPF, ei);
  775: 
  776:       if (ret == RMAP_DENYMATCH)
  777:         {
  778:           ei->route_map_set = save_values;
  779:           if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
  780:             zlog_debug ("Redistribute[%s]: %s/%d filtered by route-map.",
  781:                        ospf_redist_string(type),
  782:                        inet_ntoa (p->prefix), p->prefixlen);
  783:           return 0;
  784:         }
  785: 
  786:       /* check if 'route-map set' changed something */
  787:       if (changed)
  788:         *changed = !ospf_route_map_set_compare (&ei->route_map_set,
  789:                                                 &save_values);
  790:     }
  791: 
  792:   return 1;
  793: }
  794: 
  795: /* OSPF route-map set for redistribution */
  796: void
  797: ospf_routemap_set (struct ospf *ospf, int type, const char *name)
  798: {
  799:   if (ROUTEMAP_NAME (ospf, type))
  800:     free (ROUTEMAP_NAME (ospf, type));
  801: 
  802:   ROUTEMAP_NAME (ospf, type) = strdup (name);
  803:   ROUTEMAP (ospf, type) = route_map_lookup_by_name (name);
  804: }
  805: 
  806: void
  807: ospf_routemap_unset (struct ospf *ospf, int type)
  808: {
  809:   if (ROUTEMAP_NAME (ospf, type))
  810:     free (ROUTEMAP_NAME (ospf, type));
  811: 
  812:   ROUTEMAP_NAME (ospf, type) = NULL;
  813:   ROUTEMAP (ospf, type) = NULL;
  814: }
  815: 
  816: /* Zebra route add and delete treatment. */
  817: static int
  818: ospf_zebra_read_ipv4 (int command, struct zclient *zclient,
  819:                       zebra_size_t length)
  820: {
  821:   struct stream *s;
  822:   struct zapi_ipv4 api;
  823:   unsigned long ifindex;
  824:   struct in_addr nexthop;
  825:   struct prefix_ipv4 p;
  826:   struct external_info *ei;
  827:   struct ospf *ospf;
  828: 
  829:   s = zclient->ibuf;
  830:   ifindex = 0;
  831:   nexthop.s_addr = 0;
  832: 
  833:   /* Type, flags, message. */
  834:   api.type = stream_getc (s);
  835:   api.flags = stream_getc (s);
  836:   api.message = stream_getc (s);
  837: 
  838:   /* IPv4 prefix. */
  839:   memset (&p, 0, sizeof (struct prefix_ipv4));
  840:   p.family = AF_INET;
  841:   p.prefixlen = stream_getc (s);
  842:   stream_get (&p.prefix, s, PSIZE (p.prefixlen));
  843: 
  844:   if (IPV4_NET127(ntohl(p.prefix.s_addr)))
  845:     return 0;
  846: 
  847:   /* Nexthop, ifindex, distance, metric. */
  848:   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
  849:     {
  850:       api.nexthop_num = stream_getc (s);
  851:       nexthop.s_addr = stream_get_ipv4 (s);
  852:     }
  853:   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
  854:     {
  855:       api.ifindex_num = stream_getc (s);
  856:       /* XXX assert(api.ifindex_num == 1); */
  857:       ifindex = stream_getl (s);
  858:     }
  859:   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
  860:     api.distance = stream_getc (s);
  861:   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
  862:     api.metric = stream_getl (s);
  863: 
  864:   ospf = ospf_lookup ();
  865:   if (ospf == NULL)
  866:     return 0;
  867: 
  868:   if (command == ZEBRA_IPV4_ROUTE_ADD)
  869:     {
  870:       /* XXX|HACK|TODO|FIXME:
  871:        * Maybe we should ignore reject/blackhole routes? Testing shows that
  872:        * there is no problems though and this is only way to "summarize"
  873:        * routes in ASBR at the moment. Maybe we need just a better generalised
  874:        * solution for these types?
  875:        *
  876:        * if ( CHECK_FLAG (api.flags, ZEBRA_FLAG_BLACKHOLE)
  877:        *     || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT))
  878:        * return 0;
  879:        */
  880:         
  881:       ei = ospf_external_info_add (api.type, p, ifindex, nexthop);
  882: 
  883:       if (ospf->router_id.s_addr == 0)
  884:         /* Set flags to generate AS-external-LSA originate event
  885:            for each redistributed protocols later. */
  886:         ospf->external_origin |= (1 << api.type);
  887:       else
  888:         {
  889:           if (ei)
  890:             {
  891:               if (is_prefix_default (&p))
  892:                 ospf_external_lsa_refresh_default (ospf);
  893:               else
  894:                 {
  895:                   struct ospf_lsa *current;
  896: 
  897:                   current = ospf_external_info_find_lsa (ospf, &ei->p);
  898:                   if (!current)
  899:                     ospf_external_lsa_originate (ospf, ei);
  900:                   else if (IS_LSA_MAXAGE (current))
  901:                     ospf_external_lsa_refresh (ospf, current,
  902:                                                ei, LSA_REFRESH_FORCE);
  903:                   else
  904:                     zlog_warn ("ospf_zebra_read_ipv4() : %s already exists",
  905:                                inet_ntoa (p.prefix));
  906:                 }
  907:             }
  908:         }
  909:     }
  910:   else                          /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
  911:     {
  912:       ospf_external_info_delete (api.type, p);
  913:       if (is_prefix_default (&p))
  914:         ospf_external_lsa_refresh_default (ospf);
  915:       else
  916:         ospf_external_lsa_flush (ospf, api.type, &p, ifindex /*, nexthop */);
  917:     }
  918: 
  919:   return 0;
  920: }
  921: 
  922: 
  923: int
  924: ospf_distribute_list_out_set (struct ospf *ospf, int type, const char *name)
  925: {
  926:   /* Lookup access-list for distribute-list. */
  927:   DISTRIBUTE_LIST (ospf, type) = access_list_lookup (AFI_IP, name);
  928: 
  929:   /* Clear previous distribute-name. */
  930:   if (DISTRIBUTE_NAME (ospf, type))
  931:     free (DISTRIBUTE_NAME (ospf, type));
  932: 
  933:   /* Set distribute-name. */
  934:   DISTRIBUTE_NAME (ospf, type) = strdup (name);
  935: 
  936:   /* If access-list have been set, schedule update timer. */
  937:   if (DISTRIBUTE_LIST (ospf, type))
  938:     ospf_distribute_list_update (ospf, type);
  939: 
  940:   return CMD_SUCCESS;
  941: }
  942: 
  943: int
  944: ospf_distribute_list_out_unset (struct ospf *ospf, int type, const char *name)
  945: {
  946:   /* Schedule update timer. */
  947:   if (DISTRIBUTE_LIST (ospf, type))
  948:     ospf_distribute_list_update (ospf, type);
  949: 
  950:   /* Unset distribute-list. */
  951:   DISTRIBUTE_LIST (ospf, type) = NULL;
  952: 
  953:   /* Clear distribute-name. */
  954:   if (DISTRIBUTE_NAME (ospf, type))
  955:     free (DISTRIBUTE_NAME (ospf, type));
  956: 
  957:   DISTRIBUTE_NAME (ospf, type) = NULL;
  958: 
  959:   return CMD_SUCCESS;
  960: }
  961: 
  962: /* distribute-list update timer. */
  963: static int
  964: ospf_distribute_list_update_timer (struct thread *thread)
  965: {
  966:   struct route_node *rn;
  967:   struct external_info *ei;
  968:   struct route_table *rt;
  969:   struct ospf_lsa *lsa;
  970:   int type, default_refresh = 0;
  971:   struct ospf *ospf;
  972: 
  973:   ospf = ospf_lookup ();
  974:   if (ospf == NULL)
  975:     return 0;
  976: 
  977:   ospf->t_distribute_update = NULL;
  978: 
  979:   zlog_info ("Zebra[Redistribute]: distribute-list update timer fired!");
  980: 
  981:   /* foreach all external info. */
  982:   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
  983:     {
  984:       rt = EXTERNAL_INFO (type);
  985:       if (!rt)
  986: 	continue;
  987:       for (rn = route_top (rt); rn; rn = route_next (rn))
  988: 	if ((ei = rn->info) != NULL)
  989: 	  {
  990: 	    if (is_prefix_default (&ei->p))
  991: 	      default_refresh = 1;
  992: 	    else if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p)))
  993: 	      ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_IF_CHANGED);
  994: 	    else
  995: 	      ospf_external_lsa_originate (ospf, ei);
  996: 	  }
  997:     }
  998:   if (default_refresh)
  999:     ospf_external_lsa_refresh_default (ospf);
 1000:   return 0;
 1001: }
 1002: 
 1003: #define OSPF_DISTRIBUTE_UPDATE_DELAY 5
 1004: 
 1005: /* Update distribute-list and set timer to apply access-list. */
 1006: void
 1007: ospf_distribute_list_update (struct ospf *ospf, uintptr_t type)
 1008: {
 1009:   struct route_table *rt;
 1010: 
 1011:   /* External info does not exist. */
 1012:   if (!(rt = EXTERNAL_INFO (type)))
 1013:     return;
 1014: 
 1015:   /* If exists previously invoked thread, then let it continue. */
 1016:   if (ospf->t_distribute_update)
 1017:     return;
 1018: 
 1019:   /* Set timer. */
 1020:   ospf->t_distribute_update =
 1021:     thread_add_timer (master, ospf_distribute_list_update_timer,
 1022:                       (void *) type, OSPF_DISTRIBUTE_UPDATE_DELAY);
 1023: }
 1024: 
 1025: /* If access-list is updated, apply some check. */
 1026: static void
 1027: ospf_filter_update (struct access_list *access)
 1028: {
 1029:   struct ospf *ospf;
 1030:   int type;
 1031:   int abr_inv = 0;
 1032:   struct ospf_area *area;
 1033:   struct listnode *node;
 1034: 
 1035:   /* If OSPF instatnce does not exist, return right now. */
 1036:   ospf = ospf_lookup ();
 1037:   if (ospf == NULL)
 1038:     return;
 1039: 
 1040:   /* Update distribute-list, and apply filter. */
 1041:   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
 1042:     {
 1043:       if (ROUTEMAP (ospf, type) != NULL)
 1044:         {
 1045:           /* if route-map is not NULL it may be using this access list */
 1046:           ospf_distribute_list_update (ospf, type);
 1047:           continue;
 1048:         }
 1049: 
 1050:       /* There is place for route-map for default-information (ZEBRA_ROUTE_MAX),
 1051:        * but no distribute list. */
 1052:       if (type == ZEBRA_ROUTE_MAX)
 1053: 	break;
 1054: 
 1055:       if (DISTRIBUTE_NAME (ospf, type))
 1056:         {
 1057:           /* Keep old access-list for distribute-list. */
 1058:           struct access_list *old = DISTRIBUTE_LIST (ospf, type);
 1059: 
 1060:           /* Update access-list for distribute-list. */
 1061:           DISTRIBUTE_LIST (ospf, type) =
 1062:             access_list_lookup (AFI_IP, DISTRIBUTE_NAME (ospf, type));
 1063: 
 1064:           /* No update for this distribute type. */
 1065:           if (old == NULL && DISTRIBUTE_LIST (ospf, type) == NULL)
 1066:             continue;
 1067: 
 1068:           /* Schedule distribute-list update timer. */
 1069:           if (DISTRIBUTE_LIST (ospf, type) == NULL ||
 1070:               strcmp (DISTRIBUTE_NAME (ospf, type), access->name) == 0)
 1071:             ospf_distribute_list_update (ospf, type);
 1072:         }
 1073:     }
 1074: 
 1075:   /* Update Area access-list. */
 1076:   for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
 1077:     {
 1078:       if (EXPORT_NAME (area))
 1079:         {
 1080:           EXPORT_LIST (area) = NULL;
 1081:           abr_inv++;
 1082:         }
 1083: 
 1084:       if (IMPORT_NAME (area))
 1085:         {
 1086:           IMPORT_LIST (area) = NULL;
 1087:           abr_inv++;
 1088:         }
 1089:     }
 1090: 
 1091:   /* Schedule ABR tasks -- this will be changed -- takada. */
 1092:   if (IS_OSPF_ABR (ospf) && abr_inv)
 1093:     ospf_schedule_abr_task (ospf);
 1094: }
 1095: 
 1096: /* If prefix-list is updated, do some updates. */
 1097: void
 1098: ospf_prefix_list_update (struct prefix_list *plist)
 1099: {
 1100:   struct ospf *ospf;
 1101:   int type;
 1102:   int abr_inv = 0;
 1103:   struct ospf_area *area;
 1104:   struct listnode *node;
 1105: 
 1106:   /* If OSPF instatnce does not exist, return right now. */
 1107:   ospf = ospf_lookup ();
 1108:   if (ospf == NULL)
 1109:     return;
 1110: 
 1111:   /* Update all route-maps which are used as redistribution filters.
 1112:    * They might use prefix-list.
 1113:    */
 1114:   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++)
 1115:     {
 1116:       if (ROUTEMAP (ospf, type) != NULL)
 1117:         {
 1118:           /* If route-map is not NULL it may be using this prefix list */
 1119:           ospf_distribute_list_update (ospf, type);
 1120:           continue;
 1121:         }
 1122:     }
 1123: 
 1124:   /* Update area filter-lists. */
 1125:   for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
 1126:     {
 1127:       /* Update filter-list in. */
 1128:       if (PREFIX_NAME_IN (area))
 1129:         if (strcmp (PREFIX_NAME_IN (area), plist->name) == 0)
 1130:           {
 1131:             PREFIX_LIST_IN (area) =
 1132:               prefix_list_lookup (AFI_IP, PREFIX_NAME_IN (area));
 1133:             abr_inv++;
 1134:           }
 1135: 
 1136:       /* Update filter-list out. */
 1137:       if (PREFIX_NAME_OUT (area))
 1138:         if (strcmp (PREFIX_NAME_OUT (area), plist->name) == 0)
 1139:           {
 1140:             PREFIX_LIST_IN (area) =
 1141:               prefix_list_lookup (AFI_IP, PREFIX_NAME_OUT (area));
 1142:             abr_inv++;
 1143:           }
 1144:     }
 1145: 
 1146:   /* Schedule ABR task. */
 1147:   if (IS_OSPF_ABR (ospf) && abr_inv)
 1148:     ospf_schedule_abr_task (ospf);
 1149: }
 1150: 
 1151: static struct ospf_distance *
 1152: ospf_distance_new (void)
 1153: {
 1154:   return XCALLOC (MTYPE_OSPF_DISTANCE, sizeof (struct ospf_distance));
 1155: }
 1156: 
 1157: static void
 1158: ospf_distance_free (struct ospf_distance *odistance)
 1159: {
 1160:   XFREE (MTYPE_OSPF_DISTANCE, odistance);
 1161: }
 1162: 
 1163: int
 1164: ospf_distance_set (struct vty *vty, struct ospf *ospf, 
 1165:                    const char *distance_str,
 1166:                    const char *ip_str, 
 1167:                    const char *access_list_str)
 1168: {
 1169:   int ret;
 1170:   struct prefix_ipv4 p;
 1171:   u_char distance;
 1172:   struct route_node *rn;
 1173:   struct ospf_distance *odistance;
 1174: 
 1175:   ret = str2prefix_ipv4 (ip_str, &p);
 1176:   if (ret == 0)
 1177:     {
 1178:       vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
 1179:       return CMD_WARNING;
 1180:     }
 1181: 
 1182:   distance = atoi (distance_str);
 1183: 
 1184:   /* Get OSPF distance node. */
 1185:   rn = route_node_get (ospf->distance_table, (struct prefix *) &p);
 1186:   if (rn->info)
 1187:     {
 1188:       odistance = rn->info;
 1189:       route_unlock_node (rn);
 1190:     }
 1191:   else
 1192:     {
 1193:       odistance = ospf_distance_new ();
 1194:       rn->info = odistance;
 1195:     }
 1196: 
 1197:   /* Set distance value. */
 1198:   odistance->distance = distance;
 1199: 
 1200:   /* Reset access-list configuration. */
 1201:   if (odistance->access_list)
 1202:     {
 1203:       free (odistance->access_list);
 1204:       odistance->access_list = NULL;
 1205:     }
 1206:   if (access_list_str)
 1207:     odistance->access_list = strdup (access_list_str);
 1208: 
 1209:   return CMD_SUCCESS;
 1210: }
 1211: 
 1212: int
 1213: ospf_distance_unset (struct vty *vty, struct ospf *ospf, 
 1214:                      const char *distance_str,
 1215:                      const char *ip_str, char 
 1216:                      const *access_list_str)
 1217: {
 1218:   int ret;
 1219:   struct prefix_ipv4 p;
 1220:   struct route_node *rn;
 1221:   struct ospf_distance *odistance;
 1222: 
 1223:   ret = str2prefix_ipv4 (ip_str, &p);
 1224:   if (ret == 0)
 1225:     {
 1226:       vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
 1227:       return CMD_WARNING;
 1228:     }
 1229: 
 1230:   rn = route_node_lookup (ospf->distance_table, (struct prefix *) &p);
 1231:   if (!rn)
 1232:     {
 1233:       vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
 1234:       return CMD_WARNING;
 1235:     }
 1236: 
 1237:   odistance = rn->info;
 1238: 
 1239:   if (odistance->access_list)
 1240:     free (odistance->access_list);
 1241:   ospf_distance_free (odistance);
 1242: 
 1243:   rn->info = NULL;
 1244:   route_unlock_node (rn);
 1245:   route_unlock_node (rn);
 1246: 
 1247:   return CMD_SUCCESS;
 1248: }
 1249: 
 1250: void
 1251: ospf_distance_reset (struct ospf *ospf)
 1252: {
 1253:   struct route_node *rn;
 1254:   struct ospf_distance *odistance;
 1255: 
 1256:   for (rn = route_top (ospf->distance_table); rn; rn = route_next (rn))
 1257:     if ((odistance = rn->info) != NULL)
 1258:       {
 1259:         if (odistance->access_list)
 1260:           free (odistance->access_list);
 1261:         ospf_distance_free (odistance);
 1262:         rn->info = NULL;
 1263:         route_unlock_node (rn);
 1264:       }
 1265: }
 1266: 
 1267: u_char
 1268: ospf_distance_apply (struct prefix_ipv4 *p, struct ospf_route *or)
 1269: {
 1270:   struct ospf *ospf;
 1271: 
 1272:   ospf = ospf_lookup ();
 1273:   if (ospf == NULL)
 1274:     return 0;
 1275: 
 1276:   if (ospf->distance_intra)
 1277:     if (or->path_type == OSPF_PATH_INTRA_AREA)
 1278:       return ospf->distance_intra;
 1279: 
 1280:   if (ospf->distance_inter)
 1281:     if (or->path_type == OSPF_PATH_INTER_AREA)
 1282:       return ospf->distance_inter;
 1283: 
 1284:   if (ospf->distance_external)
 1285:     if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL
 1286:         || or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
 1287:       return ospf->distance_external;
 1288: 
 1289:   if (ospf->distance_all)
 1290:     return ospf->distance_all;
 1291: 
 1292:   return 0;
 1293: }
 1294: 
 1295: void
 1296: ospf_zebra_init ()
 1297: {
 1298:   /* Allocate zebra structure. */
 1299:   zclient = zclient_new ();
 1300:   zclient_init (zclient, ZEBRA_ROUTE_OSPF);
 1301:   zclient->router_id_update = ospf_router_id_update_zebra;
 1302:   zclient->interface_add = ospf_interface_add;
 1303:   zclient->interface_delete = ospf_interface_delete;
 1304:   zclient->interface_up = ospf_interface_state_up;
 1305:   zclient->interface_down = ospf_interface_state_down;
 1306:   zclient->interface_address_add = ospf_interface_address_add;
 1307:   zclient->interface_address_delete = ospf_interface_address_delete;
 1308:   zclient->ipv4_route_add = ospf_zebra_read_ipv4;
 1309:   zclient->ipv4_route_delete = ospf_zebra_read_ipv4;
 1310: 
 1311:   access_list_add_hook (ospf_filter_update);
 1312:   access_list_delete_hook (ospf_filter_update);
 1313:   prefix_list_add_hook (ospf_prefix_list_update);
 1314:   prefix_list_delete_hook (ospf_prefix_list_update);
 1315: }

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