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