1/* RIPng daemon 2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#include <zebra.h> 23 24#include "prefix.h" 25#include "filter.h" 26#include "log.h" 27#include "thread.h" 28#include "memory.h" 29#include "if.h" 30#include "stream.h" 31#include "table.h" 32#include "command.h" 33#include "sockopt.h" 34#include "distribute.h" 35#include "plist.h" 36#include "routemap.h" 37#include "if_rmap.h" 38#include "privs.h" 39 40#include "ripngd/ripngd.h" 41#include "ripngd/ripng_route.h" 42#include "ripngd/ripng_debug.h" 43#include "ripngd/ripng_nexthop.h" 44 45/* RIPng structure which includes many parameters related to RIPng 46 protocol. If ripng couldn't active or ripng doesn't configured, 47 ripng->fd must be negative value. */ 48struct ripng *ripng = NULL; 49 50enum 51{ 52 ripng_all_route, 53 ripng_changed_route, 54}; 55 56extern struct zebra_privs_t ripngd_privs; 57 58/* Prototypes. */ 59void 60ripng_output_process (struct interface *, struct sockaddr_in6 *, int); 61 62int 63ripng_triggered_update (struct thread *); 64 65/* RIPng next hop specification. */ 66struct ripng_nexthop 67{ 68 enum ripng_nexthop_type 69 { 70 RIPNG_NEXTHOP_UNSPEC, 71 RIPNG_NEXTHOP_ADDRESS 72 } flag; 73 struct in6_addr address; 74}; 75 76static int 77ripng_route_rte (struct ripng_info *rinfo) 78{ 79 return (rinfo->type == ZEBRA_ROUTE_RIPNG && rinfo->sub_type == RIPNG_ROUTE_RTE); 80} 81 82/* Allocate new ripng information. */ 83struct ripng_info * 84ripng_info_new () 85{ 86 struct ripng_info *new; 87 88 new = XCALLOC (MTYPE_RIPNG_ROUTE, sizeof (struct ripng_info)); 89 return new; 90} 91 92/* Free ripng information. */ 93void 94ripng_info_free (struct ripng_info *rinfo) 95{ 96 XFREE (MTYPE_RIPNG_ROUTE, rinfo); 97} 98 99/* Create ripng socket. */ 100static int 101ripng_make_socket (void) 102{ 103 int ret; 104 int sock; 105 struct sockaddr_in6 ripaddr; 106 107 sock = socket (AF_INET6, SOCK_DGRAM, 0); 108 if (sock < 0) 109 { 110 zlog (NULL, LOG_ERR, "Can't make ripng socket"); 111 return sock; 112 } 113 114 ret = setsockopt_so_recvbuf (sock, 8096); 115 if (ret < 0) 116 return ret; 117 ret = setsockopt_ipv6_pktinfo (sock, 1); 118 if (ret < 0) 119 return ret; 120#ifdef IPTOS_PREC_INTERNETCONTROL 121 ret = setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL); 122 if (ret < 0) 123 return ret; 124#endif 125 ret = setsockopt_ipv6_multicast_hops (sock, 255); 126 if (ret < 0) 127 return ret; 128 ret = setsockopt_ipv6_multicast_loop (sock, 0); 129 if (ret < 0) 130 return ret; 131 ret = setsockopt_ipv6_hoplimit (sock, 1); 132 if (ret < 0) 133 return ret; 134 135 memset (&ripaddr, 0, sizeof (ripaddr)); 136 ripaddr.sin6_family = AF_INET6; 137#ifdef SIN6_LEN 138 ripaddr.sin6_len = sizeof (struct sockaddr_in6); 139#endif /* SIN6_LEN */ 140 ripaddr.sin6_port = htons (RIPNG_PORT_DEFAULT); 141 142 if (ripngd_privs.change (ZPRIVS_RAISE)) 143 zlog_err ("ripng_make_socket: could not raise privs"); 144 145 ret = bind (sock, (struct sockaddr *) &ripaddr, sizeof (ripaddr)); 146 if (ret < 0) 147 { 148 zlog (NULL, LOG_ERR, "Can't bind ripng socket: %s.", safe_strerror (errno)); 149 if (ripngd_privs.change (ZPRIVS_LOWER)) 150 zlog_err ("ripng_make_socket: could not lower privs"); 151 return ret; 152 } 153 if (ripngd_privs.change (ZPRIVS_LOWER)) 154 zlog_err ("ripng_make_socket: could not lower privs"); 155 return sock; 156} 157 158/* Send RIPng packet. */ 159int 160ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to, 161 struct interface *ifp) 162{ 163 int ret; 164 struct msghdr msg; 165 struct iovec iov; 166 struct cmsghdr *cmsgptr; 167 char adata [256]; 168 struct in6_pktinfo *pkt; 169 struct sockaddr_in6 addr; 170 171 if (IS_RIPNG_DEBUG_SEND) { 172 if (to) 173 zlog_debug ("send to %s", inet6_ntoa (to->sin6_addr)); 174 zlog_debug (" send interface %s", ifp->name); 175 zlog_debug (" send packet size %d", bufsize); 176 } 177 178 memset (&addr, 0, sizeof (struct sockaddr_in6)); 179 addr.sin6_family = AF_INET6; 180#ifdef SIN6_LEN 181 addr.sin6_len = sizeof (struct sockaddr_in6); 182#endif /* SIN6_LEN */ 183 addr.sin6_flowinfo = htonl (RIPNG_PRIORITY_DEFAULT); 184 185 /* When destination is specified. */ 186 if (to != NULL) 187 { 188 addr.sin6_addr = to->sin6_addr; 189 addr.sin6_port = to->sin6_port; 190 } 191 else 192 { 193 inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr); 194 addr.sin6_port = htons (RIPNG_PORT_DEFAULT); 195 } 196 197 msg.msg_name = (void *) &addr; 198 msg.msg_namelen = sizeof (struct sockaddr_in6); 199 msg.msg_iov = &iov; 200 msg.msg_iovlen = 1; 201 msg.msg_control = (void *) adata; 202 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 203 204 iov.iov_base = buf; 205 iov.iov_len = bufsize; 206 207 cmsgptr = (struct cmsghdr *)adata; 208 cmsgptr->cmsg_len = CMSG_LEN(sizeof (struct in6_pktinfo)); 209 cmsgptr->cmsg_level = IPPROTO_IPV6; 210 cmsgptr->cmsg_type = IPV6_PKTINFO; 211 212 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); 213 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr)); 214 pkt->ipi6_ifindex = ifp->ifindex; 215 216 ret = sendmsg (ripng->sock, &msg, 0); 217 218 if (ret < 0) { 219 if (to) 220 zlog_err ("RIPng send fail on %s to %s: %s", ifp->name, 221 inet6_ntoa (to->sin6_addr), safe_strerror (errno)); 222 else 223 zlog_err ("RIPng send fail on %s: %s", ifp->name, safe_strerror (errno)); 224 } 225 226 return ret; 227} 228 229/* Receive UDP RIPng packet from socket. */ 230static int 231ripng_recv_packet (int sock, u_char *buf, int bufsize, 232 struct sockaddr_in6 *from, unsigned int *ifindex, 233 int *hoplimit) 234{ 235 int ret; 236 struct msghdr msg; 237 struct iovec iov; 238 struct cmsghdr *cmsgptr; 239 struct in6_addr dst; 240 241 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this 242 point I can't determine size of cmsghdr */ 243 char adata[1024]; 244 245 /* Fill in message and iovec. */ 246 msg.msg_name = (void *) from; 247 msg.msg_namelen = sizeof (struct sockaddr_in6); 248 msg.msg_iov = &iov; 249 msg.msg_iovlen = 1; 250 msg.msg_control = (void *) adata; 251 msg.msg_controllen = sizeof adata; 252 iov.iov_base = buf; 253 iov.iov_len = bufsize; 254 255 /* If recvmsg fail return minus value. */ 256 ret = recvmsg (sock, &msg, 0); 257 if (ret < 0) 258 return ret; 259 260 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; 261 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) 262 { 263 /* I want interface index which this packet comes from. */ 264 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && 265 cmsgptr->cmsg_type == IPV6_PKTINFO) 266 { 267 struct in6_pktinfo *ptr; 268 269 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); 270 *ifindex = ptr->ipi6_ifindex; 271 dst = ptr->ipi6_addr; 272 273 if (*ifindex == 0) 274 zlog_warn ("Interface index returned by IPV6_PKTINFO is zero"); 275 } 276 277 /* Incoming packet's multicast hop limit. */ 278 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && 279 cmsgptr->cmsg_type == IPV6_HOPLIMIT) 280 { 281 int *phoplimit = (int *) CMSG_DATA (cmsgptr); 282 *hoplimit = *phoplimit; 283 } 284 } 285 286 /* Hoplimit check shold be done when destination address is 287 multicast address. */ 288 if (! IN6_IS_ADDR_MULTICAST (&dst)) 289 *hoplimit = -1; 290 291 return ret; 292} 293 294/* Dump rip packet */ 295void 296ripng_packet_dump (struct ripng_packet *packet, int size, const char *sndrcv) 297{ 298 caddr_t lim; 299 struct rte *rte; 300 const char *command_str; 301 302 /* Set command string. */ 303 if (packet->command == RIPNG_REQUEST) 304 command_str = "request"; 305 else if (packet->command == RIPNG_RESPONSE) 306 command_str = "response"; 307 else 308 command_str = "unknown"; 309 310 /* Dump packet header. */ 311 zlog_debug ("%s %s version %d packet size %d", 312 sndrcv, command_str, packet->version, size); 313 314 /* Dump each routing table entry. */ 315 rte = packet->rte; 316 317 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) 318 { 319 if (rte->metric == RIPNG_METRIC_NEXTHOP) 320 zlog_debug (" nexthop %s/%d", inet6_ntoa (rte->addr), rte->prefixlen); 321 else 322 zlog_debug (" %s/%d metric %d tag %d", 323 inet6_ntoa (rte->addr), rte->prefixlen, 324 rte->metric, ntohs (rte->tag)); 325 } 326} 327 328/* RIPng next hop address RTE (Route Table Entry). */ 329static void 330ripng_nexthop_rte (struct rte *rte, 331 struct sockaddr_in6 *from, 332 struct ripng_nexthop *nexthop) 333{ 334 char buf[INET6_BUFSIZ]; 335 336 /* Logging before checking RTE. */ 337 if (IS_RIPNG_DEBUG_RECV) 338 zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d", 339 inet6_ntoa (rte->addr), ntohs (rte->tag), rte->prefixlen); 340 341 /* RFC2080 2.1.1 Next Hop: 342 The route tag and prefix length in the next hop RTE must be 343 set to zero on sending and ignored on receiption. */ 344 if (ntohs (rte->tag) != 0) 345 zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s", 346 ntohs (rte->tag), inet6_ntoa (from->sin6_addr)); 347 348 if (rte->prefixlen != 0) 349 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s", 350 rte->prefixlen, inet6_ntoa (from->sin6_addr)); 351 352 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a 353 next hop RTE indicates that the next hop address should be the 354 originator of the RIPng advertisement. An address specified as a 355 next hop must be a link-local address. */ 356 if (IN6_IS_ADDR_UNSPECIFIED (&rte->addr)) 357 { 358 nexthop->flag = RIPNG_NEXTHOP_UNSPEC; 359 memset (&nexthop->address, 0, sizeof (struct in6_addr)); 360 return; 361 } 362 363 if (IN6_IS_ADDR_LINKLOCAL (&rte->addr)) 364 { 365 nexthop->flag = RIPNG_NEXTHOP_ADDRESS; 366 IPV6_ADDR_COPY (&nexthop->address, &rte->addr); 367 return; 368 } 369 370 /* The purpose of the next hop RTE is to eliminate packets being 371 routed through extra hops in the system. It is particularly useful 372 when RIPng is not being run on all of the routers on a network. 373 Note that next hop RTE is "advisory". That is, if the provided 374 information is ignored, a possibly sub-optimal, but absolutely 375 valid, route may be taken. If the received next hop address is not 376 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */ 377 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s", 378 inet6_ntoa (rte->addr), 379 inet_ntop (AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ)); 380 381 nexthop->flag = RIPNG_NEXTHOP_UNSPEC; 382 memset (&nexthop->address, 0, sizeof (struct in6_addr)); 383 384 return; 385} 386 387/* If ifp has same link-local address then return 1. */ 388static int 389ripng_lladdr_check (struct interface *ifp, struct in6_addr *addr) 390{ 391 struct listnode *node; 392 struct connected *connected; 393 struct prefix *p; 394 395 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) 396 { 397 p = connected->address; 398 399 if (p->family == AF_INET6 && 400 IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6) && 401 IN6_ARE_ADDR_EQUAL (&p->u.prefix6, addr)) 402 return 1; 403 } 404 return 0; 405} 406 407/* RIPng route garbage collect timer. */ 408static int 409ripng_garbage_collect (struct thread *t) 410{ 411 struct ripng_info *rinfo; 412 struct route_node *rp; 413 414 rinfo = THREAD_ARG (t); 415 rinfo->t_garbage_collect = NULL; 416 417 /* Off timeout timer. */ 418 RIPNG_TIMER_OFF (rinfo->t_timeout); 419 420 /* Get route_node pointer. */ 421 rp = rinfo->rp; 422 423 /* Unlock route_node. */ 424 rp->info = NULL; 425 route_unlock_node (rp); 426 427 /* Free RIPng routing information. */ 428 ripng_info_free (rinfo); 429 430 return 0; 431} 432 433/* Timeout RIPng routes. */ 434static int 435ripng_timeout (struct thread *t) 436{ 437 struct ripng_info *rinfo; 438 struct route_node *rp; 439 440 rinfo = THREAD_ARG (t); 441 rinfo->t_timeout = NULL; 442 443 /* Get route_node pointer. */ 444 rp = rinfo->rp; 445 446 /* - The garbage-collection timer is set for 120 seconds. */ 447 RIPNG_TIMER_ON (rinfo->t_garbage_collect, ripng_garbage_collect, 448 ripng->garbage_time); 449 450 /* Delete this route from the kernel. */ 451 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop, 452 rinfo->ifindex); 453 /* - The metric for the route is set to 16 (infinity). This causes 454 the route to be removed from service. */ 455 rinfo->metric = RIPNG_METRIC_INFINITY; 456 rinfo->flags &= ~RIPNG_RTF_FIB; 457 458 /* Aggregate count decrement. */ 459 ripng_aggregate_decrement (rp, rinfo); 460 461 /* - The route change flag is to indicate that this entry has been 462 changed. */ 463 rinfo->flags |= RIPNG_RTF_CHANGED; 464 465 /* - The output process is signalled to trigger a response. */ 466 ripng_event (RIPNG_TRIGGERED_UPDATE, 0); 467 468 return 0; 469} 470 471static void 472ripng_timeout_update (struct ripng_info *rinfo) 473{ 474 if (rinfo->metric != RIPNG_METRIC_INFINITY) 475 { 476 RIPNG_TIMER_OFF (rinfo->t_timeout); 477 RIPNG_TIMER_ON (rinfo->t_timeout, ripng_timeout, ripng->timeout_time); 478 } 479} 480 481static int 482ripng_incoming_filter (struct prefix_ipv6 *p, struct ripng_interface *ri) 483{ 484 struct distribute *dist; 485 struct access_list *alist; 486 struct prefix_list *plist; 487 488 /* Input distribute-list filtering. */ 489 if (ri->list[RIPNG_FILTER_IN]) 490 { 491 if (access_list_apply (ri->list[RIPNG_FILTER_IN], 492 (struct prefix *) p) == FILTER_DENY) 493 { 494 if (IS_RIPNG_DEBUG_PACKET) 495 zlog_debug ("%s/%d filtered by distribute in", 496 inet6_ntoa (p->prefix), p->prefixlen); 497 return -1; 498 } 499 } 500 if (ri->prefix[RIPNG_FILTER_IN]) 501 { 502 if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN], 503 (struct prefix *) p) == PREFIX_DENY) 504 { 505 if (IS_RIPNG_DEBUG_PACKET) 506 zlog_debug ("%s/%d filtered by prefix-list in", 507 inet6_ntoa (p->prefix), p->prefixlen); 508 return -1; 509 } 510 } 511 512 /* All interface filter check. */ 513 dist = distribute_lookup (NULL); 514 if (dist) 515 { 516 if (dist->list[DISTRIBUTE_IN]) 517 { 518 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]); 519 520 if (alist) 521 { 522 if (access_list_apply (alist, 523 (struct prefix *) p) == FILTER_DENY) 524 { 525 if (IS_RIPNG_DEBUG_PACKET) 526 zlog_debug ("%s/%d filtered by distribute in", 527 inet6_ntoa (p->prefix), p->prefixlen); 528 return -1; 529 } 530 } 531 } 532 if (dist->prefix[DISTRIBUTE_IN]) 533 { 534 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]); 535 536 if (plist) 537 { 538 if (prefix_list_apply (plist, 539 (struct prefix *) p) == PREFIX_DENY) 540 { 541 if (IS_RIPNG_DEBUG_PACKET) 542 zlog_debug ("%s/%d filtered by prefix-list in", 543 inet6_ntoa (p->prefix), p->prefixlen); 544 return -1; 545 } 546 } 547 } 548 } 549 return 0; 550} 551 552static int 553ripng_outgoing_filter (struct prefix_ipv6 *p, struct ripng_interface *ri) 554{ 555 struct distribute *dist; 556 struct access_list *alist; 557 struct prefix_list *plist; 558 559 if (ri->list[RIPNG_FILTER_OUT]) 560 { 561 if (access_list_apply (ri->list[RIPNG_FILTER_OUT], 562 (struct prefix *) p) == FILTER_DENY) 563 { 564 if (IS_RIPNG_DEBUG_PACKET) 565 zlog_debug ("%s/%d is filtered by distribute out", 566 inet6_ntoa (p->prefix), p->prefixlen); 567 return -1; 568 } 569 } 570 if (ri->prefix[RIPNG_FILTER_OUT]) 571 { 572 if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT], 573 (struct prefix *) p) == PREFIX_DENY) 574 { 575 if (IS_RIPNG_DEBUG_PACKET) 576 zlog_debug ("%s/%d is filtered by prefix-list out", 577 inet6_ntoa (p->prefix), p->prefixlen); 578 return -1; 579 } 580 } 581 582 /* All interface filter check. */ 583 dist = distribute_lookup (NULL); 584 if (dist) 585 { 586 if (dist->list[DISTRIBUTE_OUT]) 587 { 588 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]); 589 590 if (alist) 591 { 592 if (access_list_apply (alist, 593 (struct prefix *) p) == FILTER_DENY) 594 { 595 if (IS_RIPNG_DEBUG_PACKET) 596 zlog_debug ("%s/%d filtered by distribute out", 597 inet6_ntoa (p->prefix), p->prefixlen); 598 return -1; 599 } 600 } 601 } 602 if (dist->prefix[DISTRIBUTE_OUT]) 603 { 604 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]); 605 606 if (plist) 607 { 608 if (prefix_list_apply (plist, 609 (struct prefix *) p) == PREFIX_DENY) 610 { 611 if (IS_RIPNG_DEBUG_PACKET) 612 zlog_debug ("%s/%d filtered by prefix-list out", 613 inet6_ntoa (p->prefix), p->prefixlen); 614 return -1; 615 } 616 } 617 } 618 } 619 return 0; 620} 621 622/* Process RIPng route according to RFC2080. */ 623static void 624ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, 625 struct ripng_nexthop *ripng_nexthop, 626 struct interface *ifp) 627{ 628 int ret; 629 struct prefix_ipv6 p; 630 struct route_node *rp; 631 struct ripng_info *rinfo; 632 struct ripng_interface *ri; 633 struct in6_addr *nexthop; 634 u_char oldmetric; 635 int same = 0; 636 637 /* Make prefix structure. */ 638 memset (&p, 0, sizeof (struct prefix_ipv6)); 639 p.family = AF_INET6; 640 /* p.prefix = rte->addr; */ 641 IPV6_ADDR_COPY (&p.prefix, &rte->addr); 642 p.prefixlen = rte->prefixlen; 643 644 /* Make sure mask is applied. */ 645 /* XXX We have to check the prefix is valid or not before call 646 apply_mask_ipv6. */ 647 apply_mask_ipv6 (&p); 648 649 /* Apply input filters. */ 650 ri = ifp->info; 651 652 ret = ripng_incoming_filter (&p, ri); 653 if (ret < 0) 654 return; 655 656 /* Modify entry. */ 657 if (ri->routemap[RIPNG_FILTER_IN]) 658 { 659 int ret; 660 struct ripng_info newinfo; 661 662 memset (&newinfo, 0, sizeof (struct ripng_info)); 663 newinfo.type = ZEBRA_ROUTE_RIPNG; 664 newinfo.sub_type = RIPNG_ROUTE_RTE; 665 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) 666 newinfo.nexthop = ripng_nexthop->address; 667 else 668 newinfo.nexthop = from->sin6_addr; 669 newinfo.from = from->sin6_addr; 670 newinfo.ifindex = ifp->ifindex; 671 newinfo.metric = rte->metric; 672 newinfo.metric_out = rte->metric; /* XXX */ 673 newinfo.tag = ntohs(rte->tag); /* XXX */ 674 675 ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN], 676 (struct prefix *)&p, RMAP_RIPNG, &newinfo); 677 678 if (ret == RMAP_DENYMATCH) 679 { 680 if (IS_RIPNG_DEBUG_PACKET) 681 zlog_debug ("RIPng %s/%d is filtered by route-map in", 682 inet6_ntoa (p.prefix), p.prefixlen); 683 return; 684 } 685 686 /* Get back the object */ 687 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) { 688 if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) { 689 /* the nexthop get changed by the routemap */ 690 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) 691 ripng_nexthop->address = newinfo.nexthop; 692 else 693 ripng_nexthop->address = in6addr_any; 694 } 695 } else { 696 if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) { 697 /* the nexthop get changed by the routemap */ 698 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) { 699 ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS; 700 ripng_nexthop->address = newinfo.nexthop; 701 } 702 } 703 } 704 rte->tag = htons(newinfo.tag_out); /* XXX */ 705 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */ 706 } 707 708 /* Once the entry has been validated, update the metric by 709 * adding the cost of the network on wich the message 710 * arrived. If the result is greater than infinity, use infinity 711 * (RFC2453 Sec. 3.9.2) 712 **/ 713 714 /* Zebra ripngd can handle offset-list in. */ 715 ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric); 716 717 /* If offset-list does not modify the metric use interface's 718 * one. */ 719 if (! ret) 720 rte->metric += ifp->metric ? ifp->metric : 1; 721 722 if (rte->metric > RIPNG_METRIC_INFINITY) 723 rte->metric = RIPNG_METRIC_INFINITY; 724 725 /* Set nexthop pointer. */ 726 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) 727 nexthop = &ripng_nexthop->address; 728 else 729 nexthop = &from->sin6_addr; 730 731 /* Lookup RIPng routing table. */ 732 rp = route_node_get (ripng->table, (struct prefix *) &p); 733 734 /* Sanity check */ 735 rinfo = rp->info; 736 if (rinfo) 737 { 738 /* Redistributed route check. */ 739 if (rinfo->type != ZEBRA_ROUTE_RIPNG 740 && rinfo->metric != RIPNG_METRIC_INFINITY) 741 return; 742 743 /* Local static route. */ 744 if (rinfo->type == ZEBRA_ROUTE_RIPNG 745 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) || 746 (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) 747 && rinfo->metric != RIPNG_METRIC_INFINITY) 748 return; 749 } 750 751 if (rp->info == NULL) 752 { 753 /* Now, check to see whether there is already an explicit route 754 for the destination prefix. If there is no such route, add 755 this route to the routing table, unless the metric is 756 infinity (there is no point in adding a route which 757 unusable). */ 758 if (rte->metric != RIPNG_METRIC_INFINITY) 759 { 760 rinfo = ripng_info_new (); 761 762 /* - Setting the destination prefix and length to those in 763 the RTE. */ 764 rp->info = rinfo; 765 rinfo->rp = rp; 766 767 /* - Setting the metric to the newly calculated metric (as 768 described above). */ 769 rinfo->metric = rte->metric; 770 rinfo->tag = ntohs (rte->tag); 771 772 /* - Set the next hop address to be the address of the router 773 from which the datagram came or the next hop address 774 specified by a next hop RTE. */ 775 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop); 776 IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr); 777 rinfo->ifindex = ifp->ifindex; 778 779 /* - Initialize the timeout for the route. If the 780 garbage-collection timer is running for this route, stop it. */ 781 ripng_timeout_update (rinfo); 782 783 /* - Set the route change flag. */ 784 rinfo->flags |= RIPNG_RTF_CHANGED; 785 786 /* - Signal the output process to trigger an update (see section 787 2.5). */ 788 ripng_event (RIPNG_TRIGGERED_UPDATE, 0); 789 790 /* Finally, route goes into the kernel. */ 791 rinfo->type = ZEBRA_ROUTE_RIPNG; 792 rinfo->sub_type = RIPNG_ROUTE_RTE; 793 794 ripng_zebra_ipv6_add (&p, &rinfo->nexthop, rinfo->ifindex, 795 rinfo->metric); 796 rinfo->flags |= RIPNG_RTF_FIB; 797 798 /* Aggregate check. */ 799 ripng_aggregate_increment (rp, rinfo); 800 } 801 } 802 else 803 { 804 rinfo = rp->info; 805 806 /* If there is an existing route, compare the next hop address 807 to the address of the router from which the datagram came. 808 If this datagram is from the same router as the existing 809 route, reinitialize the timeout. */ 810 same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) 811 && (rinfo->ifindex == ifp->ifindex)); 812 813 if (same) 814 ripng_timeout_update (rinfo); 815 816 /* Next, compare the metrics. If the datagram is from the same 817 router as the existing route, and the new metric is different 818 than the old one; or, if the new metric is lower than the old 819 one; do the following actions: */ 820 if ((same && rinfo->metric != rte->metric) || 821 rte->metric < rinfo->metric) 822 { 823 /* - Adopt the route from the datagram. That is, put the 824 new metric in, and adjust the next hop address (if 825 necessary). */ 826 oldmetric = rinfo->metric; 827 rinfo->metric = rte->metric; 828 rinfo->tag = ntohs (rte->tag); 829 IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr); 830 rinfo->ifindex = ifp->ifindex; 831 832 /* Should a new route to this network be established 833 while the garbage-collection timer is running, the 834 new route will replace the one that is about to be 835 deleted. In this case the garbage-collection timer 836 must be cleared. */ 837 838 if (oldmetric == RIPNG_METRIC_INFINITY && 839 rinfo->metric < RIPNG_METRIC_INFINITY) 840 { 841 rinfo->type = ZEBRA_ROUTE_RIPNG; 842 rinfo->sub_type = RIPNG_ROUTE_RTE; 843 844 RIPNG_TIMER_OFF (rinfo->t_garbage_collect); 845 846 if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop)) 847 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop); 848 849 ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex, rinfo->metric); 850 rinfo->flags |= RIPNG_RTF_FIB; 851 852 /* The aggregation counter needs to be updated because 853 the prefixes, which are into the gc, have been 854 removed from the aggregator (see ripng_timout). */ 855 ripng_aggregate_increment (rp, rinfo); 856 } 857 858 /* Update nexthop and/or metric value. */ 859 if (oldmetric != RIPNG_METRIC_INFINITY) 860 { 861 ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex); 862 ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex, rinfo->metric); 863 rinfo->flags |= RIPNG_RTF_FIB; 864 865 if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop)) 866 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop); 867 } 868 869 /* - Set the route change flag and signal the output process 870 to trigger an update. */ 871 rinfo->flags |= RIPNG_RTF_CHANGED; 872 ripng_event (RIPNG_TRIGGERED_UPDATE, 0); 873 874 /* - If the new metric is infinity, start the deletion 875 process (described above); */ 876 if (rinfo->metric == RIPNG_METRIC_INFINITY) 877 { 878 /* If the new metric is infinity, the deletion process 879 begins for the route, which is no longer used for 880 routing packets. Note that the deletion process is 881 started only when the metric is first set to 882 infinity. If the metric was already infinity, then a 883 new deletion process is not started. */ 884 if (oldmetric != RIPNG_METRIC_INFINITY) 885 { 886 /* - The garbage-collection timer is set for 120 seconds. */ 887 RIPNG_TIMER_ON (rinfo->t_garbage_collect, 888 ripng_garbage_collect, ripng->garbage_time); 889 RIPNG_TIMER_OFF (rinfo->t_timeout); 890 891 /* - The metric for the route is set to 16 892 (infinity). This causes the route to be removed 893 from service.*/ 894 ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex); 895 rinfo->flags &= ~RIPNG_RTF_FIB; 896 897 /* Aggregate count decrement. */ 898 ripng_aggregate_decrement (rp, rinfo); 899 900 /* - The route change flag is to indicate that this 901 entry has been changed. */ 902 /* - The output process is signalled to trigger a 903 response. */ 904 ; /* Above processes are already done previously. */ 905 } 906 } 907 else 908 { 909 /* otherwise, re-initialize the timeout. */ 910 ripng_timeout_update (rinfo); 911 } 912 } 913 /* Unlock tempolary lock of the route. */ 914 route_unlock_node (rp); 915 } 916} 917 918/* Add redistributed route to RIPng table. */ 919void 920ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, 921 unsigned int ifindex, struct in6_addr *nexthop) 922{ 923 struct route_node *rp; 924 struct ripng_info *rinfo; 925 926 /* Redistribute route */ 927 if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) 928 return; 929 if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) 930 return; 931 932 rp = route_node_get (ripng->table, (struct prefix *) p); 933 rinfo = rp->info; 934 935 if (rinfo) 936 { 937 if (rinfo->type == ZEBRA_ROUTE_CONNECT 938 && rinfo->sub_type == RIPNG_ROUTE_INTERFACE 939 && rinfo->metric != RIPNG_METRIC_INFINITY) { 940 route_unlock_node (rp); 941 return; 942 } 943 944 /* Manually configured RIPng route check. 945 * They have the precedence on all the other entries. 946 **/ 947 if (rinfo->type == ZEBRA_ROUTE_RIPNG 948 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) || 949 (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) { 950 if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) && 951 (sub_type != RIPNG_ROUTE_DEFAULT))) { 952 route_unlock_node (rp); 953 return; 954 } 955 } 956 957 RIPNG_TIMER_OFF (rinfo->t_timeout); 958 RIPNG_TIMER_OFF (rinfo->t_garbage_collect); 959 960 /* Tells the other daemons about the deletion of 961 * this RIPng route 962 **/ 963 if (ripng_route_rte (rinfo)) 964 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop, 965 rinfo->metric); 966 967 rp->info = NULL; 968 ripng_info_free (rinfo); 969 970 route_unlock_node (rp); 971 972 } 973 974 rinfo = ripng_info_new (); 975 976 rinfo->type = type; 977 rinfo->sub_type = sub_type; 978 rinfo->ifindex = ifindex; 979 rinfo->metric = 1; 980 rinfo->rp = rp; 981 982 if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop)) 983 rinfo->nexthop = *nexthop; 984 985 rinfo->flags |= RIPNG_RTF_FIB; 986 rp->info = rinfo; 987 988 /* Aggregate check. */ 989 ripng_aggregate_increment (rp, rinfo); 990 991 rinfo->flags |= RIPNG_RTF_CHANGED; 992 993 if (IS_RIPNG_DEBUG_EVENT) { 994 if (!nexthop) 995 zlog_debug ("Redistribute new prefix %s/%d on the interface %s", 996 inet6_ntoa(p->prefix), p->prefixlen, 997 ifindex2ifname(ifindex)); 998 else 999 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s", 1000 inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop), 1001 ifindex2ifname(ifindex)); 1002 } 1003 1004 ripng_event (RIPNG_TRIGGERED_UPDATE, 0); 1005} 1006 1007/* Delete redistributed route to RIPng table. */ 1008void 1009ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, 1010 unsigned int ifindex) 1011{ 1012 struct route_node *rp; 1013 struct ripng_info *rinfo; 1014 1015 if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) 1016 return; 1017 if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) 1018 return; 1019 1020 rp = route_node_lookup (ripng->table, (struct prefix *) p); 1021 1022 if (rp) 1023 { 1024 rinfo = rp->info; 1025 1026 if (rinfo != NULL 1027 && rinfo->type == type 1028 && rinfo->sub_type == sub_type 1029 && rinfo->ifindex == ifindex) 1030 { 1031 /* Perform poisoned reverse. */ 1032 rinfo->metric = RIPNG_METRIC_INFINITY; 1033 RIPNG_TIMER_ON (rinfo->t_garbage_collect, 1034 ripng_garbage_collect, ripng->garbage_time); 1035 RIPNG_TIMER_OFF (rinfo->t_timeout); 1036 1037 /* Aggregate count decrement. */ 1038 ripng_aggregate_decrement (rp, rinfo); 1039 1040 rinfo->flags |= RIPNG_RTF_CHANGED; 1041 1042 if (IS_RIPNG_DEBUG_EVENT) 1043 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]", 1044 inet6_ntoa(p->prefix), p->prefixlen, 1045 ifindex2ifname(ifindex)); 1046 1047 ripng_event (RIPNG_TRIGGERED_UPDATE, 0); 1048 } 1049 } 1050} 1051 1052/* Withdraw redistributed route. */ 1053void 1054ripng_redistribute_withdraw (int type) 1055{ 1056 struct route_node *rp; 1057 struct ripng_info *rinfo; 1058 1059 if (!ripng) 1060 return; 1061 1062 for (rp = route_top (ripng->table); rp; rp = route_next (rp)) 1063 if ((rinfo = rp->info) != NULL) 1064 { 1065 if ((rinfo->type == type) 1066 && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE)) 1067 { 1068 /* Perform poisoned reverse. */ 1069 rinfo->metric = RIPNG_METRIC_INFINITY; 1070 RIPNG_TIMER_ON (rinfo->t_garbage_collect, 1071 ripng_garbage_collect, ripng->garbage_time); 1072 RIPNG_TIMER_OFF (rinfo->t_timeout); 1073 1074 /* Aggregate count decrement. */ 1075 ripng_aggregate_decrement (rp, rinfo); 1076 1077 rinfo->flags |= RIPNG_RTF_CHANGED; 1078 1079 if (IS_RIPNG_DEBUG_EVENT) { 1080 struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p; 1081 1082 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]", 1083 inet6_ntoa(p->prefix), p->prefixlen, 1084 ifindex2ifname(rinfo->ifindex)); 1085 } 1086 1087 ripng_event (RIPNG_TRIGGERED_UPDATE, 0); 1088 } 1089 } 1090} 1091 1092/* RIP routing information. */ 1093static void 1094ripng_response_process (struct ripng_packet *packet, int size, 1095 struct sockaddr_in6 *from, struct interface *ifp, 1096 int hoplimit) 1097{ 1098 caddr_t lim; 1099 struct rte *rte; 1100 struct ripng_nexthop nexthop; 1101 1102 /* RFC2080 2.4.2 Response Messages: 1103 The Response must be ignored if it is not from the RIPng port. */ 1104 if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT) 1105 { 1106 zlog_warn ("RIPng packet comes from non RIPng port %d from %s", 1107 ntohs (from->sin6_port), inet6_ntoa (from->sin6_addr)); 1108 ripng_peer_bad_packet (from); 1109 return; 1110 } 1111 1112 /* The datagram's IPv6 source address should be checked to see 1113 whether the datagram is from a valid neighbor; the source of the 1114 datagram must be a link-local address. */ 1115 if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) 1116 { 1117 zlog_warn ("RIPng packet comes from non link local address %s", 1118 inet6_ntoa (from->sin6_addr)); 1119 ripng_peer_bad_packet (from); 1120 return; 1121 } 1122 1123 /* It is also worth checking to see whether the response is from one 1124 of the router's own addresses. Interfaces on broadcast networks 1125 may receive copies of their own multicasts immediately. If a 1126 router processes its own output as new input, confusion is likely, 1127 and such datagrams must be ignored. */ 1128 if (ripng_lladdr_check (ifp, &from->sin6_addr)) 1129 { 1130 zlog_warn ("RIPng packet comes from my own link local address %s", 1131 inet6_ntoa (from->sin6_addr)); 1132 ripng_peer_bad_packet (from); 1133 return; 1134 } 1135 1136 /* As an additional check, periodic advertisements must have their 1137 hop counts set to 255, and inbound, multicast packets sent from the 1138 RIPng port (i.e. periodic advertisement or triggered update 1139 packets) must be examined to ensure that the hop count is 255. */ 1140 if (hoplimit >= 0 && hoplimit != 255) 1141 { 1142 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s", 1143 hoplimit, inet6_ntoa (from->sin6_addr)); 1144 ripng_peer_bad_packet (from); 1145 return; 1146 } 1147 1148 /* Update RIPng peer. */ 1149 ripng_peer_update (from, packet->version); 1150 1151 /* Reset nexthop. */ 1152 memset (&nexthop, 0, sizeof (struct ripng_nexthop)); 1153 nexthop.flag = RIPNG_NEXTHOP_UNSPEC; 1154 1155 /* Set RTE pointer. */ 1156 rte = packet->rte; 1157 1158 for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++) 1159 { 1160 /* First of all, we have to check this RTE is next hop RTE or 1161 not. Next hop RTE is completely different with normal RTE so 1162 we need special treatment. */ 1163 if (rte->metric == RIPNG_METRIC_NEXTHOP) 1164 { 1165 ripng_nexthop_rte (rte, from, &nexthop); 1166 continue; 1167 } 1168 1169 /* RTE information validation. */ 1170 1171 /* - is the destination prefix valid (e.g., not a multicast 1172 prefix and not a link-local address) A link-local address 1173 should never be present in an RTE. */ 1174 if (IN6_IS_ADDR_MULTICAST (&rte->addr)) 1175 { 1176 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]", 1177 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); 1178 ripng_peer_bad_route (from); 1179 continue; 1180 } 1181 if (IN6_IS_ADDR_LINKLOCAL (&rte->addr)) 1182 { 1183 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]", 1184 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); 1185 ripng_peer_bad_route (from); 1186 continue; 1187 } 1188 if (IN6_IS_ADDR_LOOPBACK (&rte->addr)) 1189 { 1190 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]", 1191 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); 1192 ripng_peer_bad_route (from); 1193 continue; 1194 } 1195 1196 /* - is the prefix length valid (i.e., between 0 and 128, 1197 inclusive) */ 1198 if (rte->prefixlen > 128) 1199 { 1200 zlog_warn ("Invalid prefix length %s/%d from %s%%%s", 1201 inet6_ntoa (rte->addr), rte->prefixlen, 1202 inet6_ntoa (from->sin6_addr), ifp->name); 1203 ripng_peer_bad_route (from); 1204 continue; 1205 } 1206 1207 /* - is the metric valid (i.e., between 1 and 16, inclusive) */ 1208 if (! (rte->metric >= 1 && rte->metric <= 16)) 1209 { 1210 zlog_warn ("Invalid metric %d from %s%%%s", rte->metric, 1211 inet6_ntoa (from->sin6_addr), ifp->name); 1212 ripng_peer_bad_route (from); 1213 continue; 1214 } 1215 1216 /* Vincent: XXX Should we compute the direclty reachable nexthop 1217 * for our RIPng network ? 1218 **/ 1219 1220 /* Routing table updates. */ 1221 ripng_route_process (rte, from, &nexthop, ifp); 1222 } 1223} 1224 1225/* Response to request message. */ 1226static void 1227ripng_request_process (struct ripng_packet *packet,int size, 1228 struct sockaddr_in6 *from, struct interface *ifp) 1229{ 1230 caddr_t lim; 1231 struct rte *rte; 1232 struct prefix_ipv6 p; 1233 struct route_node *rp; 1234 struct ripng_info *rinfo; 1235 struct ripng_interface *ri; 1236 1237 /* Does not reponse to the requests on the loopback interfaces */ 1238 if (if_is_loopback (ifp)) 1239 return; 1240 1241 /* Check RIPng process is enabled on this interface. */ 1242 ri = ifp->info; 1243 if (! ri->running) 1244 return; 1245 1246 /* When passive interface is specified, suppress responses */ 1247 if (ri->passive) 1248 return; 1249 1250 /* RIPng peer update. */ 1251 ripng_peer_update (from, packet->version); 1252 1253 lim = ((caddr_t) packet) + size; 1254 rte = packet->rte; 1255 1256 /* The Request is processed entry by entry. If there are no 1257 entries, no response is given. */ 1258 if (lim == (caddr_t) rte) 1259 return; 1260 1261 /* There is one special case. If there is exactly one entry in the 1262 request, and it has a destination prefix of zero, a prefix length 1263 of zero, and a metric of infinity (i.e., 16), then this is a 1264 request to send the entire routing table. In that case, a call 1265 is made to the output process to send the routing table to the 1266 requesting address/port. */ 1267 if (lim == ((caddr_t) (rte + 1)) && 1268 IN6_IS_ADDR_UNSPECIFIED (&rte->addr) && 1269 rte->prefixlen == 0 && 1270 rte->metric == RIPNG_METRIC_INFINITY) 1271 { 1272 /* All route with split horizon */ 1273 ripng_output_process (ifp, from, ripng_all_route); 1274 } 1275 else 1276 { 1277 /* Except for this special case, processing is quite simple. 1278 Examine the list of RTEs in the Request one by one. For each 1279 entry, look up the destination in the router's routing 1280 database and, if there is a route, put that route's metric in 1281 the metric field of the RTE. If there is no explicit route 1282 to the specified destination, put infinity in the metric 1283 field. Once all the entries have been filled in, change the 1284 command from Request to Response and send the datagram back 1285 to the requestor. */ 1286 memset (&p, 0, sizeof (struct prefix_ipv6)); 1287 p.family = AF_INET6; 1288 1289 for (; ((caddr_t) rte) < lim; rte++) 1290 { 1291 p.prefix = rte->addr; 1292 p.prefixlen = rte->prefixlen; 1293 apply_mask_ipv6 (&p); 1294 1295 rp = route_node_lookup (ripng->table, (struct prefix *) &p); 1296 1297 if (rp) 1298 { 1299 rinfo = rp->info; 1300 rte->metric = rinfo->metric; 1301 route_unlock_node (rp); 1302 } 1303 else 1304 rte->metric = RIPNG_METRIC_INFINITY; 1305 } 1306 packet->command = RIPNG_RESPONSE; 1307 1308 ripng_send_packet ((caddr_t) packet, size, from, ifp); 1309 } 1310} 1311 1312/* First entry point of reading RIPng packet. */ 1313static int 1314ripng_read (struct thread *thread) 1315{ 1316 int len; 1317 int sock; 1318 struct sockaddr_in6 from; 1319 struct ripng_packet *packet; 1320 unsigned int ifindex; 1321 struct interface *ifp; 1322 int hoplimit = -1; 1323 1324 /* Check ripng is active and alive. */ 1325 assert (ripng != NULL); 1326 assert (ripng->sock >= 0); 1327 1328 /* Fetch thread data and set read pointer to empty for event 1329 managing. `sock' sould be same as ripng->sock. */ 1330 sock = THREAD_FD (thread); 1331 ripng->t_read = NULL; 1332 1333 /* Add myself to the next event. */ 1334 ripng_event (RIPNG_READ, sock); 1335 1336 /* Read RIPng packet. */ 1337 len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf), 1338 STREAM_SIZE (ripng->ibuf), &from, &ifindex, 1339 &hoplimit); 1340 if (len < 0) 1341 { 1342 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno)); 1343 return len; 1344 } 1345 1346 /* Check RTE boundary. RTE size (Packet length - RIPng header size 1347 (4)) must be multiple size of one RTE size (20). */ 1348 if (((len - 4) % 20) != 0) 1349 { 1350 zlog_warn ("RIPng invalid packet size %d from %s", len, 1351 inet6_ntoa (from.sin6_addr)); 1352 ripng_peer_bad_packet (&from); 1353 return 0; 1354 } 1355 1356 packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf); 1357 ifp = if_lookup_by_index (ifindex); 1358 1359 /* RIPng packet received. */ 1360 if (IS_RIPNG_DEBUG_EVENT) 1361 zlog_debug ("RIPng packet received from %s port %d on %s", 1362 inet6_ntoa (from.sin6_addr), ntohs (from.sin6_port), 1363 ifp ? ifp->name : "unknown"); 1364 1365 /* Logging before packet checking. */ 1366 if (IS_RIPNG_DEBUG_RECV) 1367 ripng_packet_dump (packet, len, "RECV"); 1368 1369 /* Packet comes from unknown interface. */ 1370 if (ifp == NULL) 1371 { 1372 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex); 1373 return 0; 1374 } 1375 1376 /* Packet version mismatch checking. */ 1377 if (packet->version != ripng->version) 1378 { 1379 zlog_warn ("RIPng packet version %d doesn't fit to my version %d", 1380 packet->version, ripng->version); 1381 ripng_peer_bad_packet (&from); 1382 return 0; 1383 } 1384 1385 /* Process RIPng packet. */ 1386 switch (packet->command) 1387 { 1388 case RIPNG_REQUEST: 1389 ripng_request_process (packet, len, &from, ifp); 1390 break; 1391 case RIPNG_RESPONSE: 1392 ripng_response_process (packet, len, &from, ifp, hoplimit); 1393 break; 1394 default: 1395 zlog_warn ("Invalid RIPng command %d", packet->command); 1396 ripng_peer_bad_packet (&from); 1397 break; 1398 } 1399 return 0; 1400} 1401 1402/* Walk down the RIPng routing table then clear changed flag. */ 1403static void 1404ripng_clear_changed_flag (void) 1405{ 1406 struct route_node *rp; 1407 struct ripng_info *rinfo; 1408 1409 for (rp = route_top (ripng->table); rp; rp = route_next (rp)) 1410 if ((rinfo = rp->info) != NULL) 1411 if (rinfo->flags & RIPNG_RTF_CHANGED) 1412 rinfo->flags &= ~RIPNG_RTF_CHANGED; 1413} 1414 1415/* Regular update of RIPng route. Send all routing formation to RIPng 1416 enabled interface. */ 1417static int 1418ripng_update (struct thread *t) 1419{ 1420 struct listnode *node; 1421 struct interface *ifp; 1422 struct ripng_interface *ri; 1423 1424 /* Clear update timer thread. */ 1425 ripng->t_update = NULL; 1426 1427 /* Logging update event. */ 1428 if (IS_RIPNG_DEBUG_EVENT) 1429 zlog_debug ("RIPng update timer expired!"); 1430 1431 /* Supply routes to each interface. */ 1432 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 1433 { 1434 ri = ifp->info; 1435 1436 if (if_is_loopback (ifp) || ! if_is_up (ifp)) 1437 continue; 1438 1439 if (! ri->running) 1440 continue; 1441 1442 /* When passive interface is specified, suppress announce to the 1443 interface. */ 1444 if (ri->passive) 1445 continue; 1446 1447#if RIPNG_ADVANCED 1448 if (ri->ri_send == RIPNG_SEND_OFF) 1449 { 1450 if (IS_RIPNG_DEBUG_EVENT) 1451 zlog (NULL, LOG_DEBUG, 1452 "[Event] RIPng send to if %d is suppressed by config", 1453 ifp->ifindex); 1454 continue; 1455 } 1456#endif /* RIPNG_ADVANCED */ 1457 1458 ripng_output_process (ifp, NULL, ripng_all_route); 1459 } 1460 1461 /* Triggered updates may be suppressed if a regular update is due by 1462 the time the triggered update would be sent. */ 1463 if (ripng->t_triggered_interval) 1464 { 1465 thread_cancel (ripng->t_triggered_interval); 1466 ripng->t_triggered_interval = NULL; 1467 } 1468 ripng->trigger = 0; 1469 1470 /* Reset flush event. */ 1471 ripng_event (RIPNG_UPDATE_EVENT, 0); 1472 1473 return 0; 1474} 1475 1476/* Triggered update interval timer. */ 1477static int 1478ripng_triggered_interval (struct thread *t) 1479{ 1480 ripng->t_triggered_interval = NULL; 1481 1482 if (ripng->trigger) 1483 { 1484 ripng->trigger = 0; 1485 ripng_triggered_update (t); 1486 } 1487 return 0; 1488} 1489 1490/* Execute triggered update. */ 1491int 1492ripng_triggered_update (struct thread *t) 1493{ 1494 struct listnode *node; 1495 struct interface *ifp; 1496 struct ripng_interface *ri; 1497 int interval; 1498 1499 ripng->t_triggered_update = NULL; 1500 1501 /* Cancel interval timer. */ 1502 if (ripng->t_triggered_interval) 1503 { 1504 thread_cancel (ripng->t_triggered_interval); 1505 ripng->t_triggered_interval = NULL; 1506 } 1507 ripng->trigger = 0; 1508 1509 /* Logging triggered update. */ 1510 if (IS_RIPNG_DEBUG_EVENT) 1511 zlog_debug ("RIPng triggered update!"); 1512 1513 /* Split Horizon processing is done when generating triggered 1514 updates as well as normal updates (see section 2.6). */ 1515 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 1516 { 1517 ri = ifp->info; 1518 1519 if (if_is_loopback (ifp) || ! if_is_up (ifp)) 1520 continue; 1521 1522 if (! ri->running) 1523 continue; 1524 1525 /* When passive interface is specified, suppress announce to the 1526 interface. */ 1527 if (ri->passive) 1528 continue; 1529 1530 ripng_output_process (ifp, NULL, ripng_changed_route); 1531 } 1532 1533 /* Once all of the triggered updates have been generated, the route 1534 change flags should be cleared. */ 1535 ripng_clear_changed_flag (); 1536 1537 /* After a triggered update is sent, a timer should be set for a 1538 random interval between 1 and 5 seconds. If other changes that 1539 would trigger updates occur before the timer expires, a single 1540 update is triggered when the timer expires. */ 1541 interval = (random () % 5) + 1; 1542 1543 ripng->t_triggered_interval = 1544 thread_add_timer (master, ripng_triggered_interval, NULL, interval); 1545 1546 return 0; 1547} 1548 1549/* Write routing table entry to the stream and return next index of 1550 the routing table entry in the stream. */ 1551int 1552ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p, 1553 struct in6_addr *nexthop, u_int16_t tag, u_char metric) 1554{ 1555 /* RIPng packet header. */ 1556 if (num == 0) 1557 { 1558 stream_putc (s, RIPNG_RESPONSE); 1559 stream_putc (s, RIPNG_V1); 1560 stream_putw (s, 0); 1561 } 1562 1563 /* Write routing table entry. */ 1564 if (!nexthop) 1565 stream_write (s, (u_char *) &p->prefix, sizeof (struct in6_addr)); 1566 else 1567 stream_write (s, (u_char *) nexthop, sizeof (struct in6_addr)); 1568 stream_putw (s, tag); 1569 if (p) 1570 stream_putc (s, p->prefixlen); 1571 else 1572 stream_putc (s, 0); 1573 stream_putc (s, metric); 1574 1575 return ++num; 1576} 1577 1578/* Send RESPONSE message to specified destination. */ 1579void 1580ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to, 1581 int route_type) 1582{ 1583 int ret; 1584 struct route_node *rp; 1585 struct ripng_info *rinfo; 1586 struct ripng_interface *ri; 1587 struct ripng_aggregate *aggregate; 1588 struct prefix_ipv6 *p; 1589 struct list * ripng_rte_list; 1590 1591 if (IS_RIPNG_DEBUG_EVENT) { 1592 if (to) 1593 zlog_debug ("RIPng update routes to neighbor %s", 1594 inet6_ntoa(to->sin6_addr)); 1595 else 1596 zlog_debug ("RIPng update routes on interface %s", ifp->name); 1597 } 1598 1599 /* Get RIPng interface. */ 1600 ri = ifp->info; 1601 1602 ripng_rte_list = ripng_rte_new(); 1603 1604 for (rp = route_top (ripng->table); rp; rp = route_next (rp)) 1605 { 1606 if ((rinfo = rp->info) != NULL && rinfo->suppress == 0) 1607 { 1608 /* If no route-map are applied, the RTE will be these following 1609 * informations. 1610 */ 1611 p = (struct prefix_ipv6 *) &rp->p; 1612 rinfo->metric_out = rinfo->metric; 1613 rinfo->tag_out = rinfo->tag; 1614 memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out)); 1615 /* In order to avoid some local loops, 1616 * if the RIPng route has a nexthop via this interface, keep the nexthop, 1617 * otherwise set it to 0. The nexthop should not be propagated 1618 * beyond the local broadcast/multicast area in order 1619 * to avoid an IGP multi-level recursive look-up. 1620 */ 1621 if (rinfo->ifindex == ifp->ifindex) 1622 rinfo->nexthop_out = rinfo->nexthop; 1623 1624 /* Apply output filters. */ 1625 ret = ripng_outgoing_filter (p, ri); 1626 if (ret < 0) 1627 continue; 1628 1629 /* Changed route only output. */ 1630 if (route_type == ripng_changed_route && 1631 (! (rinfo->flags & RIPNG_RTF_CHANGED))) 1632 continue; 1633 1634 /* Split horizon. */ 1635 if (ri->split_horizon == RIPNG_SPLIT_HORIZON) 1636 { 1637 /* We perform split horizon for RIPng routes. */ 1638 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && 1639 rinfo->ifindex == ifp->ifindex) 1640 continue; 1641 } 1642 1643 /* Preparation for route-map. */ 1644 rinfo->metric_set = 0; 1645 /* nexthop_out, 1646 * metric_out 1647 * and tag_out are already initialized. 1648 */ 1649 1650 /* Interface route-map */ 1651 if (ri->routemap[RIPNG_FILTER_OUT]) 1652 { 1653 int ret; 1654 1655 ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], 1656 (struct prefix *) p, RMAP_RIPNG, 1657 rinfo); 1658 1659 if (ret == RMAP_DENYMATCH) 1660 { 1661 if (IS_RIPNG_DEBUG_PACKET) 1662 zlog_debug ("RIPng %s/%d is filtered by route-map out", 1663 inet6_ntoa (p->prefix), p->prefixlen); 1664 continue; 1665 } 1666 1667 } 1668 1669 /* Redistribute route-map. */ 1670 if (ripng->route_map[rinfo->type].name) 1671 { 1672 int ret; 1673 1674 ret = route_map_apply (ripng->route_map[rinfo->type].map, 1675 (struct prefix *) p, RMAP_RIPNG, 1676 rinfo); 1677 1678 if (ret == RMAP_DENYMATCH) 1679 { 1680 if (IS_RIPNG_DEBUG_PACKET) 1681 zlog_debug ("RIPng %s/%d is filtered by route-map", 1682 inet6_ntoa (p->prefix), p->prefixlen); 1683 continue; 1684 } 1685 } 1686 1687 /* When the route-map does not set metric. */ 1688 if (! rinfo->metric_set) 1689 { 1690 /* If the redistribute metric is set. */ 1691 if (ripng->route_map[rinfo->type].metric_config 1692 && rinfo->metric != RIPNG_METRIC_INFINITY) 1693 { 1694 rinfo->metric_out = ripng->route_map[rinfo->type].metric; 1695 } 1696 else 1697 { 1698 /* If the route is not connected or localy generated 1699 one, use default-metric value */ 1700 if (rinfo->type != ZEBRA_ROUTE_RIPNG 1701 && rinfo->type != ZEBRA_ROUTE_CONNECT 1702 && rinfo->metric != RIPNG_METRIC_INFINITY) 1703 rinfo->metric_out = ripng->default_metric; 1704 } 1705 } 1706 1707 /* Apply offset-list */ 1708 if (rinfo->metric_out != RIPNG_METRIC_INFINITY) 1709 ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out); 1710 1711 if (rinfo->metric_out > RIPNG_METRIC_INFINITY) 1712 rinfo->metric_out = RIPNG_METRIC_INFINITY; 1713 1714 /* Perform split-horizon with poisoned reverse 1715 * for RIPng routes. 1716 **/ 1717 if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) { 1718 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && 1719 rinfo->ifindex == ifp->ifindex) 1720 rinfo->metric_out = RIPNG_METRIC_INFINITY; 1721 } 1722 1723 /* Add RTE to the list */ 1724 ripng_rte_add(ripng_rte_list, p, rinfo, NULL); 1725 } 1726 1727 /* Process the aggregated RTE entry */ 1728 if ((aggregate = rp->aggregate) != NULL && 1729 aggregate->count > 0 && 1730 aggregate->suppress == 0) 1731 { 1732 /* If no route-map are applied, the RTE will be these following 1733 * informations. 1734 */ 1735 p = (struct prefix_ipv6 *) &rp->p; 1736 aggregate->metric_set = 0; 1737 aggregate->metric_out = aggregate->metric; 1738 aggregate->tag_out = aggregate->tag; 1739 memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out)); 1740 1741 /* Apply output filters.*/ 1742 ret = ripng_outgoing_filter (p, ri); 1743 if (ret < 0) 1744 continue; 1745 1746 /* Interface route-map */ 1747 if (ri->routemap[RIPNG_FILTER_OUT]) 1748 { 1749 int ret; 1750 struct ripng_info newinfo; 1751 1752 /* let's cast the aggregate structure to ripng_info */ 1753 memset (&newinfo, 0, sizeof (struct ripng_info)); 1754 /* the nexthop is :: */ 1755 newinfo.metric = aggregate->metric; 1756 newinfo.metric_out = aggregate->metric_out; 1757 newinfo.tag = aggregate->tag; 1758 newinfo.tag_out = aggregate->tag_out; 1759 1760 ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], 1761 (struct prefix *) p, RMAP_RIPNG, 1762 &newinfo); 1763 1764 if (ret == RMAP_DENYMATCH) 1765 { 1766 if (IS_RIPNG_DEBUG_PACKET) 1767 zlog_debug ("RIPng %s/%d is filtered by route-map out", 1768 inet6_ntoa (p->prefix), p->prefixlen); 1769 continue; 1770 } 1771 1772 aggregate->metric_out = newinfo.metric_out; 1773 aggregate->tag_out = newinfo.tag_out; 1774 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out)) 1775 aggregate->nexthop_out = newinfo.nexthop_out; 1776 } 1777 1778 /* There is no redistribute routemap for the aggregated RTE */ 1779 1780 /* Changed route only output. */ 1781 /* XXX, vincent, in order to increase time convergence, 1782 * it should be announced if a child has changed. 1783 */ 1784 if (route_type == ripng_changed_route) 1785 continue; 1786 1787 /* Apply offset-list */ 1788 if (aggregate->metric_out != RIPNG_METRIC_INFINITY) 1789 ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out); 1790 1791 if (aggregate->metric_out > RIPNG_METRIC_INFINITY) 1792 aggregate->metric_out = RIPNG_METRIC_INFINITY; 1793 1794 /* Add RTE to the list */ 1795 ripng_rte_add(ripng_rte_list, p, NULL, aggregate); 1796 } 1797 1798 } 1799 1800 /* Flush the list */ 1801 ripng_rte_send(ripng_rte_list, ifp, to); 1802 ripng_rte_free(ripng_rte_list); 1803} 1804 1805/* Create new RIPng instance and set it to global variable. */ 1806static int 1807ripng_create (void) 1808{ 1809 /* ripng should be NULL. */ 1810 assert (ripng == NULL); 1811 1812 /* Allocaste RIPng instance. */ 1813 ripng = XCALLOC (MTYPE_RIPNG, sizeof (struct ripng)); 1814 1815 /* Default version and timer values. */ 1816 ripng->version = RIPNG_V1; 1817 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; 1818 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; 1819 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; 1820 ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; 1821 1822 /* Make buffer. */ 1823 ripng->ibuf = stream_new (RIPNG_MAX_PACKET_SIZE * 5); 1824 ripng->obuf = stream_new (RIPNG_MAX_PACKET_SIZE); 1825 1826 /* Initialize RIPng routig table. */ 1827 ripng->table = route_table_init (); 1828 ripng->route = route_table_init (); 1829 ripng->aggregate = route_table_init (); 1830 1831 /* Make socket. */ 1832 ripng->sock = ripng_make_socket (); 1833 if (ripng->sock < 0) 1834 return ripng->sock; 1835 1836 /* Threads. */ 1837 ripng_event (RIPNG_READ, ripng->sock); 1838 ripng_event (RIPNG_UPDATE_EVENT, 1); 1839 1840 return 0; 1841} 1842 1843/* Send RIPng request to the interface. */ 1844int 1845ripng_request (struct interface *ifp) 1846{ 1847 struct rte *rte; 1848 struct ripng_packet ripng_packet; 1849 1850 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */ 1851 if (if_is_loopback(ifp)) 1852 return 0; 1853 1854 /* If interface is down, don't send RIP packet. */ 1855 if (! if_is_up (ifp)) 1856 return 0; 1857 1858 if (IS_RIPNG_DEBUG_EVENT) 1859 zlog_debug ("RIPng send request to %s", ifp->name); 1860 1861 memset (&ripng_packet, 0, sizeof (ripng_packet)); 1862 ripng_packet.command = RIPNG_REQUEST; 1863 ripng_packet.version = RIPNG_V1; 1864 rte = ripng_packet.rte; 1865 rte->metric = RIPNG_METRIC_INFINITY; 1866 1867 return ripng_send_packet ((caddr_t) &ripng_packet, sizeof (ripng_packet), 1868 NULL, ifp); 1869} 1870 1871 1872static int 1873ripng_update_jitter (int time) 1874{ 1875 return ((rand () % (time + 1)) - (time / 2)); 1876} 1877 1878void 1879ripng_event (enum ripng_event event, int sock) 1880{ 1881 int jitter = 0; 1882 1883 switch (event) 1884 { 1885 case RIPNG_READ: 1886 if (!ripng->t_read) 1887 ripng->t_read = thread_add_read (master, ripng_read, NULL, sock); 1888 break; 1889 case RIPNG_UPDATE_EVENT: 1890 if (ripng->t_update) 1891 { 1892 thread_cancel (ripng->t_update); 1893 ripng->t_update = NULL; 1894 } 1895 /* Update timer jitter. */ 1896 jitter = ripng_update_jitter (ripng->update_time); 1897 1898 ripng->t_update = 1899 thread_add_timer (master, ripng_update, NULL, 1900 sock ? 2 : ripng->update_time + jitter); 1901 break; 1902 case RIPNG_TRIGGERED_UPDATE: 1903 if (ripng->t_triggered_interval) 1904 ripng->trigger = 1; 1905 else if (! ripng->t_triggered_update) 1906 ripng->t_triggered_update = 1907 thread_add_event (master, ripng_triggered_update, NULL, 0); 1908 break; 1909 default: 1910 break; 1911 } 1912} 1913 1914 1915/* Print out routes update time. */ 1916static void 1917ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo) 1918{ 1919 time_t clock; 1920 struct tm *tm; 1921#define TIME_BUF 25 1922 char timebuf [TIME_BUF]; 1923 struct thread *thread; 1924 1925 if ((thread = rinfo->t_timeout) != NULL) 1926 { 1927 clock = thread_timer_remain_second (thread); 1928 tm = gmtime (&clock); 1929 strftime (timebuf, TIME_BUF, "%M:%S", tm); 1930 vty_out (vty, "%5s", timebuf); 1931 } 1932 else if ((thread = rinfo->t_garbage_collect) != NULL) 1933 { 1934 clock = thread_timer_remain_second (thread); 1935 tm = gmtime (&clock); 1936 strftime (timebuf, TIME_BUF, "%M:%S", tm); 1937 vty_out (vty, "%5s", timebuf); 1938 } 1939} 1940 1941static char * 1942ripng_route_subtype_print (struct ripng_info *rinfo) 1943{ 1944 static char str[3]; 1945 memset(str, 0, 3); 1946 1947 if (rinfo->suppress) 1948 strcat(str, "S"); 1949 1950 switch (rinfo->sub_type) 1951 { 1952 case RIPNG_ROUTE_RTE: 1953 strcat(str, "n"); 1954 break; 1955 case RIPNG_ROUTE_STATIC: 1956 strcat(str, "s"); 1957 break; 1958 case RIPNG_ROUTE_DEFAULT: 1959 strcat(str, "d"); 1960 break; 1961 case RIPNG_ROUTE_REDISTRIBUTE: 1962 strcat(str, "r"); 1963 break; 1964 case RIPNG_ROUTE_INTERFACE: 1965 strcat(str, "i"); 1966 break; 1967 default: 1968 strcat(str, "?"); 1969 break; 1970 } 1971 1972 return str; 1973} 1974 1975DEFUN (show_ipv6_ripng, 1976 show_ipv6_ripng_cmd, 1977 "show ipv6 ripng", 1978 SHOW_STR 1979 IPV6_STR 1980 "Show RIPng routes\n") 1981{ 1982 struct route_node *rp; 1983 struct ripng_info *rinfo; 1984 struct ripng_aggregate *aggregate; 1985 struct prefix_ipv6 *p; 1986 int len; 1987 1988 if (! ripng) 1989 return CMD_SUCCESS; 1990 1991 /* Header of display. */ 1992 vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s" 1993 "Sub-codes:%s" 1994 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s" 1995 " (i) - interface, (a/S) - aggregated/Suppressed%s%s" 1996 " Network Next Hop Via Metric Tag Time%s", 1997 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, 1998 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); 1999 2000 for (rp = route_top (ripng->table); rp; rp = route_next (rp)) 2001 { 2002 if ((aggregate = rp->aggregate) != NULL) 2003 { 2004 p = (struct prefix_ipv6 *) &rp->p; 2005 2006#ifdef DEBUG 2007 len = vty_out (vty, "R(a) %d/%d %s/%d ", 2008 aggregate->count, aggregate->suppress, 2009 inet6_ntoa (p->prefix), p->prefixlen); 2010#else 2011 len = vty_out (vty, "R(a) %s/%d ", 2012 inet6_ntoa (p->prefix), p->prefixlen); 2013#endif /* DEBUG */ 2014 vty_out (vty, "%s", VTY_NEWLINE); 2015 vty_out (vty, "%*s", 18, " "); 2016 2017 vty_out (vty, "%*s", 28, " "); 2018 vty_out (vty, "self %2d %3d%s", aggregate->metric, 2019 aggregate->tag, 2020 VTY_NEWLINE); 2021 } 2022 2023 if ((rinfo = rp->info) != NULL) 2024 { 2025 p = (struct prefix_ipv6 *) &rp->p; 2026 2027#ifdef DEBUG 2028 len = vty_out (vty, "%c(%s) 0/%d %s/%d ", 2029 zebra_route_char(rinfo->type), 2030 ripng_route_subtype_print(rinfo), 2031 rinfo->suppress, 2032 inet6_ntoa (p->prefix), p->prefixlen); 2033#else 2034 len = vty_out (vty, "%c(%s) %s/%d ", 2035 zebra_route_char(rinfo->type), 2036 ripng_route_subtype_print(rinfo), 2037 inet6_ntoa (p->prefix), p->prefixlen); 2038#endif /* DEBUG */ 2039 vty_out (vty, "%s", VTY_NEWLINE); 2040 vty_out (vty, "%*s", 18, " "); 2041 len = vty_out (vty, "%s", inet6_ntoa (rinfo->nexthop)); 2042 2043 len = 28 - len; 2044 if (len > 0) 2045 len = vty_out (vty, "%*s", len, " "); 2046 2047 /* from */ 2048 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && 2049 (rinfo->sub_type == RIPNG_ROUTE_RTE)) 2050 { 2051 len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex)); 2052 } else if (rinfo->metric == RIPNG_METRIC_INFINITY) 2053 { 2054 len = vty_out (vty, "kill"); 2055 } else 2056 len = vty_out (vty, "self"); 2057 2058 len = 9 - len; 2059 if (len > 0) 2060 vty_out (vty, "%*s", len, " "); 2061 2062 vty_out (vty, " %2d %3d ", 2063 rinfo->metric, rinfo->tag); 2064 2065 /* time */ 2066 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && 2067 (rinfo->sub_type == RIPNG_ROUTE_RTE)) 2068 { 2069 /* RTE from remote RIP routers */ 2070 ripng_vty_out_uptime (vty, rinfo); 2071 } else if (rinfo->metric == RIPNG_METRIC_INFINITY) 2072 { 2073 /* poisonous reversed routes (gc) */ 2074 ripng_vty_out_uptime (vty, rinfo); 2075 } 2076 2077 vty_out (vty, "%s", VTY_NEWLINE); 2078 } 2079 } 2080 2081 return CMD_SUCCESS; 2082} 2083 2084DEFUN (show_ipv6_ripng_status, 2085 show_ipv6_ripng_status_cmd, 2086 "show ipv6 ripng status", 2087 SHOW_STR 2088 IPV6_STR 2089 "Show RIPng routes\n" 2090 "IPv6 routing protocol process parameters and statistics\n") 2091{ 2092 struct listnode *node; 2093 struct interface *ifp; 2094 2095 if (! ripng) 2096 return CMD_SUCCESS; 2097 2098 vty_out (vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE); 2099 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,", 2100 ripng->update_time); 2101 vty_out (vty, " next due in %lu seconds%s", 2102 thread_timer_remain_second (ripng->t_update), 2103 VTY_NEWLINE); 2104 vty_out (vty, " Timeout after %ld seconds,", ripng->timeout_time); 2105 vty_out (vty, " garbage collect after %ld seconds%s", ripng->garbage_time, 2106 VTY_NEWLINE); 2107 2108 /* Filtering status show. */ 2109 config_show_distribute (vty); 2110 2111 /* Default metric information. */ 2112 vty_out (vty, " Default redistribution metric is %d%s", 2113 ripng->default_metric, VTY_NEWLINE); 2114 2115 /* Redistribute information. */ 2116 vty_out (vty, " Redistributing:"); 2117 ripng_redistribute_write (vty, 0); 2118 vty_out (vty, "%s", VTY_NEWLINE); 2119 2120 vty_out (vty, " Default version control: send version %d,", ripng->version); 2121 vty_out (vty, " receive version %d %s", ripng->version, 2122 VTY_NEWLINE); 2123 2124 vty_out (vty, " Interface Send Recv%s", VTY_NEWLINE); 2125 2126 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 2127 { 2128 struct ripng_interface *ri; 2129 2130 ri = ifp->info; 2131 2132 if (ri->enable_network || ri->enable_interface) 2133 { 2134 2135 vty_out (vty, " %-17s%-3d %-3d%s", ifp->name, 2136 ripng->version, 2137 ripng->version, 2138 VTY_NEWLINE); 2139 } 2140 } 2141 2142 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE); 2143 ripng_network_write (vty, 0); 2144 2145 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE); 2146 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE); 2147 ripng_peer_display (vty); 2148 2149 return CMD_SUCCESS; 2150} 2151 2152DEFUN (router_ripng, 2153 router_ripng_cmd, 2154 "router ripng", 2155 "Enable a routing process\n" 2156 "Make RIPng instance command\n") 2157{ 2158 int ret; 2159 2160 vty->node = RIPNG_NODE; 2161 2162 if (!ripng) 2163 { 2164 ret = ripng_create (); 2165 2166 /* Notice to user we couldn't create RIPng. */ 2167 if (ret < 0) 2168 { 2169 zlog_warn ("can't create RIPng"); 2170 return CMD_WARNING; 2171 } 2172 } 2173 2174 return CMD_SUCCESS; 2175} 2176 2177DEFUN (no_router_ripng, 2178 no_router_ripng_cmd, 2179 "no router ripng", 2180 NO_STR 2181 "Enable a routing process\n" 2182 "Make RIPng instance command\n") 2183{ 2184 if(ripng) 2185 ripng_clean(); 2186 return CMD_SUCCESS; 2187} 2188 2189DEFUN (ripng_route, 2190 ripng_route_cmd, 2191 "route IPV6ADDR", 2192 "Static route setup\n" 2193 "Set static RIPng route announcement\n") 2194{ 2195 int ret; 2196 struct prefix_ipv6 p; 2197 struct route_node *rp; 2198 2199 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p); 2200 if (ret <= 0) 2201 { 2202 vty_out (vty, "Malformed address%s", VTY_NEWLINE); 2203 return CMD_WARNING; 2204 } 2205 apply_mask_ipv6 (&p); 2206 2207 rp = route_node_get (ripng->route, (struct prefix *) &p); 2208 if (rp->info) 2209 { 2210 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE); 2211 route_unlock_node (rp); 2212 return CMD_WARNING; 2213 } 2214 rp->info = (void *)1; 2215 2216 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL); 2217 2218 return CMD_SUCCESS; 2219} 2220 2221DEFUN (no_ripng_route, 2222 no_ripng_route_cmd, 2223 "no route IPV6ADDR", 2224 NO_STR 2225 "Static route setup\n" 2226 "Delete static RIPng route announcement\n") 2227{ 2228 int ret; 2229 struct prefix_ipv6 p; 2230 struct route_node *rp; 2231 2232 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p); 2233 if (ret <= 0) 2234 { 2235 vty_out (vty, "Malformed address%s", VTY_NEWLINE); 2236 return CMD_WARNING; 2237 } 2238 apply_mask_ipv6 (&p); 2239 2240 rp = route_node_lookup (ripng->route, (struct prefix *) &p); 2241 if (! rp) 2242 { 2243 vty_out (vty, "Can't find static route.%s", VTY_NEWLINE); 2244 return CMD_WARNING; 2245 } 2246 2247 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0); 2248 route_unlock_node (rp); 2249 2250 rp->info = NULL; 2251 route_unlock_node (rp); 2252 2253 return CMD_SUCCESS; 2254} 2255 2256DEFUN (ripng_aggregate_address, 2257 ripng_aggregate_address_cmd, 2258 "aggregate-address X:X::X:X/M", 2259 "Set aggregate RIPng route announcement\n" 2260 "Aggregate network\n") 2261{ 2262 int ret; 2263 struct prefix p; 2264 struct route_node *node; 2265 2266 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p); 2267 if (ret <= 0) 2268 { 2269 vty_out (vty, "Malformed address%s", VTY_NEWLINE); 2270 return CMD_WARNING; 2271 } 2272 2273 /* Check aggregate alredy exist or not. */ 2274 node = route_node_get (ripng->aggregate, &p); 2275 if (node->info) 2276 { 2277 vty_out (vty, "There is already same aggregate route.%s", VTY_NEWLINE); 2278 route_unlock_node (node); 2279 return CMD_WARNING; 2280 } 2281 node->info = (void *)1; 2282 2283 ripng_aggregate_add (&p); 2284 2285 return CMD_SUCCESS; 2286} 2287 2288DEFUN (no_ripng_aggregate_address, 2289 no_ripng_aggregate_address_cmd, 2290 "no aggregate-address X:X::X:X/M", 2291 NO_STR 2292 "Delete aggregate RIPng route announcement\n" 2293 "Aggregate network") 2294{ 2295 int ret; 2296 struct prefix p; 2297 struct route_node *rn; 2298 2299 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &p); 2300 if (ret <= 0) 2301 { 2302 vty_out (vty, "Malformed address%s", VTY_NEWLINE); 2303 return CMD_WARNING; 2304 } 2305 2306 rn = route_node_lookup (ripng->aggregate, &p); 2307 if (! rn) 2308 { 2309 vty_out (vty, "Can't find aggregate route.%s", VTY_NEWLINE); 2310 return CMD_WARNING; 2311 } 2312 route_unlock_node (rn); 2313 rn->info = NULL; 2314 route_unlock_node (rn); 2315 2316 ripng_aggregate_delete (&p); 2317 2318 return CMD_SUCCESS; 2319} 2320 2321DEFUN (ripng_default_metric, 2322 ripng_default_metric_cmd, 2323 "default-metric <1-16>", 2324 "Set a metric of redistribute routes\n" 2325 "Default metric\n") 2326{ 2327 if (ripng) 2328 { 2329 ripng->default_metric = atoi (argv[0]); 2330 } 2331 return CMD_SUCCESS; 2332} 2333 2334DEFUN (no_ripng_default_metric, 2335 no_ripng_default_metric_cmd, 2336 "no default-metric", 2337 NO_STR 2338 "Set a metric of redistribute routes\n" 2339 "Default metric\n") 2340{ 2341 if (ripng) 2342 { 2343 ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; 2344 } 2345 return CMD_SUCCESS; 2346} 2347 2348ALIAS (no_ripng_default_metric, 2349 no_ripng_default_metric_val_cmd, 2350 "no default-metric <1-16>", 2351 NO_STR 2352 "Set a metric of redistribute routes\n" 2353 "Default metric\n") 2354 2355#if 0 2356/* RIPng update timer setup. */ 2357DEFUN (ripng_update_timer, 2358 ripng_update_timer_cmd, 2359 "update-timer SECOND", 2360 "Set RIPng update timer in seconds\n" 2361 "Seconds\n") 2362{ 2363 unsigned long update; 2364 char *endptr = NULL; 2365 2366 update = strtoul (argv[0], &endptr, 10); 2367 if (update == ULONG_MAX || *endptr != '\0') 2368 { 2369 vty_out (vty, "update timer value error%s", VTY_NEWLINE); 2370 return CMD_WARNING; 2371 } 2372 2373 ripng->update_time = update; 2374 2375 ripng_event (RIPNG_UPDATE_EVENT, 0); 2376 return CMD_SUCCESS; 2377} 2378 2379DEFUN (no_ripng_update_timer, 2380 no_ripng_update_timer_cmd, 2381 "no update-timer SECOND", 2382 NO_STR 2383 "Unset RIPng update timer in seconds\n" 2384 "Seconds\n") 2385{ 2386 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; 2387 ripng_event (RIPNG_UPDATE_EVENT, 0); 2388 return CMD_SUCCESS; 2389} 2390 2391/* RIPng timeout timer setup. */ 2392DEFUN (ripng_timeout_timer, 2393 ripng_timeout_timer_cmd, 2394 "timeout-timer SECOND", 2395 "Set RIPng timeout timer in seconds\n" 2396 "Seconds\n") 2397{ 2398 unsigned long timeout; 2399 char *endptr = NULL; 2400 2401 timeout = strtoul (argv[0], &endptr, 10); 2402 if (timeout == ULONG_MAX || *endptr != '\0') 2403 { 2404 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE); 2405 return CMD_WARNING; 2406 } 2407 2408 ripng->timeout_time = timeout; 2409 2410 return CMD_SUCCESS; 2411} 2412 2413DEFUN (no_ripng_timeout_timer, 2414 no_ripng_timeout_timer_cmd, 2415 "no timeout-timer SECOND", 2416 NO_STR 2417 "Unset RIPng timeout timer in seconds\n" 2418 "Seconds\n") 2419{ 2420 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; 2421 return CMD_SUCCESS; 2422} 2423 2424/* RIPng garbage timer setup. */ 2425DEFUN (ripng_garbage_timer, 2426 ripng_garbage_timer_cmd, 2427 "garbage-timer SECOND", 2428 "Set RIPng garbage timer in seconds\n" 2429 "Seconds\n") 2430{ 2431 unsigned long garbage; 2432 char *endptr = NULL; 2433 2434 garbage = strtoul (argv[0], &endptr, 10); 2435 if (garbage == ULONG_MAX || *endptr != '\0') 2436 { 2437 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE); 2438 return CMD_WARNING; 2439 } 2440 2441 ripng->garbage_time = garbage; 2442 2443 return CMD_SUCCESS; 2444} 2445 2446DEFUN (no_ripng_garbage_timer, 2447 no_ripng_garbage_timer_cmd, 2448 "no garbage-timer SECOND", 2449 NO_STR 2450 "Unset RIPng garbage timer in seconds\n" 2451 "Seconds\n") 2452{ 2453 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; 2454 return CMD_SUCCESS; 2455} 2456#endif /* 0 */ 2457 2458DEFUN (ripng_timers, 2459 ripng_timers_cmd, 2460 "timers basic <0-65535> <0-65535> <0-65535>", 2461 "RIPng timers setup\n" 2462 "Basic timer\n" 2463 "Routing table update timer value in second. Default is 30.\n" 2464 "Routing information timeout timer. Default is 180.\n" 2465 "Garbage collection timer. Default is 120.\n") 2466{ 2467 unsigned long update; 2468 unsigned long timeout; 2469 unsigned long garbage; 2470 2471 VTY_GET_INTEGER_RANGE("update timer", update, argv[0], 0, 65535); 2472 VTY_GET_INTEGER_RANGE("timeout timer", timeout, argv[1], 0, 65535); 2473 VTY_GET_INTEGER_RANGE("garbage timer", garbage, argv[2], 0, 65535); 2474 2475 /* Set each timer value. */ 2476 ripng->update_time = update; 2477 ripng->timeout_time = timeout; 2478 ripng->garbage_time = garbage; 2479 2480 /* Reset update timer thread. */ 2481 ripng_event (RIPNG_UPDATE_EVENT, 0); 2482 2483 return CMD_SUCCESS; 2484} 2485 2486DEFUN (no_ripng_timers, 2487 no_ripng_timers_cmd, 2488 "no timers basic", 2489 NO_STR 2490 "RIPng timers setup\n" 2491 "Basic timer\n") 2492{ 2493 /* Set each timer value to the default. */ 2494 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; 2495 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; 2496 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; 2497 2498 /* Reset update timer thread. */ 2499 ripng_event (RIPNG_UPDATE_EVENT, 0); 2500 2501 return CMD_SUCCESS; 2502} 2503 2504ALIAS (no_ripng_timers, 2505 no_ripng_timers_val_cmd, 2506 "no timers basic <0-65535> <0-65535> <0-65535>", 2507 NO_STR 2508 "RIPng timers setup\n" 2509 "Basic timer\n" 2510 "Routing table update timer value in second. Default is 30.\n" 2511 "Routing information timeout timer. Default is 180.\n" 2512 "Garbage collection timer. Default is 120.\n") 2513 2514DEFUN (show_ipv6_protocols, show_ipv6_protocols_cmd, 2515 "show ipv6 protocols", 2516 SHOW_STR 2517 IPV6_STR 2518 "Routing protocol information") 2519{ 2520 if (! ripng) 2521 return CMD_SUCCESS; 2522 2523 vty_out (vty, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE); 2524 2525 vty_out (vty, "Sending updates every %ld seconds, next due in %d seconds%s", 2526 ripng->update_time, 0, 2527 VTY_NEWLINE); 2528 2529 vty_out (vty, "Timerout after %ld seconds, garbage correct %ld%s", 2530 ripng->timeout_time, 2531 ripng->garbage_time, 2532 VTY_NEWLINE); 2533 2534 vty_out (vty, "Outgoing update filter list for all interfaces is not set"); 2535 vty_out (vty, "Incoming update filter list for all interfaces is not set"); 2536 2537 return CMD_SUCCESS; 2538} 2539 2540/* Please be carefull to use this command. */ 2541DEFUN (ripng_default_information_originate, 2542 ripng_default_information_originate_cmd, 2543 "default-information originate", 2544 "Default route information\n" 2545 "Distribute default route\n") 2546{ 2547 struct prefix_ipv6 p; 2548 2549 if (! ripng ->default_information) { 2550 ripng->default_information = 1; 2551 2552 str2prefix_ipv6 ("::/0", &p); 2553 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL); 2554 } 2555 2556 return CMD_SUCCESS; 2557} 2558 2559DEFUN (no_ripng_default_information_originate, 2560 no_ripng_default_information_originate_cmd, 2561 "no default-information originate", 2562 NO_STR 2563 "Default route information\n" 2564 "Distribute default route\n") 2565{ 2566 struct prefix_ipv6 p; 2567 2568 if (ripng->default_information) { 2569 ripng->default_information = 0; 2570 2571 str2prefix_ipv6 ("::/0", &p); 2572 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0); 2573 } 2574 2575 return CMD_SUCCESS; 2576} 2577 2578/* RIPng configuration write function. */ 2579static int 2580ripng_config_write (struct vty *vty) 2581{ 2582 int ripng_network_write (struct vty *, int); 2583 void ripng_redistribute_write (struct vty *, int); 2584 int write = 0; 2585 struct route_node *rp; 2586 2587 if (ripng) 2588 { 2589 2590 /* RIPng router. */ 2591 vty_out (vty, "router ripng%s", VTY_NEWLINE); 2592 2593 if (ripng->default_information) 2594 vty_out (vty, " default-information originate%s", VTY_NEWLINE); 2595 2596 ripng_network_write (vty, 1); 2597 2598 /* RIPng default metric configuration */ 2599 if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT) 2600 vty_out (vty, " default-metric %d%s", 2601 ripng->default_metric, VTY_NEWLINE); 2602 2603 ripng_redistribute_write (vty, 1); 2604 2605 /* RIP offset-list configuration. */ 2606 config_write_ripng_offset_list (vty); 2607 2608 /* RIPng aggregate routes. */ 2609 for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp)) 2610 if (rp->info != NULL) 2611 vty_out (vty, " aggregate-address %s/%d%s", 2612 inet6_ntoa (rp->p.u.prefix6), 2613 rp->p.prefixlen, 2614 2615 VTY_NEWLINE); 2616 2617 /* RIPng static routes. */ 2618 for (rp = route_top (ripng->route); rp; rp = route_next (rp)) 2619 if (rp->info != NULL) 2620 vty_out (vty, " route %s/%d%s", inet6_ntoa (rp->p.u.prefix6), 2621 rp->p.prefixlen, 2622 VTY_NEWLINE); 2623 2624 /* RIPng timers configuration. */ 2625 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT || 2626 ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT || 2627 ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT) 2628 { 2629 vty_out (vty, " timers basic %ld %ld %ld%s", 2630 ripng->update_time, 2631 ripng->timeout_time, 2632 ripng->garbage_time, 2633 VTY_NEWLINE); 2634 } 2635#if 0 2636 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT) 2637 vty_out (vty, " update-timer %d%s", ripng->update_time, 2638 VTY_NEWLINE); 2639 if (ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT) 2640 vty_out (vty, " timeout-timer %d%s", ripng->timeout_time, 2641 VTY_NEWLINE); 2642 if (ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT) 2643 vty_out (vty, " garbage-timer %d%s", ripng->garbage_time, 2644 VTY_NEWLINE); 2645#endif /* 0 */ 2646 2647 write += config_write_distribute (vty); 2648 2649 write += config_write_if_rmap (vty); 2650 2651 write++; 2652 } 2653 return write; 2654} 2655 2656/* RIPng node structure. */ 2657static struct cmd_node cmd_ripng_node = 2658{ 2659 RIPNG_NODE, 2660 "%s(config-router)# ", 2661 1, 2662}; 2663 2664static void 2665ripng_distribute_update (struct distribute *dist) 2666{ 2667 struct interface *ifp; 2668 struct ripng_interface *ri; 2669 struct access_list *alist; 2670 struct prefix_list *plist; 2671 2672 if (! dist->ifname) 2673 return; 2674 2675 ifp = if_lookup_by_name (dist->ifname); 2676 if (ifp == NULL) 2677 return; 2678 2679 ri = ifp->info; 2680 2681 if (dist->list[DISTRIBUTE_IN]) 2682 { 2683 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]); 2684 if (alist) 2685 ri->list[RIPNG_FILTER_IN] = alist; 2686 else 2687 ri->list[RIPNG_FILTER_IN] = NULL; 2688 } 2689 else 2690 ri->list[RIPNG_FILTER_IN] = NULL; 2691 2692 if (dist->list[DISTRIBUTE_OUT]) 2693 { 2694 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]); 2695 if (alist) 2696 ri->list[RIPNG_FILTER_OUT] = alist; 2697 else 2698 ri->list[RIPNG_FILTER_OUT] = NULL; 2699 } 2700 else 2701 ri->list[RIPNG_FILTER_OUT] = NULL; 2702 2703 if (dist->prefix[DISTRIBUTE_IN]) 2704 { 2705 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]); 2706 if (plist) 2707 ri->prefix[RIPNG_FILTER_IN] = plist; 2708 else 2709 ri->prefix[RIPNG_FILTER_IN] = NULL; 2710 } 2711 else 2712 ri->prefix[RIPNG_FILTER_IN] = NULL; 2713 2714 if (dist->prefix[DISTRIBUTE_OUT]) 2715 { 2716 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]); 2717 if (plist) 2718 ri->prefix[RIPNG_FILTER_OUT] = plist; 2719 else 2720 ri->prefix[RIPNG_FILTER_OUT] = NULL; 2721 } 2722 else 2723 ri->prefix[RIPNG_FILTER_OUT] = NULL; 2724} 2725 2726void 2727ripng_distribute_update_interface (struct interface *ifp) 2728{ 2729 struct distribute *dist; 2730 2731 dist = distribute_lookup (ifp->name); 2732 if (dist) 2733 ripng_distribute_update (dist); 2734} 2735 2736/* Update all interface's distribute list. */ 2737static void 2738ripng_distribute_update_all (struct prefix_list *notused) 2739{ 2740 struct interface *ifp; 2741 struct listnode *node; 2742 2743 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 2744 ripng_distribute_update_interface (ifp); 2745} 2746 2747static void 2748ripng_distribute_update_all_wrapper (struct access_list *notused) 2749{ 2750 ripng_distribute_update_all(NULL); 2751} 2752 2753/* delete all the added ripng routes. */ 2754void 2755ripng_clean() 2756{ 2757 int i; 2758 struct route_node *rp; 2759 struct ripng_info *rinfo; 2760 2761 if (ripng) { 2762 /* Clear RIPng routes */ 2763 for (rp = route_top (ripng->table); rp; rp = route_next (rp)) { 2764 if ((rinfo = rp->info) != NULL) { 2765 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && 2766 (rinfo->sub_type == RIPNG_ROUTE_RTE)) 2767 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, 2768 &rinfo->nexthop, rinfo->metric); 2769 2770 RIPNG_TIMER_OFF (rinfo->t_timeout); 2771 RIPNG_TIMER_OFF (rinfo->t_garbage_collect); 2772 2773 rp->info = NULL; 2774 route_unlock_node (rp); 2775 2776 ripng_info_free(rinfo); 2777 } 2778 } 2779 2780 /* Cancel the RIPng timers */ 2781 RIPNG_TIMER_OFF (ripng->t_update); 2782 RIPNG_TIMER_OFF (ripng->t_triggered_update); 2783 RIPNG_TIMER_OFF (ripng->t_triggered_interval); 2784 2785 /* Cancel the read thread */ 2786 if (ripng->t_read) { 2787 thread_cancel (ripng->t_read); 2788 ripng->t_read = NULL; 2789 } 2790 2791 /* Close the RIPng socket */ 2792 if (ripng->sock >= 0) { 2793 close(ripng->sock); 2794 ripng->sock = -1; 2795 } 2796 2797 /* Static RIPng route configuration. */ 2798 for (rp = route_top (ripng->route); rp; rp = route_next (rp)) 2799 if (rp->info) { 2800 rp->info = NULL; 2801 route_unlock_node (rp); 2802 } 2803 2804 /* RIPng aggregated prefixes */ 2805 for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp)) 2806 if (rp->info) { 2807 rp->info = NULL; 2808 route_unlock_node (rp); 2809 } 2810 2811 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 2812 if (ripng->route_map[i].name) 2813 free (ripng->route_map[i].name); 2814 2815 XFREE (MTYPE_ROUTE_TABLE, ripng->table); 2816 XFREE (MTYPE_ROUTE_TABLE, ripng->route); 2817 XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate); 2818 2819 XFREE (MTYPE_RIPNG, ripng); 2820 ripng = NULL; 2821 } /* if (ripng) */ 2822 2823 ripng_clean_network(); 2824 ripng_passive_interface_clean (); 2825 ripng_offset_clean (); 2826 ripng_interface_clean (); 2827 ripng_redistribute_clean (); 2828} 2829 2830/* Reset all values to the default settings. */ 2831void 2832ripng_reset () 2833{ 2834 /* Call ripd related reset functions. */ 2835 ripng_debug_reset (); 2836 ripng_route_map_reset (); 2837 2838 /* Call library reset functions. */ 2839 vty_reset (); 2840 access_list_reset (); 2841 prefix_list_reset (); 2842 2843 distribute_list_reset (); 2844 2845 ripng_interface_reset (); 2846 2847 ripng_zclient_reset (); 2848} 2849 2850static void 2851ripng_if_rmap_update (struct if_rmap *if_rmap) 2852{ 2853 struct interface *ifp; 2854 struct ripng_interface *ri; 2855 struct route_map *rmap; 2856 2857 ifp = if_lookup_by_name (if_rmap->ifname); 2858 if (ifp == NULL) 2859 return; 2860 2861 ri = ifp->info; 2862 2863 if (if_rmap->routemap[IF_RMAP_IN]) 2864 { 2865 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]); 2866 if (rmap) 2867 ri->routemap[IF_RMAP_IN] = rmap; 2868 else 2869 ri->routemap[IF_RMAP_IN] = NULL; 2870 } 2871 else 2872 ri->routemap[RIPNG_FILTER_IN] = NULL; 2873 2874 if (if_rmap->routemap[IF_RMAP_OUT]) 2875 { 2876 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]); 2877 if (rmap) 2878 ri->routemap[IF_RMAP_OUT] = rmap; 2879 else 2880 ri->routemap[IF_RMAP_OUT] = NULL; 2881 } 2882 else 2883 ri->routemap[RIPNG_FILTER_OUT] = NULL; 2884} 2885 2886void 2887ripng_if_rmap_update_interface (struct interface *ifp) 2888{ 2889 struct if_rmap *if_rmap; 2890 2891 if_rmap = if_rmap_lookup (ifp->name); 2892 if (if_rmap) 2893 ripng_if_rmap_update (if_rmap); 2894} 2895 2896static void 2897ripng_routemap_update_redistribute (void) 2898{ 2899 int i; 2900 2901 if (ripng) 2902 { 2903 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 2904 { 2905 if (ripng->route_map[i].name) 2906 ripng->route_map[i].map = 2907 route_map_lookup_by_name (ripng->route_map[i].name); 2908 } 2909 } 2910} 2911 2912static void 2913ripng_routemap_update (const char *unused) 2914{ 2915 struct interface *ifp; 2916 struct listnode *node; 2917 2918 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 2919 ripng_if_rmap_update_interface (ifp); 2920 2921 ripng_routemap_update_redistribute (); 2922} 2923 2924/* Initialize ripng structure and set commands. */ 2925void 2926ripng_init () 2927{ 2928 /* Randomize. */ 2929 srand (time (NULL)); 2930 2931 /* Install RIPNG_NODE. */ 2932 install_node (&cmd_ripng_node, ripng_config_write); 2933 2934 /* Install ripng commands. */ 2935 install_element (VIEW_NODE, &show_ipv6_ripng_cmd); 2936 install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd); 2937 2938 install_element (ENABLE_NODE, &show_ipv6_ripng_cmd); 2939 install_element (ENABLE_NODE, &show_ipv6_ripng_status_cmd); 2940 2941 install_element (CONFIG_NODE, &router_ripng_cmd); 2942 install_element (CONFIG_NODE, &no_router_ripng_cmd); 2943 2944 install_default (RIPNG_NODE); 2945 install_element (RIPNG_NODE, &ripng_route_cmd); 2946 install_element (RIPNG_NODE, &no_ripng_route_cmd); 2947 install_element (RIPNG_NODE, &ripng_aggregate_address_cmd); 2948 install_element (RIPNG_NODE, &no_ripng_aggregate_address_cmd); 2949 2950 install_element (RIPNG_NODE, &ripng_default_metric_cmd); 2951 install_element (RIPNG_NODE, &no_ripng_default_metric_cmd); 2952 install_element (RIPNG_NODE, &no_ripng_default_metric_val_cmd); 2953 2954 install_element (RIPNG_NODE, &ripng_timers_cmd); 2955 install_element (RIPNG_NODE, &no_ripng_timers_cmd); 2956 install_element (RIPNG_NODE, &no_ripng_timers_val_cmd); 2957#if 0 2958 install_element (RIPNG_NODE, &ripng_update_timer_cmd); 2959 install_element (RIPNG_NODE, &no_ripng_update_timer_cmd); 2960 install_element (RIPNG_NODE, &ripng_timeout_timer_cmd); 2961 install_element (RIPNG_NODE, &no_ripng_timeout_timer_cmd); 2962 install_element (RIPNG_NODE, &ripng_garbage_timer_cmd); 2963 install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd); 2964#endif /* 0 */ 2965 2966 install_element (RIPNG_NODE, &ripng_default_information_originate_cmd); 2967 install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd); 2968 2969 ripng_if_init (); 2970 ripng_debug_init (); 2971 2972 /* Access list install. */ 2973 access_list_init (); 2974 access_list_add_hook (ripng_distribute_update_all_wrapper); 2975 access_list_delete_hook (ripng_distribute_update_all_wrapper); 2976 2977 /* Prefix list initialize.*/ 2978 prefix_list_init (); 2979 prefix_list_add_hook (ripng_distribute_update_all); 2980 prefix_list_delete_hook (ripng_distribute_update_all); 2981 2982 /* Distribute list install. */ 2983 distribute_list_init (RIPNG_NODE); 2984 distribute_list_add_hook (ripng_distribute_update); 2985 distribute_list_delete_hook (ripng_distribute_update); 2986 2987 /* Route-map for interface. */ 2988 ripng_route_map_init (); 2989 ripng_offset_init (); 2990 2991 route_map_add_hook (ripng_routemap_update); 2992 route_map_delete_hook (ripng_routemap_update); 2993 2994 if_rmap_init (RIPNG_NODE); 2995 if_rmap_hook_add (ripng_if_rmap_update); 2996 if_rmap_hook_delete (ripng_if_rmap_update); 2997} 2998