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