1/* RIP version 1 and 2. 2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org> 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 "if.h" 25#include "command.h" 26#include "prefix.h" 27#include "table.h" 28#include "thread.h" 29#include "memory.h" 30#include "log.h" 31#include "stream.h" 32#include "filter.h" 33#include "sockunion.h" 34#include "routemap.h" 35#include "plist.h" 36#include "distribute.h" 37#include "md5-gnu.h" 38#include "keychain.h" 39 40#include "ripd/ripd.h" 41#include "ripd/rip_debug.h" 42 43/* RIP Structure. */ 44struct rip *rip = NULL; 45 46/* RIP neighbor address table. */ 47struct route_table *rip_neighbor_table; 48 49/* RIP route changes. */ 50long rip_global_route_changes = 0; 51 52/* RIP queries. */ 53long rip_global_queries = 0; 54 55/* Prototypes. */ 56void rip_event (enum rip_event, int); 57 58void rip_output_process (struct interface *, struct sockaddr_in *, 59 int, u_char); 60 61/* RIP output routes type. */ 62enum 63{ 64 rip_all_route, 65 rip_changed_route 66}; 67 68/* RIP command strings. */ 69struct message rip_msg[] = 70{ 71 {RIP_REQUEST, "REQUEST"}, 72 {RIP_RESPONSE, "RESPONSE"}, 73 {RIP_TRACEON, "TRACEON"}, 74 {RIP_TRACEOFF, "TRACEOFF"}, 75 {RIP_POLL, "POLL"}, 76 {RIP_POLL_ENTRY, "POLL ENTRY"}, 77 {0, NULL} 78}; 79 80/* Each route type's strings and default preference. */ 81struct 82{ 83 int key; 84 char *str; 85 char *str_long; 86} route_info[] = 87{ 88 { ZEBRA_ROUTE_SYSTEM, "X", "system"}, 89 { ZEBRA_ROUTE_KERNEL, "K", "kernel"}, 90 { ZEBRA_ROUTE_CONNECT, "C", "connected"}, 91 { ZEBRA_ROUTE_STATIC, "S", "static"}, 92 { ZEBRA_ROUTE_RIP, "R", "rip"}, 93 { ZEBRA_ROUTE_RIPNG, "R", "ripng"}, 94 { ZEBRA_ROUTE_OSPF, "O", "ospf"}, 95 { ZEBRA_ROUTE_OSPF6, "O", "ospf6"}, 96 { ZEBRA_ROUTE_BGP, "B", "bgp"} 97}; 98 99/* foxconn added start by EricHuang, 11/05/2007 */ 100//#ifdef U12H072 101/* Foxconn mark start by aspen Bai, 07/17/2008 */ 102//#if (defined(U12H072) || defined(U12H083) || defined(U12H081)) 103/* Foxconn mark end by aspen Bai, 07/17/2008 */ 104#define max_fox_rt_info 32 105 106struct fox_rt_info { 107 int metric; 108 struct in_addr prefix __attribute__ ((aligned (8))); 109}; 110 111struct fox_rt_info fox_rt_info_table[max_fox_rt_info]; 112 113#include "if.h" 114/* 115void my_log(char *string) 116{ 117 FILE *fd; 118 119 fd = fopen("/tmp/riplog", "a+"); 120 121 if (fd) 122 { 123 fprintf(fd, string); 124 fclose(fd); 125 } 126} 127*/ 128 129void fox_get_rtinfo() 130{ 131 FILE *fp; 132 char buf[128]; 133 char iface[32], dest[9], gate[9], mask[9]; 134 int flags, refcnt, use, metric, mtu, window, rtt; 135 int j=0; 136 137 /* Open /proc filesystem */ 138 fp = fopen ("/proc/net/route", "r"); 139 if (fp == NULL) 140 { 141 return; 142 } 143 144 /* Drop first label line. */ 145 fgets (buf, 128, fp); 146 147 while (fgets (buf, 128, fp) != NULL) 148 { 149 int n; 150 //char str[128]; 151 152 n = sscanf (buf, "%s %s %s %x %d %d %d %s %d %d %d", 153 iface, dest, gate, &flags, &refcnt, &use, &metric, 154 mask, &mtu, &window, &rtt); 155 if (n != 11) 156 { 157 continue; 158 } 159 if (! (flags & RTF_UP)) 160 continue; 161 if (! (flags & RTF_GATEWAY)) 162 continue; 163 164 sscanf (dest, "%lX", (unsigned long *)&fox_rt_info_table[j].prefix); 165 fox_rt_info_table[j].metric=metric; 166 167 //sprintf(str, "addr: %x, metric: %d\n", fox_rt_info_table[j].prefix, fox_rt_info_table[j].metric); 168 //my_log(str); 169 170 if ( j++ > max_fox_rt_info ) 171 break; 172 } 173 174 if (fp) 175 fclose(fp); 176} 177/* Foxconn mark start by aspen Bai, 07/17/2008 */ 178//#endif 179/* Foxconn mark end by aspen Bai, 07/17/2008 */ 180/* foxconn added end by EricHuang, 11/05/2007 */ 181 182 183/* Utility function to set boradcast option to the socket. */ 184int 185sockopt_broadcast (int sock) 186{ 187 int ret; 188 int on = 1; 189 190 ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on); 191 if (ret < 0) 192 { 193#ifdef FOX_RIP_DEBUG 194 zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock); 195#endif /* FOX_RIP_DEBUG */ 196 return -1; 197 } 198 return 0; 199} 200 201int 202rip_route_rte (struct rip_info *rinfo) 203{ 204 return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE); 205} 206 207struct rip_info * 208rip_info_new () 209{ 210 struct rip_info *new; 211 212 new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info)); 213 memset (new, 0, sizeof (struct rip_info)); 214 return new; 215} 216 217void 218rip_info_free (struct rip_info *rinfo) 219{ 220 XFREE (MTYPE_RIP_INFO, rinfo); 221} 222 223/* RIP route garbage collect timer. */ 224int 225rip_garbage_collect (struct thread *t) 226{ 227 struct rip_info *rinfo; 228 struct route_node *rp; 229 230 rinfo = THREAD_ARG (t); 231 rinfo->t_garbage_collect = NULL; 232 233 /* Off timeout timer. */ 234 RIP_TIMER_OFF (rinfo->t_timeout); 235 236 /* Get route_node pointer. */ 237 rp = rinfo->rp; 238 239 /* Unlock route_node. */ 240 rp->info = NULL; 241 route_unlock_node (rp); 242 243 /* Free RIP routing information. */ 244 rip_info_free (rinfo); 245 246 return 0; 247} 248 249/* Timeout RIP routes. */ 250int 251rip_timeout (struct thread *t) 252{ 253 struct rip_info *rinfo; 254 struct route_node *rn; 255 256 rinfo = THREAD_ARG (t); 257 rinfo->t_timeout = NULL; 258 259 rn = rinfo->rp; 260 261 /* - The garbage-collection timer is set for 120 seconds. */ 262 RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect, 263 rip->garbage_time); 264 265 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop, 266 rinfo->metric); 267 /* - The metric for the route is set to 16 (infinity). This causes 268 the route to be removed from service. */ 269 rinfo->metric = RIP_METRIC_INFINITY; 270 rinfo->flags &= ~RIP_RTF_FIB; 271 272 /* - The route change flag is to indicate that this entry has been 273 changed. */ 274 rinfo->flags |= RIP_RTF_CHANGED; 275 276 /* - The output process is signalled to trigger a response. */ 277 rip_event (RIP_TRIGGERED_UPDATE, 0); 278 279 return 0; 280} 281 282void 283rip_timeout_update (struct rip_info *rinfo) 284{ 285 if (rinfo->metric != RIP_METRIC_INFINITY) 286 { 287 RIP_TIMER_OFF (rinfo->t_timeout); 288 RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time); 289 } 290} 291 292int 293rip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri) 294{ 295 struct distribute *dist; 296 struct access_list *alist; 297 struct prefix_list *plist; 298 299 /* Input distribute-list filtering. */ 300 if (ri->list[RIP_FILTER_IN]) 301 { 302 if (access_list_apply (ri->list[RIP_FILTER_IN], 303 (struct prefix *) p) == FILTER_DENY) 304 { 305#ifdef FOX_RIP_DEBUG 306 if (IS_RIP_DEBUG_PACKET) 307 zlog_info ("%s/%d filtered by distribute in", 308 inet_ntoa (p->prefix), p->prefixlen); 309#endif /* FOX_RIP_DEBUG */ 310 return -1; 311 } 312 } 313#ifdef FOX_LIST_SUPPORT 314 if (ri->prefix[RIP_FILTER_IN]) 315 { 316 if (prefix_list_apply (ri->prefix[RIP_FILTER_IN], 317 (struct prefix *) p) == PREFIX_DENY) 318 { 319#ifdef FOX_RIP_DEBUG 320 if (IS_RIP_DEBUG_PACKET) 321 zlog_info ("%s/%d filtered by prefix-list in", 322 inet_ntoa (p->prefix), p->prefixlen); 323#endif /* FOX_RIP_DEBUG */ 324 return -1; 325 } 326 } 327#endif /* FOX_LIST_SUPPORT */ 328 329 /* All interface filter check. */ 330 dist = distribute_lookup (NULL); 331 if (dist) 332 { 333 if (dist->list[DISTRIBUTE_IN]) 334 { 335 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]); 336 337 if (alist) 338 { 339 if (access_list_apply (alist, 340 (struct prefix *) p) == FILTER_DENY) 341 { 342#ifdef FOX_RIP_DEBUG 343 if (IS_RIP_DEBUG_PACKET) 344 zlog_info ("%s/%d filtered by distribute in", 345 inet_ntoa (p->prefix), p->prefixlen); 346#endif /* FOX_RIP_DEBUG */ 347 return -1; 348 } 349 } 350 } 351#ifdef FOX_LIST_SUPPORT 352 if (dist->prefix[DISTRIBUTE_IN]) 353 { 354 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]); 355 356 if (plist) 357 { 358 if (prefix_list_apply (plist, 359 (struct prefix *) p) == PREFIX_DENY) 360 { 361#ifdef FOX_RIP_DEBUG 362 if (IS_RIP_DEBUG_PACKET) 363 zlog_info ("%s/%d filtered by prefix-list in", 364 inet_ntoa (p->prefix), p->prefixlen); 365#endif /* FOX_RIP_DEBUG */ 366 return -1; 367 } 368 } 369 } 370#endif /* FOX_LIST_SUPPORT */ 371 } 372 return 0; 373} 374 375int 376rip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri) 377{ 378 struct distribute *dist; 379 struct access_list *alist; 380 struct prefix_list *plist; 381 382 if (ri->list[RIP_FILTER_OUT]) 383 { 384 if (access_list_apply (ri->list[RIP_FILTER_OUT], 385 (struct prefix *) p) == FILTER_DENY) 386 { 387#ifdef FOX_RIP_DEBUG 388 if (IS_RIP_DEBUG_PACKET) 389 zlog_info ("%s/%d is filtered by distribute out", 390 inet_ntoa (p->prefix), p->prefixlen); 391#endif /* FOX_RIP_DEBUG */ 392 return -1; 393 } 394 } 395#ifdef FOX_LIST_SUPPORT 396 if (ri->prefix[RIP_FILTER_OUT]) 397 { 398 if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT], 399 (struct prefix *) p) == PREFIX_DENY) 400 { 401#ifdef FOX_RIP_DEBUG 402 if (IS_RIP_DEBUG_PACKET) 403 zlog_info ("%s/%d is filtered by prefix-list out", 404 inet_ntoa (p->prefix), p->prefixlen); 405#endif /* FOX_RIP_DEBUG */ 406 return -1; 407 } 408 } 409#endif /* FOX_LIST_SUPPORT */ 410 411 /* All interface filter check. */ 412 dist = distribute_lookup (NULL); 413 if (dist) 414 { 415 if (dist->list[DISTRIBUTE_OUT]) 416 { 417 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]); 418 419 if (alist) 420 { 421 if (access_list_apply (alist, 422 (struct prefix *) p) == FILTER_DENY) 423 { 424#ifdef FOX_RIP_DEBUG 425 if (IS_RIP_DEBUG_PACKET) 426 zlog_info ("%s/%d filtered by distribute out", 427 inet_ntoa (p->prefix), p->prefixlen); 428#endif /* FOX_RIP_DEBUG */ 429 return -1; 430 } 431 } 432 } 433#ifdef FOX_LIST_SUPPORT 434 if (dist->prefix[DISTRIBUTE_OUT]) 435 { 436 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]); 437 438 if (plist) 439 { 440 if (prefix_list_apply (plist, 441 (struct prefix *) p) == PREFIX_DENY) 442 { 443#ifdef FOX_RIP_DEBUG 444 if (IS_RIP_DEBUG_PACKET) 445 zlog_info ("%s/%d filtered by prefix-list out", 446 inet_ntoa (p->prefix), p->prefixlen); 447#endif /* FOX_RIP_DEBUG */ 448 return -1; 449 } 450 } 451 } 452#endif /* FOX_LIST_SUPPORT */ 453 } 454 return 0; 455} 456 457/* Check nexthop address validity. */ 458static int 459rip_nexthop_check (struct in_addr *addr) 460{ 461 listnode node; 462 listnode cnode; 463 struct interface *ifp; 464 struct connected *ifc; 465 struct prefix *p; 466 467 /* If nexthop address matches local configured address then it is 468 invalid nexthop. */ 469 for (node = listhead (iflist); node; nextnode (node)) 470 { 471 ifp = getdata (node); 472 473 for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) 474 { 475 ifc = getdata (cnode); 476 p = ifc->address; 477 478 if (p->family == AF_INET 479 && IPV4_ADDR_SAME (&p->u.prefix4, addr)) 480 return -1; 481 } 482 } 483 return 0; 484} 485 486/* RIP add route to routing table. */ 487void 488rip_rte_process (struct rte *rte, struct sockaddr_in *from, 489 struct interface *ifp) 490 491{ 492 int ret; 493 struct prefix_ipv4 p; 494 struct route_node *rp; 495 struct rip_info *rinfo; 496 struct rip_interface *ri; 497 struct in_addr *nexthop; 498 u_char oldmetric; 499 int same = 0; 500 501 /* Make prefix structure. */ 502 memset (&p, 0, sizeof (struct prefix_ipv4)); 503 p.family = AF_INET; 504 p.prefix = rte->prefix; 505 p.prefixlen = ip_masklen (rte->mask); 506 507 /* Make sure mask is applied. */ 508 apply_mask_ipv4 (&p); 509 510 /* Apply input filters. */ 511 ri = ifp->info; 512 513 ret = rip_incoming_filter (&p, ri); 514 if (ret < 0) 515 return; 516 517 /* Once the entry has been validated, update the metric by 518 adding the cost of the network on wich the message 519 arrived. If the result is greater than infinity, use infinity 520 (RFC2453 Sec. 3.9.2) */ 521 /* Zebra ripd can handle offset-list in. */ 522#ifdef FOX_LIST_SUPPORT 523 ret = rip_offset_list_apply_in (&p, ifp, &rte->metric); 524#endif /* FOX_LIST_SUPPORT */ 525 /* If offset-list does not modify the metric use interface's 526 metric. */ 527 if (! ret) 528 rte->metric += ifp->metric; 529 530 if (rte->metric > RIP_METRIC_INFINITY) 531 rte->metric = RIP_METRIC_INFINITY; 532 533 /* Set nexthop pointer. */ 534 if (rte->nexthop.s_addr == 0) 535 nexthop = &from->sin_addr; 536 else 537 nexthop = &rte->nexthop; 538 539 /* Check nexthop address. */ 540 if (rip_nexthop_check (nexthop) < 0) 541 { 542#ifdef FOX_RIP_DEBUG 543 if (IS_RIP_DEBUG_PACKET) 544 zlog_info ("Nexthop address %s is invalid", inet_ntoa (*nexthop)); 545#endif /* FOX_RIP_DEBUG */ 546 return; 547 } 548 549 /* Get index for the prefix. */ 550 rp = route_node_get (rip->table, (struct prefix *) &p); 551 552 /* Check to see whether there is already RIP route on the table. */ 553 rinfo = rp->info; 554 555 if (rinfo) 556 { 557 /* Redistributed route check. */ 558 if (rinfo->type != ZEBRA_ROUTE_RIP 559 && rinfo->metric != RIP_METRIC_INFINITY) 560 return; 561 562 /* Local static route. */ 563 if (rinfo->type == ZEBRA_ROUTE_RIP 564 && rinfo->sub_type == RIP_ROUTE_STATIC 565 && rinfo->metric != RIP_METRIC_INFINITY) 566 return; 567 } 568 569 if (! rinfo) 570 { 571 /* Now, check to see whether there is already an explicit route 572 for the destination prefix. If there is no such route, add 573 this route to the routing table, unless the metric is 574 infinity (there is no point in adding a route which 575 unusable). */ 576 if (rte->metric != RIP_METRIC_INFINITY) 577 { 578 rinfo = rip_info_new (); 579 580 /* - Setting the destination prefix and length to those in 581 the RTE. */ 582 rinfo->rp = rp; 583 584 /* - Setting the metric to the newly calculated metric (as 585 described above). */ 586 rinfo->metric = rte->metric; 587 rinfo->tag = ntohs (rte->tag); 588 589 /* - Set the next hop address to be the address of the router 590 from which the datagram came or the next hop address 591 specified by a next hop RTE. */ 592 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop); 593 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr); 594 rinfo->ifindex = ifp->ifindex; 595 596 /* - Initialize the timeout for the route. If the 597 garbage-collection timer is running for this route, stop it 598 (see section 2.3 for a discussion of the timers). */ 599 rip_timeout_update (rinfo); 600 601 /* - Set the route change flag. */ 602 rinfo->flags |= RIP_RTF_CHANGED; 603 604 /* - Signal the output process to trigger an update (see section 605 2.5). */ 606 rip_event (RIP_TRIGGERED_UPDATE, 0); 607 608 /* Finally, route goes into the kernel. */ 609 rinfo->type = ZEBRA_ROUTE_RIP; 610 rinfo->sub_type = RIP_ROUTE_RTE; 611 612 /* Set distance value. */ 613 rinfo->distance = rip_distance_apply (rinfo); 614 615 rp->info = rinfo; 616 rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric, 617 rinfo->distance); 618 rinfo->flags |= RIP_RTF_FIB; 619 } 620 } 621 else 622 { 623 /* Route is there but we are not sure the route is RIP or not. */ 624 rinfo = rp->info; 625 626 /* If there is an existing route, compare the next hop address 627 to the address of the router from which the datagram came. 628 If this datagram is from the same router as the existing 629 route, reinitialize the timeout. */ 630 same = IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr); 631 632 if (same) 633 rip_timeout_update (rinfo); 634 635 /* Next, compare the metrics. If the datagram is from the same 636 router as the existing route, and the new metric is different 637 than the old one; or, if the new metric is lower than the old 638 one; do the following actions: */ 639 if ((same && rinfo->metric != rte->metric) || 640 rte->metric < rinfo->metric) 641 { 642 /* - Adopt the route from the datagram. That is, put the 643 new metric in, and adjust the next hop address (if 644 necessary). */ 645 oldmetric = rinfo->metric; 646 rinfo->metric = rte->metric; 647 rinfo->tag = ntohs (rte->tag); 648 IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr); 649 rinfo->ifindex = ifp->ifindex; 650 rinfo->distance = rip_distance_apply (rinfo); 651 652 /* Should a new route to this network be established 653 while the garbage-collection timer is running, the 654 new route will replace the one that is about to be 655 deleted. In this case the garbage-collection timer 656 must be cleared. */ 657 658 if (oldmetric == RIP_METRIC_INFINITY && 659 rinfo->metric < RIP_METRIC_INFINITY) 660 { 661 rinfo->type = ZEBRA_ROUTE_RIP; 662 rinfo->sub_type = RIP_ROUTE_RTE; 663 664 RIP_TIMER_OFF (rinfo->t_garbage_collect); 665 666 if (! IPV4_ADDR_SAME (&rinfo->nexthop, nexthop)) 667 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop); 668 669 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric, 670 rinfo->distance); 671 rinfo->flags |= RIP_RTF_FIB; 672 } 673 674 /* Update nexthop and/or metric value. */ 675 if (oldmetric != RIP_METRIC_INFINITY) 676 { 677 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric); 678 rip_zebra_ipv4_add (&p, nexthop, rinfo->metric, 679 rinfo->distance); 680 rinfo->flags |= RIP_RTF_FIB; 681 682 if (! IPV4_ADDR_SAME (&rinfo->nexthop, nexthop)) 683 IPV4_ADDR_COPY (&rinfo->nexthop, nexthop); 684 } 685 686 /* - Set the route change flag and signal the output process 687 to trigger an update. */ 688 rinfo->flags |= RIP_RTF_CHANGED; 689 rip_event (RIP_TRIGGERED_UPDATE, 0); 690 691 /* - If the new metric is infinity, start the deletion 692 process (described above); */ 693 if (rinfo->metric == RIP_METRIC_INFINITY) 694 { 695 /* If the new metric is infinity, the deletion process 696 begins for the route, which is no longer used for 697 routing packets. Note that the deletion process is 698 started only when the metric is first set to 699 infinity. If the metric was already infinity, then a 700 new deletion process is not started. */ 701 if (oldmetric != RIP_METRIC_INFINITY) 702 { 703 /* - The garbage-collection timer is set for 120 seconds. */ 704 RIP_TIMER_ON (rinfo->t_garbage_collect, 705 rip_garbage_collect, rip->garbage_time); 706 RIP_TIMER_OFF (rinfo->t_timeout); 707 708 /* - The metric for the route is set to 16 709 (infinity). This causes the route to be removed 710 from service.*/ 711 rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric); 712 rinfo->flags &= ~RIP_RTF_FIB; 713 714 /* - The route change flag is to indicate that this 715 entry has been changed. */ 716 /* - The output process is signalled to trigger a 717 response. */ 718 ; /* Above processes are already done previously. */ 719 } 720 } 721 else 722 { 723 /* otherwise, re-initialize the timeout. */ 724 rip_timeout_update (rinfo); 725 } 726 } 727 /* Unlock tempolary lock of the route. */ 728 route_unlock_node (rp); 729 } 730} 731 732#ifdef FOX_RIP_DEBUG 733/* Dump RIP packet */ 734void 735rip_packet_dump (struct rip_packet *packet, int size, char *sndrcv) 736{ 737 caddr_t lim; 738 struct rte *rte; 739 char *command_str; 740 char pbuf[BUFSIZ], nbuf[BUFSIZ]; 741 u_char netmask = 0; 742 u_char *p; 743 744 /* Set command string. */ 745 if (packet->command > 0 && packet->command < RIP_COMMAND_MAX) 746 command_str = lookup (rip_msg, packet->command); 747 else 748 command_str = "unknown"; 749 750#ifdef FOX_RIP_DEBUG 751 /* Dump packet header. */ 752 zlog_info ("%s %s version %d packet size %d", 753 sndrcv, command_str, packet->version, size); 754#endif /* FOX_RIP_DEBUG */ 755 756 /* Dump each routing table entry. */ 757 rte = packet->rte; 758 759 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) 760 { 761 if (packet->version == RIPv2) 762 { 763 netmask = ip_masklen (rte->mask); 764 765 if (ntohs (rte->family) == 0xffff) 766 { 767 if (ntohs (rte->tag) == RIP_AUTH_SIMPLE_PASSWORD) 768 { 769 p = (u_char *)&rte->prefix; 770#ifdef FOX_RIP_DEBUG 771 zlog_info (" family 0x%X type %d auth string: %s", 772 ntohs (rte->family), ntohs (rte->tag), p); 773#endif /* FOX_RIP_DEBUG */ 774 } 775 else if (ntohs (rte->tag) == RIP_AUTH_MD5) 776 { 777 struct rip_md5_info *md5; 778 779 md5 = (struct rip_md5_info *) &packet->rte; 780 781#ifdef FOX_RIP_DEBUG 782 zlog_info (" family 0x%X type %d (MD5 authentication)", 783 ntohs (md5->family), ntohs (md5->type)); 784 zlog_info (" RIP-2 packet len %d Key ID %d" 785 " Auth Data len %d", ntohs (md5->packet_len), 786 md5->keyid, md5->auth_len); 787 zlog_info (" Sequence Number %ld", (u_long)ntohl (md5->sequence)); 788#endif /* FOX_RIP_DEBUG */ 789 } 790 else if (ntohs (rte->tag) == RIP_AUTH_DATA) 791 { 792 p = (u_char *)&rte->prefix; 793 794#ifdef FOX_RIP_DEBUG 795 zlog_info (" family 0x%X type %d (MD5 data)", 796 ntohs (rte->family), ntohs (rte->tag)); 797 zlog_info (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X" 798 "%02X%02X%02X%02X%02X%02X%02X", 799 p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7], 800 p[9],p[10],p[11],p[12],p[13],p[14],p[15]); 801#endif /* FOX_RIP_DEBUG */ 802 } 803 else 804 { 805#ifdef FOX_RIP_DEBUG 806 zlog_info (" family 0x%X type %d (Unknown auth type)", 807 ntohs (rte->family), ntohs (rte->tag)); 808#endif /* FOX_RIP_DEBUG */ 809 } 810 } 811 else{ 812#ifdef FOX_RIP_DEBUG 813 zlog_info (" %s/%d -> %s family %d tag %d metric %ld", 814 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),netmask, 815 inet_ntop (AF_INET, &rte->nexthop, nbuf, BUFSIZ), 816 ntohs (rte->family), ntohs (rte->tag), 817 (u_long)ntohl (rte->metric)); 818#endif 819 } 820 } 821 else 822 { 823#ifdef FOX_RIP_DEBUG 824 zlog_info (" %s family %d tag %d metric %ld", 825 inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ), 826 ntohs (rte->family), ntohs (rte->tag), 827 (u_long)ntohl (rte->metric)); 828#endif 829 } 830 } 831} 832#endif /* FOX_RIP_DEBUG */ 833 834/* Check if the destination address is valid (unicast; not net 0 835 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't 836 check net 0 because we accept default route. */ 837int 838rip_destination_check (struct in_addr addr) 839{ 840 u_int32_t destination; 841 842 /* Convert to host byte order. */ 843 destination = ntohl (addr.s_addr); 844 845 if (IPV4_NET127 (destination)) 846 return 0; 847 848 /* Net 0 may match to the default route. */ 849 if (IPV4_NET0 (destination) && destination != 0) 850 return 0; 851 852 /* Unicast address must belong to class A, B, C. */ 853 if (IN_CLASSA (destination)) 854 return 1; 855 if (IN_CLASSB (destination)) 856 return 1; 857 if (IN_CLASSC (destination)) 858 return 1; 859 860 return 0; 861} 862 863#ifdef FOX_AUTH_SUPPORT 864/* RIP version 2 authentication. */ 865int 866rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from, 867 struct interface *ifp) 868{ 869 struct rip_interface *ri; 870 char *auth_str; 871 872#ifdef FOX_RIP_DEBUG 873 if (IS_RIP_DEBUG_EVENT) 874 zlog_info ("RIPv2 simple password authentication from %s", 875 inet_ntoa (from->sin_addr)); 876#endif /* FOX_RIP_DEBUG */ 877 ri = ifp->info; 878 879 if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD 880 || ntohs (rte->tag) != RIP_AUTH_SIMPLE_PASSWORD) 881 return 0; 882 883 /* Simple password authentication. */ 884 if (ri->auth_str) 885 { 886 auth_str = (char *) &rte->prefix; 887 888 if (strncmp (auth_str, ri->auth_str, 16) == 0) 889 return 1; 890 } 891 if (ri->key_chain) 892 { 893 struct keychain *keychain; 894 struct key *key; 895 896 keychain = keychain_lookup (ri->key_chain); 897 if (keychain == NULL) 898 return 0; 899 900 key = key_match_for_accept (keychain, (char *) &rte->prefix); 901 if (key) 902 return 1; 903 } 904 return 0; 905} 906 907/* RIP version 2 authentication with MD5. */ 908int 909rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from, 910 struct interface *ifp) 911{ 912 struct rip_interface *ri; 913 struct rip_md5_info *md5; 914 struct rip_md5_data *md5data; 915 struct keychain *keychain; 916 struct key *key; 917 struct md5_ctx ctx; 918 u_char pdigest[RIP_AUTH_MD5_SIZE]; 919 u_char digest[RIP_AUTH_MD5_SIZE]; 920 u_int16_t packet_len; 921 char *auth_str = NULL; 922 923#ifdef FOX_RIP_DEBUG 924 if (IS_RIP_DEBUG_EVENT) 925 zlog_info ("RIPv2 MD5 authentication from %s", inet_ntoa (from->sin_addr)); 926#endif /* FOX_RIP_DEBUG */ 927 928 ri = ifp->info; 929 md5 = (struct rip_md5_info *) &packet->rte; 930 931 /* Check auth type. */ 932 if (ri->auth_type != RIP_AUTH_MD5 || ntohs (md5->type) != RIP_AUTH_MD5) 933 return 0; 934 935 if (md5->auth_len != RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE) 936 return 0; 937 938 if (ri->key_chain) 939 { 940 keychain = keychain_lookup (ri->key_chain); 941 if (keychain == NULL) 942 return 0; 943 944 key = key_lookup_for_accept (keychain, md5->keyid); 945 if (key == NULL) 946 return 0; 947 948 auth_str = key->string; 949 } 950 951 if (ri->auth_str) 952 auth_str = ri->auth_str; 953 954 if (! auth_str) 955 return 0; 956 957 /* MD5 digest authentication. */ 958 packet_len = ntohs (md5->packet_len); 959 md5data = (struct rip_md5_data *)(((u_char *) packet) + packet_len); 960 961 /* Save digest to pdigest. */ 962 memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE); 963 964 /* Overwrite digest by my secret. */ 965 memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE); 966 strncpy (md5data->digest, auth_str, RIP_AUTH_MD5_SIZE); 967 968 md5_init_ctx (&ctx); 969 md5_process_bytes (packet, packet_len + md5->auth_len, &ctx); 970 md5_finish_ctx (&ctx, digest); 971 972 if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0) 973 return packet_len; 974 else 975 return 0; 976} 977 978void 979rip_auth_md5_set (struct stream *s, struct interface *ifp) 980{ 981 struct rip_interface *ri; 982 struct keychain *keychain = NULL; 983 struct key *key = NULL; 984 unsigned long len; 985 struct md5_ctx ctx; 986 unsigned char secret[RIP_AUTH_MD5_SIZE]; 987 unsigned char digest[RIP_AUTH_MD5_SIZE]; 988 char *auth_str = NULL; 989 990 ri = ifp->info; 991 992 /* Make it sure this interface is configured as MD5 993 authentication. */ 994 if (ri->auth_type != RIP_AUTH_MD5) 995 return; 996 997 /* Lookup key chain. */ 998 if (ri->key_chain) 999 { 1000 keychain = keychain_lookup (ri->key_chain); 1001 if (keychain == NULL) 1002 return; 1003 1004 /* Lookup key. */ 1005 key = key_lookup_for_send (keychain); 1006 if (key == NULL) 1007 return; 1008 1009 auth_str = key->string; 1010 } 1011 1012 if (ri->auth_str) 1013 auth_str = ri->auth_str; 1014 1015 if (! auth_str) 1016 return; 1017 1018 /* Get packet length. */ 1019 len = s->putp; 1020 1021 /* Check packet length. */ 1022 if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE)) 1023 { 1024#ifdef FOX_RIP_DEBUG 1025 zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len); 1026#endif /* FOX_RIP_DEBUG */ 1027 return; 1028 } 1029 1030 /* Move RTE. */ 1031 memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE, 1032 s->data + RIP_HEADER_SIZE, 1033 len - RIP_HEADER_SIZE); 1034 1035 /* Set pointer to authentication header. */ 1036 stream_set_putp (s, RIP_HEADER_SIZE); 1037 len += RIP_RTE_SIZE; 1038 1039 /* MD5 authentication. */ 1040 stream_putw (s, 0xffff); 1041 stream_putw (s, RIP_AUTH_MD5); 1042 1043 /* RIP-2 Packet length. Actual value is filled in 1044 rip_auth_md5_set(). */ 1045 stream_putw (s, len); 1046 1047 /* Key ID. */ 1048 if (key) 1049 stream_putc (s, key->index % 256); 1050 else 1051 stream_putc (s, 1); 1052 1053 /* Auth Data Len. Set 16 for MD5 authentication 1054 data. */ 1055 stream_putc (s, RIP_AUTH_MD5_SIZE + RIP_HEADER_SIZE); 1056 1057 /* Sequence Number (non-decreasing). */ 1058 /* RFC2080: The value used in the sequence number is 1059 arbitrary, but two suggestions are the time of the 1060 message's creation or a simple message counter. */ 1061 stream_putl (s, time (NULL)); 1062 1063 /* Reserved field must be zero. */ 1064 stream_putl (s, 0); 1065 stream_putl (s, 0); 1066 1067 /* Set pointer to authentication data. */ 1068 stream_set_putp (s, len); 1069 1070 /* Set authentication data. */ 1071 stream_putw (s, 0xffff); 1072 stream_putw (s, 0x01); 1073 1074 /* Generate a digest for the RIP packet. */ 1075 memset (secret, 0, RIP_AUTH_MD5_SIZE); 1076 strncpy (secret, auth_str, RIP_AUTH_MD5_SIZE); 1077 md5_init_ctx (&ctx); 1078 md5_process_bytes (s->data, s->endp, &ctx); 1079 md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx); 1080 md5_finish_ctx (&ctx, digest); 1081 1082 /* Copy the digest to the packet. */ 1083 stream_write (s, digest, RIP_AUTH_MD5_SIZE); 1084} 1085#endif /* FOX_AUTH_SUPPORT */ 1086 1087/* RIP routing information. */ 1088void 1089rip_response_process (struct rip_packet *packet, int size, 1090 struct sockaddr_in *from, struct interface *ifp) 1091{ 1092 caddr_t lim; 1093 struct rte *rte; 1094 1095 /* The Response must be ignored if it is not from the RIP 1096 port. (RFC2453 - Sec. 3.9.2)*/ 1097 if (ntohs (from->sin_port) != RIP_PORT_DEFAULT) 1098 { 1099#ifdef FOX_RIP_DEBUG 1100 zlog_info ("response doesn't come from RIP port: %d", 1101 from->sin_port); 1102 rip_peer_bad_packet (from); 1103#endif /* FOX_RIP_DEBUG */ 1104 return; 1105 } 1106 1107 /* The datagram's IPv4 source address should be checked to see 1108 whether the datagram is from a valid neighbor; the source of the 1109 datagram must be on a directly connected network */ 1110 if (! if_valid_neighbor (from->sin_addr)) 1111 { 1112#ifdef FOX_RIP_DEBUG 1113 zlog_info ("This datagram doesn't came from a valid neighbor: %s", 1114 inet_ntoa (from->sin_addr)); 1115 rip_peer_bad_packet (from); 1116#endif /* FOX_RIP_DEBUG */ 1117 return; 1118 } 1119 1120 /* It is also worth checking to see whether the response is from one 1121 of the router's own addresses. */ 1122 1123 ; /* Alredy done in rip_read () */ 1124 1125#ifdef FOX_RIP_DEBUG 1126 /* Update RIP peer. */ 1127 rip_peer_update (from, packet->version); 1128#endif /* FOX_RIP_DEBUG */ 1129 1130 /* Set RTE pointer. */ 1131 rte = packet->rte; 1132 1133 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) 1134 { 1135 /* RIPv2 authentication check. */ 1136 /* If the Address Family Identifier of the first (and only the 1137 first) entry in the message is 0xFFFF, then the remainder of 1138 the entry contains the authentication. */ 1139 /* If the packet gets here it means authentication enabled */ 1140 /* Check is done in rip_read(). So, just skipping it */ 1141 if (packet->version == RIPv2 && 1142 rte == packet->rte && 1143 rte->family == 0xffff) 1144 continue; 1145 1146 if (ntohs (rte->family) != AF_INET) 1147 { 1148 /* Address family check. RIP only supports AF_INET. */ 1149#ifdef FOX_RIP_DEBUG 1150 zlog_info ("Unsupported family %d from %s.", 1151 ntohs (rte->family), inet_ntoa (from->sin_addr)); 1152#endif /* FOX_RIP_DEBUG */ 1153 continue; 1154 } 1155 1156 /* - is the destination address valid (e.g., unicast; not net 0 1157 or 127) */ 1158 if (! rip_destination_check (rte->prefix)) 1159 { 1160#ifdef FOX_RIP_DEBUG 1161 zlog_info ("Network is net 0 or net 127 or it is not unicast network"); 1162 rip_peer_bad_route (from); 1163#endif /* FOX_RIP_DEBUG */ 1164 continue; 1165 } 1166 1167 /* Convert metric value to host byte order. */ 1168 rte->metric = ntohl (rte->metric); 1169 1170 /* - is the metric valid (i.e., between 1 and 16, inclusive) */ 1171 if (! (rte->metric >= 1 && rte->metric <= 16)) 1172 { 1173#ifdef FOX_RIP_DEBUG 1174 zlog_info ("Route's metric is not in the 1-16 range."); 1175 rip_peer_bad_route (from); 1176#endif /* FOX_RIP_DEBUG */ 1177 continue; 1178 } 1179 1180 /* RIPv1 does not have nexthop value. */ 1181 if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) 1182 { 1183#ifdef FOX_RIP_DEBUG 1184 zlog_info ("RIPv1 packet with nexthop value %s", 1185 inet_ntoa (rte->nexthop)); 1186 rip_peer_bad_route (from); 1187#endif /* FOX_RIP_DEBUG */ 1188 continue; 1189 } 1190 1191 /* That is, if the provided information is ignored, a possibly 1192 sub-optimal, but absolutely valid, route may be taken. If 1193 the received Next Hop is not directly reachable, it should be 1194 treated as 0.0.0.0. */ 1195 if (packet->version == RIPv2 && rte->nexthop.s_addr != 0) 1196 { 1197 u_int32_t addrval; 1198 1199 /* Multicast address check. */ 1200 addrval = ntohl (rte->nexthop.s_addr); 1201 if (IN_CLASSD (addrval)) 1202 { 1203#ifdef FOX_RIP_DEBUG 1204 zlog_info ("Nexthop %s is multicast address, skip this rte", 1205 inet_ntoa (rte->nexthop)); 1206#endif /* FOX_RIP_DEBUG */ 1207 continue; 1208 } 1209 1210 if (! if_lookup_address (rte->nexthop)) 1211 { 1212 struct route_node *rn; 1213 struct rip_info *rinfo; 1214 1215 rn = route_node_match_ipv4 (rip->table, &rte->nexthop); 1216 1217 if (rn) 1218 { 1219 rinfo = rn->info; 1220 1221 if (rinfo->type == ZEBRA_ROUTE_RIP 1222 && rinfo->sub_type == RIP_ROUTE_RTE) 1223 { 1224#ifdef FOX_RIP_DEBUG 1225 if (IS_RIP_DEBUG_EVENT) 1226 zlog_info ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop)); 1227#endif /* FOX_RIP_DEBUG */ 1228 rte->nexthop = rinfo->from; 1229 } 1230 else 1231 { 1232#ifdef FOX_RIP_DEBUG 1233 if (IS_RIP_DEBUG_EVENT) 1234 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop)); 1235#endif /* FOX_RIP_DEBUG */ 1236 rte->nexthop.s_addr = 0; 1237 } 1238 1239 route_unlock_node (rn); 1240 } 1241 else 1242 { 1243#ifdef FOX_RIP_DEBUG 1244 if (IS_RIP_DEBUG_EVENT) 1245 zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop)); 1246#endif /* FOX_RIP_DEBUG */ 1247 rte->nexthop.s_addr = 0; 1248 } 1249 1250 } 1251 } 1252 1253 /* For RIPv1, there won't be a valid netmask. 1254 1255 This is a best guess at the masks. If everyone was using old 1256 Ciscos before the 'ip subnet zero' option, it would be almost 1257 right too :-) 1258 1259 Cisco summarize ripv1 advertisments to the classful boundary 1260 (/16 for class B's) except when the RIP packet does to inside 1261 the classful network in question. */ 1262 1263 if ((packet->version == RIPv1 && rte->prefix.s_addr != 0) 1264 || (packet->version == RIPv2 1265 && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0))) 1266 { 1267 u_int32_t destination; 1268 1269 destination = ntohl (rte->prefix.s_addr); 1270 1271 if (destination & 0xff) 1272 { 1273 masklen2ip (32, &rte->mask); 1274 } 1275 else if ((destination & 0xff00) || IN_CLASSC (destination)) 1276 { 1277 masklen2ip (24, &rte->mask); 1278 } 1279 else if ((destination & 0xff0000) || IN_CLASSB (destination)) 1280 { 1281 masklen2ip (16, &rte->mask); 1282 } 1283 else 1284 { 1285 masklen2ip (8, &rte->mask); 1286 } 1287 } 1288 1289 /* In case of RIPv2, if prefix in RTE is not netmask applied one 1290 ignore the entry. */ 1291 if ((packet->version == RIPv2) 1292 && (rte->mask.s_addr != 0) 1293 && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)) 1294 { 1295#ifdef FOX_RIP_DEBUG 1296 zlog_warn ("RIPv2 address %s is not mask /%d applied one", 1297 inet_ntoa (rte->prefix), ip_masklen (rte->mask)); 1298 rip_peer_bad_route (from); 1299#endif /* FOX_RIP_DEBUG */ 1300 continue; 1301 } 1302 1303 /* Default route's netmask is ignored. */ 1304 if (packet->version == RIPv2 1305 && (rte->prefix.s_addr == 0) 1306 && (rte->mask.s_addr != 0)) 1307 { 1308#ifdef FOX_RIP_DEBUG 1309 if (IS_RIP_DEBUG_EVENT) 1310 zlog_info ("Default route with non-zero netmask. Set zero to netmask"); 1311#endif /* FOX_RIP_DEBUG */ 1312 rte->mask.s_addr = 0; 1313 } 1314 1315 /* Routing table updates. */ 1316 rip_rte_process (rte, from, ifp); 1317 } 1318} 1319 1320/* RIP packet send to destination address. */ 1321int 1322rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to, 1323 struct interface *ifp) 1324{ 1325 int ret; 1326 struct sockaddr_in sin; 1327 int sock; 1328 1329 /* Make destination address. */ 1330 memset (&sin, 0, sizeof (struct sockaddr_in)); 1331 sin.sin_family = AF_INET; 1332#ifdef HAVE_SIN_LEN 1333 sin.sin_len = sizeof (struct sockaddr_in); 1334#endif /* HAVE_SIN_LEN */ 1335 1336 /* When destination is specified, use it's port and address. */ 1337 if (to) 1338 { 1339 sock = rip->sock; 1340 1341 sin.sin_port = to->sin_port; 1342 sin.sin_addr = to->sin_addr; 1343 } 1344 else 1345 { 1346 sock = socket (AF_INET, SOCK_DGRAM, 0); 1347 1348 sockopt_broadcast (sock); 1349 sockopt_reuseaddr (sock); 1350 sockopt_reuseport (sock); 1351 1352 sin.sin_port = htons (RIP_PORT_DEFAULT); 1353 sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); 1354 1355 /* Set multicast interface. */ 1356 rip_interface_multicast_set (sock, ifp); 1357 } 1358 1359 /* foxconn wklin added start, 04/14/2007 */ 1360 { 1361 int ttl = 1; 1362 setsockopt (sock, IPPROTO_IP, IP_TTL, (void *) &ttl, sizeof (int)); 1363 } 1364 /* foxconn wklin added end, 04/14/2007 */ 1365 ret = sendto (sock, buf, size, 0, (struct sockaddr *)&sin, 1366 sizeof (struct sockaddr_in)); 1367 1368#ifdef FOX_RIP_DEBUG 1369 if (IS_RIP_DEBUG_EVENT) 1370 zlog_info ("SEND to socket %d port %d addr %s", 1371 sock, ntohs (sin.sin_port), inet_ntoa(sin.sin_addr)); 1372 1373 if (ret < 0) 1374 zlog_warn ("can't send packet : %s", strerror (errno)); 1375#endif /* FOX_RIP_DEBUG */ 1376 1377 if (ret < 0) 1378 printf("can't send packet : %s", strerror (errno)); 1379 1380 1381 if (! to) 1382 close (sock); 1383 1384 return ret; 1385} 1386 1387/* Add redistributed route to RIP table. */ 1388void 1389rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, 1390 unsigned int ifindex, struct in_addr *nexthop) 1391{ 1392 int ret; 1393 struct route_node *rp; 1394 struct rip_info *rinfo; 1395 1396 /* Redistribute route */ 1397 ret = rip_destination_check (p->prefix); 1398 if (! ret) 1399 return; 1400 1401 rp = route_node_get (rip->table, (struct prefix *) p); 1402 1403 rinfo = rp->info; 1404 1405 if (rinfo) 1406 { 1407 if (rinfo->type == ZEBRA_ROUTE_CONNECT 1408 && rinfo->sub_type == RIP_ROUTE_INTERFACE 1409 && rinfo->metric != RIP_METRIC_INFINITY) 1410 { 1411 route_unlock_node (rp); 1412 return; 1413 } 1414 1415 /* Manually configured RIP route check. */ 1416 if (rinfo->type == ZEBRA_ROUTE_RIP 1417 && rinfo->sub_type == RIP_ROUTE_STATIC) 1418 { 1419 if (type != ZEBRA_ROUTE_RIP || sub_type != RIP_ROUTE_STATIC) 1420 { 1421 route_unlock_node (rp); 1422 return; 1423 } 1424 } 1425 1426 RIP_TIMER_OFF (rinfo->t_timeout); 1427 RIP_TIMER_OFF (rinfo->t_garbage_collect); 1428 1429 if (rip_route_rte (rinfo)) 1430 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop, 1431 rinfo->metric); 1432 rp->info = NULL; 1433 rip_info_free (rinfo); 1434 1435 route_unlock_node (rp); 1436 } 1437 1438 rinfo = rip_info_new (); 1439 1440 rinfo->type = type; 1441 rinfo->sub_type = sub_type; 1442 rinfo->ifindex = ifindex; 1443 rinfo->metric = 1; 1444 rinfo->rp = rp; 1445 1446 if (nexthop) 1447 rinfo->nexthop = *nexthop; 1448 1449 rinfo->flags |= RIP_RTF_FIB; 1450 rp->info = rinfo; 1451 1452 rinfo->flags |= RIP_RTF_CHANGED; 1453 1454 rip_event (RIP_TRIGGERED_UPDATE, 0); 1455} 1456 1457/* Delete redistributed route from RIP table. */ 1458void 1459rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p, 1460 unsigned int ifindex) 1461{ 1462 int ret; 1463 struct route_node *rp; 1464 struct rip_info *rinfo; 1465 1466 ret = rip_destination_check (p->prefix); 1467 if (! ret) 1468 return; 1469 1470 rp = route_node_lookup (rip->table, (struct prefix *) p); 1471 if (rp) 1472 { 1473 rinfo = rp->info; 1474 1475 if (rinfo != NULL 1476 && rinfo->type == type 1477 && rinfo->sub_type == sub_type 1478 && rinfo->ifindex == ifindex) 1479 { 1480 /* Perform poisoned reverse. */ 1481 rinfo->metric = RIP_METRIC_INFINITY; 1482 RIP_TIMER_ON (rinfo->t_garbage_collect, 1483 rip_garbage_collect, rip->garbage_time); 1484 RIP_TIMER_OFF (rinfo->t_timeout); 1485 rinfo->flags |= RIP_RTF_CHANGED; 1486 1487 rip_event (RIP_TRIGGERED_UPDATE, 0); 1488 } 1489 } 1490} 1491 1492/* Response to request called from rip_read ().*/ 1493void 1494rip_request_process (struct rip_packet *packet, int size, 1495 struct sockaddr_in *from, struct interface *ifp) 1496{ 1497 caddr_t lim; 1498 struct rte *rte; 1499 struct prefix_ipv4 p; 1500 struct route_node *rp; 1501 struct rip_info *rinfo; 1502 struct rip_interface *ri; 1503 1504 ri = ifp->info; 1505 1506 /* When passive interface is specified, suppress responses */ 1507 if (ri->passive) 1508 return; 1509 1510#ifdef FOX_RIP_DEBUG 1511 /* RIP peer update. */ 1512 rip_peer_update (from, packet->version); 1513#endif /* FOX_RIP_DEBUG */ 1514 1515 lim = ((caddr_t) packet) + size; 1516 rte = packet->rte; 1517 1518 /* The Request is processed entry by entry. If there are no 1519 entries, no response is given. */ 1520 if (lim == (caddr_t) rte) 1521 return; 1522 1523 /* There is one special case. If there is exactly one entry in the 1524 request, and it has an address family identifier of zero and a 1525 metric of infinity (i.e., 16), then this is a request to send the 1526 entire routing table. */ 1527 if (lim == ((caddr_t) (rte + 1)) && 1528 ntohs (rte->family) == 0 && 1529 ntohl (rte->metric) == RIP_METRIC_INFINITY) 1530 { 1531 /* All route with split horizon */ 1532 rip_output_process (ifp, from, rip_all_route, packet->version); 1533 } 1534 else 1535 { 1536 /* Examine the list of RTEs in the Request one by one. For each 1537 entry, look up the destination in the router's routing 1538 database and, if there is a route, put that route's metric in 1539 the metric field of the RTE. If there is no explicit route 1540 to the specified destination, put infinity in the metric 1541 field. Once all the entries have been filled in, change the 1542 command from Request to Response and send the datagram back 1543 to the requestor. */ 1544 p.family = AF_INET; 1545 1546 for (; ((caddr_t) rte) < lim; rte++) 1547 { 1548 p.prefix = rte->prefix; 1549 p.prefixlen = ip_masklen (rte->mask); 1550 apply_mask_ipv4 (&p); 1551 1552 rp = route_node_lookup (rip->table, (struct prefix *) &p); 1553 if (rp) 1554 { 1555 rinfo = rp->info; 1556 rte->metric = htonl (rinfo->metric); 1557 route_unlock_node (rp); 1558 } 1559 else 1560 rte->metric = htonl (RIP_METRIC_INFINITY); 1561 } 1562 packet->command = RIP_RESPONSE; 1563 1564 rip_send_packet ((caddr_t) packet, size, from, ifp); 1565 } 1566 rip_global_queries++; 1567} 1568 1569#if RIP_RECVMSG 1570/* Set IPv6 packet info to the socket. */ 1571static int 1572setsockopt_pktinfo (int sock) 1573{ 1574 int ret; 1575 int val = 1; 1576 1577 ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val)); 1578 if (ret < 0) 1579#ifdef FOX_RIP_DEBUG 1580 zlog_warn ("Can't setsockopt IP_PKTINFO : %s", strerror (errno)); 1581#endif /* FOX_RIP_DEBUG */ 1582 return ret; 1583} 1584 1585/* Read RIP packet by recvmsg function. */ 1586int 1587rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from, 1588 int *ifindex) 1589{ 1590 int ret; 1591 struct msghdr msg; 1592 struct iovec iov; 1593 struct cmsghdr *ptr; 1594 char adata[1024]; 1595 1596 msg.msg_name = (void *) from; 1597 msg.msg_namelen = sizeof (struct sockaddr_in); 1598 msg.msg_iov = &iov; 1599 msg.msg_iovlen = 1; 1600 msg.msg_control = (void *) adata; 1601 msg.msg_controllen = sizeof adata; 1602 iov.iov_base = buf; 1603 iov.iov_len = size; 1604 1605 ret = recvmsg (sock, &msg, 0); 1606 if (ret < 0) 1607 return ret; 1608 1609 for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr)) 1610 if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO) 1611 { 1612 struct in_pktinfo *pktinfo; 1613 int i; 1614 1615 pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr); 1616 i = pktinfo->ipi_ifindex; 1617 } 1618 return ret; 1619} 1620 1621/* RIP packet read function. */ 1622int 1623rip_read_new (struct thread *t) 1624{ 1625 int ret; 1626 int sock; 1627 char buf[RIP_PACKET_MAXSIZ]; 1628 struct sockaddr_in from; 1629 unsigned int ifindex; 1630 1631 /* Fetch socket then register myself. */ 1632 sock = THREAD_FD (t); 1633 rip_event (RIP_READ, sock); 1634 1635 /* Read RIP packet. */ 1636 ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex); 1637 if (ret < 0) 1638 { 1639#ifdef FOX_RIP_DEBUG 1640 zlog_warn ("Can't read RIP packet: %s", strerror (errno)); 1641#endif /* FOX_RIP_DEBUG */ 1642 return ret; 1643 } 1644 1645 return ret; 1646} 1647#endif /* RIP_RECVMSG */ 1648 1649/* First entry point of RIP packet. */ 1650int 1651rip_read (struct thread *t) 1652{ 1653 int sock; 1654 int ret; 1655 int rtenum; 1656 union rip_buf rip_buf; 1657 struct rip_packet *packet; 1658 struct sockaddr_in from; 1659 int fromlen, len; 1660 struct interface *ifp; 1661 struct rip_interface *ri; 1662 1663 /* Fetch socket then register myself. */ 1664 sock = THREAD_FD (t); 1665 rip->t_read = NULL; 1666 1667 /* Add myself to tne next event */ 1668 rip_event (RIP_READ, sock); 1669 1670 /* RIPd manages only IPv4. */ 1671 memset (&from, 0, sizeof (struct sockaddr_in)); 1672 fromlen = sizeof (struct sockaddr_in); 1673 1674 len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0, 1675 (struct sockaddr *) &from, &fromlen); 1676 if (len < 0) 1677 { 1678#ifdef FOX_RIP_DEBUG 1679 zlog_info ("recvfrom failed: %s", strerror (errno)); 1680#endif #endif /* FOX_RIP_DEBUG */ 1681 return len; 1682 } 1683 1684 /* Check is this packet comming from myself? */ 1685 if (if_check_address (from.sin_addr)) 1686 { 1687#ifdef FOX_RIP_DEBUG 1688 if (IS_RIP_DEBUG_PACKET) 1689 zlog_warn ("ignore packet comes from myself"); 1690#endif /* FOX_RIP_DEBUG */ 1691 return -1; 1692 } 1693 1694 /* Which interface is this packet comes from. */ 1695 ifp = if_lookup_address (from.sin_addr); 1696 1697 /* RIP packet received */ 1698 1699#ifdef FOX_RIP_DEBUG 1700 if (IS_RIP_DEBUG_EVENT) 1701 zlog_info ("RECV packet from %s port %d on %s", 1702 inet_ntoa (from.sin_addr), ntohs (from.sin_port), 1703 ifp ? ifp->name : "unknown"); 1704#endif /* FOX_RIP_DEBUG */ 1705 1706 /* If this packet come from unknown interface, ignore it. */ 1707 if (ifp == NULL) 1708 { 1709#ifdef FOX_RIP_DEBUG 1710 zlog_info ("packet comes from unknown interface"); 1711#endif /* FOX_RIP_DEBUG */ 1712 return -1; 1713 } 1714 1715 /* Packet length check. */ 1716 if (len < RIP_PACKET_MINSIZ) 1717 { 1718#ifdef FOX_RIP_DEBUG 1719 zlog_warn ("packet size %d is smaller than minimum size %d", 1720 len, RIP_PACKET_MINSIZ); 1721 rip_peer_bad_packet (&from); 1722#endif /* FOX_RIP_DEBUG */ 1723 return len; 1724 } 1725 if (len > RIP_PACKET_MAXSIZ) 1726 { 1727#ifdef FOX_RIP_DEBUG 1728 zlog_warn ("packet size %d is larger than max size %d", 1729 len, RIP_PACKET_MAXSIZ); 1730 rip_peer_bad_packet (&from); 1731#endif /* FOX_RIP_DEBUG */ 1732 return len; 1733 } 1734 1735 /* Packet alignment check. */ 1736 if ((len - RIP_PACKET_MINSIZ) % 20) 1737 { 1738#ifdef FOX_RIP_DEBUG 1739 zlog_warn ("packet size %d is wrong for RIP packet alignment", len); 1740 rip_peer_bad_packet (&from); 1741#endif /* FOX_RIP_DEBUG */ 1742 return len; 1743 } 1744 1745 /* Set RTE number. */ 1746 rtenum = ((len - RIP_PACKET_MINSIZ) / 20); 1747 1748 /* For easy to handle. */ 1749 packet = &rip_buf.rip_packet; 1750 1751 /* RIP version check. */ 1752 if (packet->version == 0) 1753 { 1754#ifdef FOX_RIP_DEBUG 1755 zlog_info ("version 0 with command %d received.", packet->command); 1756 rip_peer_bad_packet (&from); 1757#endif /* FOX_RIP_DEBUG */ 1758 return -1; 1759 } 1760 1761#ifdef FOX_RIP_DEBUG 1762 /* Dump RIP packet. */ 1763 if (IS_RIP_DEBUG_RECV) 1764 rip_packet_dump (packet, len, "RECV"); 1765#endif /* FOX_RIP_DEBUG */ 1766 1767 /* RIP version adjust. This code should rethink now. RFC1058 says 1768 that "Version 1 implementations are to ignore this extra data and 1769 process only the fields specified in this document.". So RIPv3 1770 packet should be treated as RIPv1 ignoring must be zero field. */ 1771 if (packet->version > RIPv2) 1772 packet->version = RIPv2; 1773 1774 /* Is RIP running or is this RIP neighbor ?*/ 1775 ri = ifp->info; 1776 if (! ri->running && ! rip_neighbor_lookup (&from)) 1777 { 1778#ifdef FOX_RIP_DEBUG 1779 if (IS_RIP_DEBUG_EVENT) 1780 zlog_info ("RIP is not enabled on interface %s.", ifp->name); 1781 rip_peer_bad_packet (&from); 1782#endif /* FOX_RIP_DEBUG */ 1783 return -1; 1784 } 1785 1786 /* RIP Version check. */ 1787 if (packet->command == RIP_RESPONSE) 1788 { 1789 if (ri->ri_receive == RI_RIP_UNSPEC) 1790 { 1791 if (packet->version != rip->version) 1792 { 1793#ifdef FOX_RIP_DEBUG 1794 if (IS_RIP_DEBUG_PACKET) 1795 zlog_warn (" packet's v%d doesn't fit to my version %d", 1796 packet->version, rip->version); 1797 rip_peer_bad_packet (&from); 1798#endif /* FOX_RIP_DEBUG */ 1799 return -1; 1800 } 1801 } 1802 else 1803 { 1804 if (packet->version == RIPv1) 1805 if (! (ri->ri_receive & RIPv1)) 1806 { 1807#ifdef FOX_RIP_DEBUG 1808 if (IS_RIP_DEBUG_PACKET) 1809 zlog_warn (" packet's v%d doesn't fit to if version spec", 1810 packet->version); 1811 rip_peer_bad_packet (&from); 1812#endif /* FOX_RIP_DEBUG */ 1813 return -1; 1814 } 1815 if (packet->version == RIPv2) 1816 if (! (ri->ri_receive & RIPv2)) 1817 { 1818#ifdef FOX_RIP_DEBUG 1819 if (IS_RIP_DEBUG_PACKET) 1820 zlog_warn (" packet's v%d doesn't fit to if version spec", 1821 packet->version); 1822 rip_peer_bad_packet (&from); 1823#endif /* FOX_RIP_DEBUG */ 1824 return -1; 1825 } 1826 } 1827 } 1828 1829 /* RFC2453 5.2 If the router is not configured to authenticate RIP-2 1830 messages, then RIP-1 and unauthenticated RIP-2 messages will be 1831 accepted; authenticated RIP-2 messages shall be discarded. */ 1832 1833 if ((ri->auth_type == RIP_NO_AUTH) 1834 && rtenum 1835 && (packet->version == RIPv2) && (packet->rte->family == 0xffff)) 1836 { 1837#ifdef FOX_RIP_DEBUG 1838 if (IS_RIP_DEBUG_EVENT) 1839 zlog_warn ("packet RIPv%d is dropped because authentication disabled", 1840 packet->version); 1841 rip_peer_bad_packet (&from); 1842#endif /* FOX_RIP_DEBUG */ 1843 return -1; 1844 } 1845 1846 /* If the router is configured to authenticate RIP-2 messages, then 1847 RIP-1 messages and RIP-2 messages which pass authentication 1848 testing shall be accepted; unauthenticated and failed 1849 authentication RIP-2 messages shall be discarded. For maximum 1850 security, RIP-1 messages should be ignored when authentication is 1851 in use (see section 4.1); otherwise, the routing information from 1852 authenticated messages will be propagated by RIP-1 routers in an 1853 unauthenticated manner. */ 1854 1855#ifdef FOX_AUTH_SUPPORT 1856 if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD 1857 || ri->auth_type == RIP_AUTH_MD5) 1858 && rtenum) 1859 { 1860 /* We follow maximum security. */ 1861 if (packet->version == RIPv1 && packet->rte->family == 0xffff) 1862 { 1863#ifdef FOX_RIP_DEBUG 1864 if (IS_RIP_DEBUG_PACKET) 1865 zlog_warn ("packet RIPv%d is dropped because authentication enabled", packet->version); 1866 rip_peer_bad_packet (&from); 1867#endif /* FOX_RIP_DEBUG */ 1868 return -1; 1869 } 1870 1871 /* Check RIPv2 authentication. */ 1872 if (packet->version == RIPv2) 1873 { 1874 if (packet->rte->family == 0xffff) 1875 { 1876 if (ntohs (packet->rte->tag) == RIP_AUTH_SIMPLE_PASSWORD) 1877 { 1878 ret = rip_auth_simple_password (packet->rte, &from, ifp); 1879 if (! ret) 1880 { 1881#ifdef FOX_RIP_DEBUG 1882 if (IS_RIP_DEBUG_EVENT) 1883 zlog_warn ("RIPv2 simple password authentication failed"); 1884 rip_peer_bad_packet (&from); 1885#endif /* FOX_RIP_DEBUG */ 1886 return -1; 1887 } 1888 else 1889 { 1890#ifdef FOX_RIP_DEBUG 1891 if (IS_RIP_DEBUG_EVENT) 1892 zlog_info ("RIPv2 simple password authentication success"); 1893#endif /* FOX_RIP_DEBUG */ 1894 } 1895 } 1896 else if (ntohs (packet->rte->tag) == RIP_AUTH_MD5) 1897 { 1898 ret = rip_auth_md5 (packet, &from, ifp); 1899 if (! ret) 1900 { 1901#ifdef FOX_RIP_DEBUG 1902 if (IS_RIP_DEBUG_EVENT) 1903 zlog_warn ("RIPv2 MD5 authentication failed"); 1904 rip_peer_bad_packet (&from); 1905#endif /* FOX_RIP_DEBUG */ 1906 return -1; 1907 } 1908 else 1909 { 1910#ifdef FOX_RIP_DEBUG 1911 if (IS_RIP_DEBUG_EVENT) 1912 zlog_info ("RIPv2 MD5 authentication success"); 1913#endif /* FOX_RIP_DEBUG */ 1914 } 1915 /* Reset RIP packet length to trim MD5 data. */ 1916 len = ret; 1917 } 1918 else 1919 { 1920#ifdef FOX_RIP_DEBUG 1921 if (IS_RIP_DEBUG_EVENT) 1922 zlog_warn ("Unknown authentication type %d", 1923 ntohs (packet->rte->tag)); 1924 rip_peer_bad_packet (&from); 1925#endif /* FOX_RIP_DEBUG */ 1926 return -1; 1927 } 1928 } 1929 else 1930 { 1931 /* There is no authentication in the packet. */ 1932 if (ri->auth_str || ri->key_chain) 1933 { 1934#ifdef FOX_RIP_DEBUG 1935 if (IS_RIP_DEBUG_EVENT) 1936 zlog_warn ("RIPv2 authentication failed: no authentication in packet"); 1937 rip_peer_bad_packet (&from); 1938#endif /* FOX_RIP_DEBUG */ 1939 return -1; 1940 } 1941 } 1942 } 1943 } 1944#endif /* FOX_AUTH_SUPPORT */ 1945 1946 /* Process each command. */ 1947 switch (packet->command) 1948 { 1949 case RIP_RESPONSE: 1950 rip_response_process (packet, len, &from, ifp); 1951 break; 1952 case RIP_REQUEST: 1953 case RIP_POLL: 1954 rip_request_process (packet, len, &from, ifp); 1955 break; 1956 case RIP_TRACEON: 1957 case RIP_TRACEOFF: 1958#ifdef FOX_RIP_DEBUG 1959 zlog_info ("Obsolete command %s received, please sent it to routed", 1960 lookup (rip_msg, packet->command)); 1961 rip_peer_bad_packet (&from); 1962#endif /* FOX_RIP_DEBUG */ 1963 break; 1964 case RIP_POLL_ENTRY: 1965#ifdef FOX_RIP_DEBUG 1966 zlog_info ("Obsolete command %s received", 1967 lookup (rip_msg, packet->command)); 1968 rip_peer_bad_packet (&from); 1969#endif /* FOX_RIP_DEBUG */ 1970 break; 1971 default: 1972#ifdef FOX_RIP_DEBUG 1973 zlog_info ("Unknown RIP command %d received", packet->command); 1974 rip_peer_bad_packet (&from); 1975#endif /* FOX_RIP_DEBUG */ 1976 break; 1977 } 1978 1979 return len; 1980} 1981 1982/* Make socket for RIP protocol. */ 1983int 1984rip_create_socket () 1985{ 1986 int ret; 1987 int sock; 1988 struct sockaddr_in addr; 1989 struct servent *sp; 1990 1991 memset (&addr, 0, sizeof (struct sockaddr_in)); 1992 1993 /* Set RIP port. */ 1994 sp = getservbyname ("router", "udp"); 1995 if (sp) 1996 addr.sin_port = sp->s_port; 1997 else 1998 addr.sin_port = htons (RIP_PORT_DEFAULT); 1999 2000 /* Address shoud be any address. */ 2001 addr.sin_family = AF_INET; 2002 addr.sin_addr.s_addr = INADDR_ANY; 2003 2004 /* Make datagram socket. */ 2005 sock = socket (AF_INET, SOCK_DGRAM, 0); 2006 if (sock < 0) 2007 { 2008 perror ("socket"); 2009 exit (1); 2010 } 2011 2012 sockopt_broadcast (sock); 2013 sockopt_reuseaddr (sock); 2014 sockopt_reuseport (sock); 2015#ifdef RIP_RECVMSG 2016 setsockopt_pktinfo (sock); 2017#endif /* RIP_RECVMSG */ 2018 2019 ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr)); 2020 if (ret < 0) 2021 { 2022 perror ("bind"); 2023 return ret; 2024 } 2025 2026 return sock; 2027} 2028 2029/* Write routing table entry to the stream and return next index of 2030 the routing table entry in the stream. */ 2031int 2032rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p, 2033 u_char version, struct rip_info *rinfo, struct interface *ifp) 2034{ 2035 struct in_addr mask; 2036 struct rip_interface *ri; 2037 2038 /* foxconn added start by EricHuang, 11/07/2007 */ 2039//#ifdef U12H072 2040/* Foxconn mark start by aspen Bai, 07/17/2008 */ 2041//#if (defined(U12H072) || defined(U12H083) || defined(U12H081)) 2042 int i=0; 2043//#endif 2044/* Foxconn mark end by aspen Bai, 07/17/2008 */ 2045 /* foxconn added end by EricHuang, 11/07/2007 */ 2046 2047 /* RIP packet header. */ 2048 if (num == 0) 2049 { 2050 stream_putc (s, RIP_RESPONSE); 2051 stream_putc (s, version); 2052 stream_putw (s, 0); 2053 2054#ifdef FOX_AUTH_SUPPORT 2055 /* In case of we need RIPv2 authentication. */ 2056 if (version == RIPv2 && ifp) 2057 { 2058 ri = ifp->info; 2059 2060 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) 2061 { 2062 if (ri->auth_str) 2063 { 2064 stream_putw (s, 0xffff); 2065 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD); 2066 2067 memset ((s->data + s->putp), 0, 16); 2068 strncpy ((s->data + s->putp), ri->auth_str, 16); 2069 stream_set_putp (s, s->putp + 16); 2070 2071 num++; 2072 } 2073 if (ri->key_chain) 2074 { 2075 struct keychain *keychain; 2076 struct key *key; 2077 2078 keychain = keychain_lookup (ri->key_chain); 2079 2080 if (keychain) 2081 { 2082 key = key_lookup_for_send (keychain); 2083 2084 if (key) 2085 { 2086 stream_putw (s, 0xffff); 2087 stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD); 2088 2089 memset ((s->data + s->putp), 0, 16); 2090 strncpy ((s->data + s->putp), key->string, 16); 2091 stream_set_putp (s, s->putp + 16); 2092 2093 num++; 2094 } 2095 } 2096 } 2097 } 2098 } 2099#endif /* FOX_AUTH_SUPPORT */ 2100 } 2101 2102 /* foxconn added start by EricHuang, 11/07/2007 */ 2103 /* replace metric value here */ 2104//#ifdef U12H072 2105/* Foxconn mark start by aspen Bai, 07/17/2008 */ 2106//#if (defined(U12H072) || defined(U12H083) || defined(U12H081)) 2107/* Foxconn mark end by aspen Bai, 07/17/2008 */ 2108 for (i=0; i<max_fox_rt_info; i++) 2109 { 2110 if ( IPV4_ADDR_SAME (&p->prefix, &fox_rt_info_table[i].prefix) ) 2111 { 2112 //char str[256]; 2113 //sprintf(str, "SAME: %s, %s\n", inet_ntoa(p->prefix), inet_ntoa(fox_rt_info_table[i].prefix)); 2114 //my_log(str); 2115 if ( fox_rt_info_table[i].metric > 0 ) 2116 { 2117 rinfo->metric_out = fox_rt_info_table[i].metric; 2118 } 2119 break; 2120 } 2121 } 2122/* Foxconn mark start by aspen Bai, 07/17/2008 */ 2123//#endif 2124/* Foxconn mark end by aspen Bai, 07/17/2008 */ 2125 /* foxconn added end by EricHuang, 11/07/2007 */ 2126 2127 /* Write routing table entry. */ 2128 if (version == RIPv1) 2129 { 2130 stream_putw (s, AF_INET); 2131 stream_putw (s, 0); 2132 stream_put_ipv4 (s, p->prefix.s_addr); 2133 stream_put_ipv4 (s, 0); 2134 stream_put_ipv4 (s, 0); 2135 stream_putl (s, rinfo->metric_out); 2136 } 2137 else 2138 { 2139 masklen2ip (p->prefixlen, &mask); 2140 2141 stream_putw (s, AF_INET); 2142 stream_putw (s, rinfo->tag); 2143 stream_put_ipv4 (s, p->prefix.s_addr); 2144 stream_put_ipv4 (s, mask.s_addr); 2145 stream_put_ipv4 (s, rinfo->nexthop_out.s_addr); 2146 stream_putl (s, rinfo->metric_out); 2147 } 2148 2149 return ++num; 2150} 2151 2152/* Send update to the ifp or spcified neighbor. */ 2153void 2154rip_output_process (struct interface *ifp, struct sockaddr_in *to, 2155 int route_type, u_char version) 2156{ 2157 int ret; 2158 struct stream *s; 2159 struct route_node *rp; 2160 struct rip_info *rinfo; 2161 struct rip_interface *ri; 2162 struct prefix_ipv4 *p; 2163 struct prefix_ipv4 classfull; 2164 int num; 2165 int rtemax; 2166 2167#ifdef FOX_RIP_DEBUG 2168 /* Logging output event. */ 2169 if (IS_RIP_DEBUG_EVENT) 2170 { 2171 if (to) 2172 zlog_info ("update routes to neighbor %s", inet_ntoa (to->sin_addr)); 2173 else 2174 zlog_info ("update routes on interface %s ifindex %d", 2175 ifp->name, ifp->ifindex); 2176 } 2177#endif /* FOX_RIP_DEBUG */ 2178 2179 /* Set output stream. */ 2180 s = rip->obuf; 2181 2182 /* Reset stream and RTE counter. */ 2183 stream_reset (s); 2184 num = 0; 2185 rtemax = (RIP_PACKET_MAXSIZ - 4) / 20; 2186 2187 /* Get RIP interface. */ 2188 ri = ifp->info; 2189 2190#ifdef FOX_AUTH_SUPPORT 2191 /* If output interface is in simple password authentication mode, we 2192 need space for authentication data. */ 2193 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) 2194 rtemax -= 1; 2195 2196 /* If output interface is in MD5 authentication mode, we need space 2197 for authentication header and data. */ 2198 if (ri->auth_type == RIP_AUTH_MD5) 2199 rtemax -= 2; 2200 2201 /* If output interface is in simple password authentication mode 2202 and string or keychain is specified we need space for auth. data */ 2203 if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) 2204 { 2205 if (ri->key_chain) 2206 { 2207 struct keychain *keychain; 2208 2209 keychain = keychain_lookup (ri->key_chain); 2210 if (keychain) 2211 if (key_lookup_for_send (keychain)) 2212 rtemax -=1; 2213 } 2214 else 2215 if (ri->auth_str) 2216 rtemax -=1; 2217 } 2218#endif /* FOX_AUTH_SUPPORT */ 2219 2220 for (rp = route_top (rip->table); rp; rp = route_next (rp)) 2221 if ((rinfo = rp->info) != NULL) 2222 { 2223 /* Some inheritance stuff: */ 2224 /* Before we process with ipv4 prefix we should mask it */ 2225 /* with Classful mask if we send RIPv1 packet.That's because */ 2226 /* user could set non-classful mask or we could get it by RIPv2 */ 2227 /* or other protocol. checked with Cisco's way of life :) */ 2228 2229 if (version == RIPv1) 2230 { 2231 memcpy (&classfull, &rp->p, sizeof (struct prefix_ipv4)); 2232#ifdef FOX_RIP_DEBUG 2233 if (IS_RIP_DEBUG_PACKET) 2234 zlog_info("%s/%d before RIPv1 mask check ", 2235 inet_ntoa (classfull.prefix), classfull.prefixlen); 2236#endif /* FOX_RIP_DEBUG */ 2237 apply_classful_mask_ipv4 (&classfull); 2238 p = &classfull; 2239#ifdef FOX_RIP_DEBUG 2240 if (IS_RIP_DEBUG_PACKET) 2241 zlog_info("%s/%d after RIPv1 mask check", 2242 inet_ntoa (p->prefix), p->prefixlen); 2243#endif 2244 } 2245 else 2246 p = (struct prefix_ipv4 *) &rp->p; 2247 2248 /* Apply output filters. */ 2249 ret = rip_outgoing_filter (p, ri); 2250 if (ret < 0) 2251 continue; 2252 2253 /* Changed route only output. */ 2254 if (route_type == rip_changed_route && 2255 (! (rinfo->flags & RIP_RTF_CHANGED))) 2256 continue; 2257 2258 /* Split horizon. */ 2259 /* if (split_horizon == rip_split_horizon) */ 2260 if (ri->split_horizon) 2261 { 2262 /* We perform split horizon for RIP and connected route. */ 2263 if ((rinfo->type == ZEBRA_ROUTE_RIP || 2264 rinfo->type == ZEBRA_ROUTE_CONNECT) && 2265 rinfo->ifindex == ifp->ifindex) 2266 continue; 2267 } 2268 2269 /* Preparation for route-map. */ 2270 rinfo->metric_set = 0; 2271 rinfo->nexthop_out.s_addr = 0; 2272 rinfo->metric_out = rinfo->metric; 2273 rinfo->ifindex_out = ifp->ifindex; 2274 2275 /* In order to avoid some local loops, if the RIP route has a 2276 nexthop via this interface, keep the nexthop, otherwise set 2277 it to 0. The nexthop should not be propagated beyond the 2278 local broadcast/multicast area in order to avoid an IGP 2279 multi-level recursive look-up. For RIP and connected 2280 route, we don't set next hop value automatically. For 2281 settting next hop to those routes, please use 2282 route-map. */ 2283 2284 if (rinfo->type != ZEBRA_ROUTE_RIP 2285 && rinfo->type != ZEBRA_ROUTE_CONNECT 2286 && rinfo->ifindex == ifp->ifindex) 2287 rinfo->nexthop_out = rinfo->nexthop; 2288 2289#ifdef FOX_LIST_SUPPORT 2290 /* Apply route map - continue, if deny */ 2291 if (rip->route_map[rinfo->type].name 2292 && rinfo->sub_type != RIP_ROUTE_INTERFACE) 2293 { 2294 ret = route_map_apply (rip->route_map[rinfo->type].map, 2295 (struct prefix *)p, RMAP_RIP, rinfo); 2296 2297 if (ret == RMAP_DENYMATCH) 2298 { 2299#ifdef FOX_RIP_DEBUG 2300 if (IS_RIP_DEBUG_PACKET) 2301 zlog_info ("%s/%d is filtered by route-map", 2302 inet_ntoa (p->prefix), p->prefixlen); 2303#endif /* FOX_RIP_DEBUG */ 2304 continue; 2305 } 2306 } 2307#endif /* FOX_LIST_SUPPORT */ 2308 /* When route-map does not set metric. */ 2309 if (! rinfo->metric_set) 2310 { 2311 /* If redistribute metric is set. */ 2312 if (rip->route_map[rinfo->type].metric_config 2313 && rinfo->metric != RIP_METRIC_INFINITY) 2314 { 2315 rinfo->metric_out = rip->route_map[rinfo->type].metric; 2316 } 2317 else 2318 { 2319 /* If the route is not connected or localy generated 2320 one, use default-metric value*/ 2321 if (rinfo->type != ZEBRA_ROUTE_RIP 2322 && rinfo->type != ZEBRA_ROUTE_CONNECT 2323 && rinfo->metric != RIP_METRIC_INFINITY) 2324 rinfo->metric_out = rip->default_metric; 2325 } 2326 } 2327 2328#ifdef FOX_LIST_SUPPORT 2329 /* Apply offset-list */ 2330 if (rinfo->metric != RIP_METRIC_INFINITY) 2331 rip_offset_list_apply_out (p, ifp, &rinfo->metric_out); 2332 2333 if (rinfo->metric_out > RIP_METRIC_INFINITY) 2334 rinfo->metric_out = RIP_METRIC_INFINITY; 2335#endif /* FOX_LIST_SUPPORT */ 2336 /* Write RTE to the stream. */ 2337 num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp); 2338 if (num == rtemax) 2339 { 2340#ifdef FOX_AUTH_SUPPORT 2341 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) 2342 rip_auth_md5_set (s, ifp); 2343#endif /* BRCM_AUTH_SUPPORT */ 2344 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), 2345 to, ifp); 2346#ifdef FOX_RIP_DEBUG 2347 if (ret >= 0 && IS_RIP_DEBUG_SEND) 2348 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s), 2349 stream_get_endp(s), "SEND"); 2350#endif /* FOX_RIP_DEBUG */ 2351 num = 0; 2352 stream_reset (s); 2353 } 2354 } 2355 2356 /* Flush unwritten RTE. */ 2357 if (num != 0) 2358 { 2359#ifdef FOX_AUTH_SUPPORT 2360 if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) 2361 rip_auth_md5_set (s, ifp); 2362#endif /* BRCM_AUTH_SUPPORT */ 2363 2364 ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp); 2365#ifdef FOX_RIP_DEBUG 2366 if (ret >= 0 && IS_RIP_DEBUG_SEND) 2367 rip_packet_dump ((struct rip_packet *)STREAM_DATA (s), 2368 stream_get_endp (s), "SEND"); 2369#endif /* FOX_RIP_DEBUG */ 2370 num = 0; 2371 stream_reset (s); 2372 } 2373 2374 /* Statistics updates. */ 2375 ri->sent_updates++; 2376} 2377 2378/* Send RIP packet to the interface. */ 2379void 2380rip_update_interface (struct interface *ifp, u_char version, int route_type) 2381{ 2382 struct prefix_ipv4 *p; 2383 struct connected *connected; 2384 listnode node; 2385 struct sockaddr_in to; 2386 2387 /* When RIP version is 2 and multicast enable interface. */ 2388 if (version == RIPv2 && if_is_multicast (ifp)) 2389 { 2390#ifdef FOX_RIP_DEBUG 2391 if (IS_RIP_DEBUG_EVENT) 2392 zlog_info ("multicast announce on %s ", ifp->name); 2393#endif /* FOX_RIP_DEBUG */ 2394 rip_output_process (ifp, NULL, route_type, version); 2395 return; 2396 } 2397 2398 /* If we can't send multicast packet, send it with unicast. */ 2399 if (if_is_broadcast (ifp) || if_is_pointopoint (ifp)) 2400 { 2401 for (node = listhead (ifp->connected); node; nextnode (node)) 2402 { 2403 connected = getdata (node); 2404 2405 /* Fetch broadcast address or poin-to-point destination 2406 address . */ 2407 p = (struct prefix_ipv4 *) connected->destination; 2408 2409 if (p->family == AF_INET) 2410 { 2411 /* Destination address and port setting. */ 2412 memset (&to, 0, sizeof (struct sockaddr_in)); 2413 to.sin_addr = p->prefix; 2414 to.sin_port = htons (RIP_PORT_DEFAULT); 2415#ifdef FOX_RIP_DEBUG 2416 if (IS_RIP_DEBUG_EVENT) 2417 zlog_info ("%s announce to %s on %s", 2418 if_is_pointopoint (ifp) ? "unicast" : "broadcast", 2419 inet_ntoa (to.sin_addr), ifp->name); 2420#endif /* FOX_RIP_DEBUG */ 2421 rip_output_process (ifp, &to, route_type, version); 2422 } 2423 } 2424 } 2425} 2426 2427/* Update send to all interface and neighbor. */ 2428void 2429rip_update_process (int route_type) 2430{ 2431 listnode node; 2432 struct interface *ifp; 2433 struct rip_interface *ri; 2434 struct route_node *rp; 2435 struct sockaddr_in to; 2436 struct prefix_ipv4 *p; 2437 2438 /* Send RIP update to each interface. */ 2439 for (node = listhead (iflist); node; nextnode (node)) 2440 { 2441 ifp = getdata (node); 2442 2443 if (if_is_loopback (ifp)) 2444 continue; 2445 2446 if (! if_is_up (ifp)) 2447 continue; 2448 2449 /* Fetch RIP interface information. */ 2450 ri = ifp->info; 2451 2452 /* When passive interface is specified, suppress announce to the 2453 interface. */ 2454 if (ri->passive) 2455 continue; 2456 2457 if (ri->running) 2458 { 2459#ifdef FOX_RIP_DEBUG 2460 if (IS_RIP_DEBUG_EVENT) 2461 { 2462 if (ifp->name) 2463 zlog_info ("SEND UPDATE to %s ifindex %d", 2464 ifp->name, ifp->ifindex); 2465 else 2466 zlog_info ("SEND UPDATE to _unknown_ ifindex %d", 2467 ifp->ifindex); 2468 } 2469#endif /* FOX_RIP_DEBUG */ 2470 /* If there is no version configuration in the interface, 2471 use rip's version setting. */ 2472 if (ri->ri_send == RI_RIP_UNSPEC) 2473 { 2474 if (rip->version == RIPv1) 2475 rip_update_interface (ifp, RIPv1, route_type); 2476 else 2477 rip_update_interface (ifp, RIPv2, route_type); 2478 } 2479 /* If interface has RIP version configuration use it. */ 2480 else 2481 { 2482 if (ri->ri_send & RIPv1) 2483 rip_update_interface (ifp, RIPv1, route_type); 2484 if (ri->ri_send & RIPv2) 2485 rip_update_interface (ifp, RIPv2, route_type); 2486 } 2487 } 2488 } 2489 2490 /* RIP send updates to each neighbor. */ 2491 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp)) 2492 if (rp->info != NULL) 2493 { 2494 p = (struct prefix_ipv4 *) &rp->p; 2495 2496 ifp = if_lookup_address (p->prefix); 2497 if (! ifp) 2498 { 2499#ifdef FOX_RIP_DEBUG 2500 zlog_warn ("Neighbor %s doesn't exist direct connected network", 2501 inet_ntoa (p->prefix)); 2502#endif /* FOX_RIP_DEBUG */ 2503 continue; 2504 } 2505 2506 /* Set destination address and port */ 2507 memset (&to, 0, sizeof (struct sockaddr_in)); 2508 to.sin_addr = p->prefix; 2509 to.sin_port = htons (RIP_PORT_DEFAULT); 2510 2511 /* RIP version is rip's configuration. */ 2512 rip_output_process (ifp, &to, route_type, rip->version); 2513 } 2514} 2515 2516/* RIP's periodical timer. */ 2517int 2518rip_update (struct thread *t) 2519{ 2520 /* Clear timer pointer. */ 2521 rip->t_update = NULL; 2522 2523#ifdef FOX_RIP_DEBUG 2524 if (IS_RIP_DEBUG_EVENT) 2525 zlog_info ("update timer fire!"); 2526#endif /* FOX_RIP_DEBUG */ 2527 2528 /* Process update output. */ 2529 rip_update_process (rip_all_route); 2530 2531 /* Triggered updates may be suppressed if a regular update is due by 2532 the time the triggered update would be sent. */ 2533 if (rip->t_triggered_interval) 2534 { 2535 thread_cancel (rip->t_triggered_interval); 2536 rip->t_triggered_interval = NULL; 2537 } 2538 rip->trigger = 0; 2539 2540 /* Register myself. */ 2541 rip_event (RIP_UPDATE_EVENT, 0); 2542 2543 return 0; 2544} 2545 2546/* Walk down the RIP routing table then clear changed flag. */ 2547void 2548rip_clear_changed_flag () 2549{ 2550 struct route_node *rp; 2551 struct rip_info *rinfo; 2552 2553 for (rp = route_top (rip->table); rp; rp = route_next (rp)) 2554 if ((rinfo = rp->info) != NULL) 2555 if (rinfo->flags & RIP_RTF_CHANGED) 2556 rinfo->flags &= ~RIP_RTF_CHANGED; 2557} 2558 2559/* Triggered update interval timer. */ 2560int 2561rip_triggered_interval (struct thread *t) 2562{ 2563 int rip_triggered_update (struct thread *); 2564 2565 rip->t_triggered_interval = NULL; 2566 2567 if (rip->trigger) 2568 { 2569 rip->trigger = 0; 2570 rip_triggered_update (t); 2571 } 2572 return 0; 2573} 2574 2575/* Execute triggered update. */ 2576int 2577rip_triggered_update (struct thread *t) 2578{ 2579 int interval; 2580 2581 /* Clear thred pointer. */ 2582 rip->t_triggered_update = NULL; 2583 2584 /* Cancel interval timer. */ 2585 if (rip->t_triggered_interval) 2586 { 2587 thread_cancel (rip->t_triggered_interval); 2588 rip->t_triggered_interval = NULL; 2589 } 2590 rip->trigger = 0; 2591 2592#ifdef FOX_RIP_DEBUG 2593 /* Logging triggered update. */ 2594 if (IS_RIP_DEBUG_EVENT) 2595 zlog_info ("triggered update!"); 2596#endif /* FOX_RIP_DEBUG */ 2597 2598 /* Split Horizon processing is done when generating triggered 2599 updates as well as normal updates (see section 2.6). */ 2600 rip_update_process (rip_changed_route); 2601 2602 /* Once all of the triggered updates have been generated, the route 2603 change flags should be cleared. */ 2604 rip_clear_changed_flag (); 2605 2606 /* After a triggered update is sent, a timer should be set for a 2607 random interval between 1 and 5 seconds. If other changes that 2608 would trigger updates occur before the timer expires, a single 2609 update is triggered when the timer expires. */ 2610 interval = (random () % 5) + 1; 2611 2612 rip->t_triggered_interval = 2613 thread_add_timer (master, rip_triggered_interval, NULL, interval); 2614 2615 return 0; 2616} 2617 2618/* Withdraw redistributed route. */ 2619void 2620rip_redistribute_withdraw (int type) 2621{ 2622 struct route_node *rp; 2623 struct rip_info *rinfo; 2624 2625 if (!rip) 2626 return; 2627 2628 for (rp = route_top (rip->table); rp; rp = route_next (rp)) 2629 if ((rinfo = rp->info) != NULL) 2630 { 2631 if (rinfo->type == type 2632 && rinfo->sub_type != RIP_ROUTE_INTERFACE) 2633 { 2634 /* Perform poisoned reverse. */ 2635 rinfo->metric = RIP_METRIC_INFINITY; 2636 RIP_TIMER_ON (rinfo->t_garbage_collect, 2637 rip_garbage_collect, rip->garbage_time); 2638 RIP_TIMER_OFF (rinfo->t_timeout); 2639 rinfo->flags |= RIP_RTF_CHANGED; 2640 2641 rip_event (RIP_TRIGGERED_UPDATE, 0); 2642 } 2643 } 2644} 2645 2646/* Create new RIP instance and set it to global variable. */ 2647int 2648rip_create () 2649{ 2650 rip = XMALLOC (MTYPE_RIP, sizeof (struct rip)); 2651 memset (rip, 0, sizeof (struct rip)); 2652 2653 /* Set initial value. */ 2654 rip->version = RIPv2; 2655 rip->update_time = RIP_UPDATE_TIMER_DEFAULT; 2656 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; 2657 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; 2658 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; 2659 2660 /* Initialize RIP routig table. */ 2661 rip->table = route_table_init (); 2662 rip->route = route_table_init (); 2663 rip->neighbor = route_table_init (); 2664 2665 /* Make output stream. */ 2666 rip->obuf = stream_new (1500); 2667 2668 /* Make socket. */ 2669 rip->sock = rip_create_socket (); 2670 if (rip->sock < 0) 2671 return rip->sock; 2672 2673 /* Create read and timer thread. */ 2674 rip_event (RIP_READ, rip->sock); 2675 rip_event (RIP_UPDATE_EVENT, 1); 2676 2677 return 0; 2678} 2679 2680/* Sned RIP request to the destination. */ 2681int 2682rip_request_send (struct sockaddr_in *to, struct interface *ifp, 2683 u_char version) 2684{ 2685 struct rte *rte; 2686 struct rip_packet rip_packet; 2687 2688 memset (&rip_packet, 0, sizeof (rip_packet)); 2689 2690 rip_packet.command = RIP_REQUEST; 2691 rip_packet.version = version; 2692 rte = rip_packet.rte; 2693 rte->metric = htonl (RIP_METRIC_INFINITY); 2694 2695 return rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet), to, ifp); 2696} 2697 2698int 2699rip_update_jitter (unsigned long time) 2700{ 2701 return ((rand () % (time + 1)) - (time / 2)); 2702} 2703 2704void 2705rip_event (enum rip_event event, int sock) 2706{ 2707 int jitter = 0; 2708 2709 switch (event) 2710 { 2711 case RIP_READ: 2712 rip->t_read = thread_add_read (master, rip_read, NULL, sock); 2713 break; 2714 case RIP_UPDATE_EVENT: 2715 if (rip->t_update) 2716 { 2717 thread_cancel (rip->t_update); 2718 rip->t_update = NULL; 2719 } 2720 jitter = rip_update_jitter (rip->update_time); 2721 rip->t_update = 2722 thread_add_timer (master, rip_update, NULL, 2723 sock ? 2 : rip->update_time + jitter); 2724 break; 2725 case RIP_TRIGGERED_UPDATE: 2726 if (rip->t_triggered_interval) 2727 rip->trigger = 1; 2728 else if (! rip->t_triggered_update) 2729 rip->t_triggered_update = 2730 thread_add_event (master, rip_triggered_update, NULL, 0); 2731 break; 2732 default: 2733 break; 2734 } 2735} 2736 2737DEFUN (router_rip, 2738 router_rip_cmd, 2739 "router rip", 2740 "Enable a routing process\n" 2741 "Routing Information Protocol (RIP)\n") 2742{ 2743 int ret; 2744 2745 /* If rip is not enabled before. */ 2746 if (! rip) 2747 { 2748 ret = rip_create (); 2749 if (ret < 0) 2750 { 2751#ifdef FOX_RIP_DEBUG 2752 zlog_info ("Can't create RIP"); 2753#endif /* FOX_RIP_DEBUG */ 2754 return CMD_WARNING; 2755 } 2756 } 2757 vty->node = RIP_NODE; 2758 vty->index = rip; 2759 2760 return CMD_SUCCESS; 2761} 2762 2763DEFUN (no_router_rip, 2764 no_router_rip_cmd, 2765 "no router rip", 2766 NO_STR 2767 "Enable a routing process\n" 2768 "Routing Information Protocol (RIP)\n") 2769{ 2770 if (rip) 2771 rip_clean (); 2772 return CMD_SUCCESS; 2773} 2774 2775#ifdef FOX_CMD_SUPPORT 2776DEFUN (rip_version, 2777 rip_version_cmd, 2778 "version <1-2>", 2779 "Set routing protocol version\n" 2780 "version\n") 2781{ 2782 int version; 2783 2784 version = atoi (argv[0]); 2785 if (version != RIPv1 && version != RIPv2) 2786 { 2787 vty_out (vty, "invalid rip version %d%s", version, 2788 VTY_NEWLINE); 2789 return CMD_WARNING; 2790 } 2791 rip->version = version; 2792 2793 return CMD_SUCCESS; 2794} 2795 2796DEFUN (no_rip_version, 2797 no_rip_version_cmd, 2798 "no version", 2799 NO_STR 2800 "Set routing protocol version\n") 2801{ 2802 /* Set RIP version to the default. */ 2803 rip->version = RIPv2; 2804 2805 return CMD_SUCCESS; 2806} 2807 2808ALIAS (no_rip_version, 2809 no_rip_version_val_cmd, 2810 "no version <1-2>", 2811 NO_STR 2812 "Set routing protocol version\n" 2813 "version\n") 2814 2815DEFUN (rip_route, 2816 rip_route_cmd, 2817 "route A.B.C.D/M", 2818 "RIP static route configuration\n" 2819 "IP prefix <network>/<length>\n") 2820{ 2821 int ret; 2822 struct prefix_ipv4 p; 2823 struct route_node *node; 2824 2825 ret = str2prefix_ipv4 (argv[0], &p); 2826 if (ret < 0) 2827 { 2828 vty_out (vty, "Malformed address%s", VTY_NEWLINE); 2829 return CMD_WARNING; 2830 } 2831 apply_mask_ipv4 (&p); 2832 2833 /* For router rip configuration. */ 2834 node = route_node_get (rip->route, (struct prefix *) &p); 2835 2836 if (node->info) 2837 { 2838 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE); 2839 route_unlock_node (node); 2840 return CMD_WARNING; 2841 } 2842 2843 node->info = "static"; 2844 2845 rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL); 2846 2847 return CMD_SUCCESS; 2848} 2849 2850DEFUN (no_rip_route, 2851 no_rip_route_cmd, 2852 "no route A.B.C.D/M", 2853 NO_STR 2854 "RIP static route configuration\n" 2855 "IP prefix <network>/<length>\n") 2856{ 2857 int ret; 2858 struct prefix_ipv4 p; 2859 struct route_node *node; 2860 2861 ret = str2prefix_ipv4 (argv[0], &p); 2862 if (ret < 0) 2863 { 2864 vty_out (vty, "Malformed address%s", VTY_NEWLINE); 2865 return CMD_WARNING; 2866 } 2867 apply_mask_ipv4 (&p); 2868 2869 /* For router rip configuration. */ 2870 node = route_node_lookup (rip->route, (struct prefix *) &p); 2871 if (! node) 2872 { 2873 vty_out (vty, "Can't find route %s.%s", argv[0], 2874 VTY_NEWLINE); 2875 return CMD_WARNING; 2876 } 2877 2878 rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); 2879 route_unlock_node (node); 2880 2881 node->info = NULL; 2882 route_unlock_node (node); 2883 2884 return CMD_SUCCESS; 2885} 2886#endif /* FOX_CMD_SUPPORT */ 2887void 2888rip_update_default_metric () 2889{ 2890 struct route_node *np; 2891 struct rip_info *rinfo; 2892 2893 for (np = route_top (rip->table); np; np = route_next (np)) 2894 if ((rinfo = np->info) != NULL) 2895 if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT) 2896 rinfo->metric = rip->default_metric; 2897} 2898 2899DEFUN (rip_default_metric, 2900 rip_default_metric_cmd, 2901 "default-metric <1-16>", 2902 "Set a metric of redistribute routes\n" 2903 "Default metric\n") 2904{ 2905 if (rip) 2906 { 2907 rip->default_metric = atoi (argv[0]); 2908 /* rip_update_default_metric (); */ 2909 } 2910 return CMD_SUCCESS; 2911} 2912 2913DEFUN (no_rip_default_metric, 2914 no_rip_default_metric_cmd, 2915 "no default-metric", 2916 NO_STR 2917 "Set a metric of redistribute routes\n" 2918 "Default metric\n") 2919{ 2920 if (rip) 2921 { 2922 rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; 2923 /* rip_update_default_metric (); */ 2924 } 2925 return CMD_SUCCESS; 2926} 2927 2928ALIAS (no_rip_default_metric, 2929 no_rip_default_metric_val_cmd, 2930 "no default-metric <1-16>", 2931 NO_STR 2932 "Set a metric of redistribute routes\n" 2933 "Default metric\n") 2934 2935DEFUN (rip_timers, 2936 rip_timers_cmd, 2937 "timers basic <5-2147483647> <5-2147483647> <5-2147483647>", 2938 "Adjust routing timers\n" 2939 "Basic routing protocol update timers\n" 2940 "Routing table update timer value in second. Default is 30.\n" 2941 "Routing information timeout timer. Default is 180.\n" 2942 "Garbage collection timer. Default is 120.\n") 2943{ 2944 unsigned long update; 2945 unsigned long timeout; 2946 unsigned long garbage; 2947 char *endptr = NULL; 2948 unsigned long RIP_TIMER_MAX = 2147483647; 2949 unsigned long RIP_TIMER_MIN = 5; 2950 2951 update = strtoul (argv[0], &endptr, 10); 2952 if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0') 2953 { 2954 vty_out (vty, "update timer value error%s", VTY_NEWLINE); 2955 return CMD_WARNING; 2956 } 2957 2958 timeout = strtoul (argv[1], &endptr, 10); 2959 if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0') 2960 { 2961 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE); 2962 return CMD_WARNING; 2963 } 2964 2965 garbage = strtoul (argv[2], &endptr, 10); 2966 if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0') 2967 { 2968 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE); 2969 return CMD_WARNING; 2970 } 2971 2972 /* Set each timer value. */ 2973 rip->update_time = update; 2974 rip->timeout_time = timeout; 2975 rip->garbage_time = garbage; 2976 2977 /* Reset update timer thread. */ 2978 rip_event (RIP_UPDATE_EVENT, 0); 2979 2980 return CMD_SUCCESS; 2981} 2982 2983DEFUN (no_rip_timers, 2984 no_rip_timers_cmd, 2985 "no timers basic", 2986 NO_STR 2987 "Adjust routing timers\n" 2988 "Basic routing protocol update timers\n") 2989{ 2990 /* Set each timer value to the default. */ 2991 rip->update_time = RIP_UPDATE_TIMER_DEFAULT; 2992 rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; 2993 rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; 2994 2995 /* Reset update timer thread. */ 2996 rip_event (RIP_UPDATE_EVENT, 0); 2997 2998 return CMD_SUCCESS; 2999} 3000 3001struct route_table *rip_distance_table; 3002 3003struct rip_distance 3004{ 3005 /* Distance value for the IP source prefix. */ 3006 u_char distance; 3007 3008 /* Name of the access-list to be matched. */ 3009 char *access_list; 3010}; 3011 3012struct rip_distance * 3013rip_distance_new () 3014{ 3015 struct rip_distance *new; 3016 new = XMALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance)); 3017 memset (new, 0, sizeof (struct rip_distance)); 3018 return new; 3019} 3020 3021void 3022rip_distance_free (struct rip_distance *rdistance) 3023{ 3024 XFREE (MTYPE_RIP_DISTANCE, rdistance); 3025} 3026 3027int 3028rip_distance_set (struct vty *vty, char *distance_str, char *ip_str, 3029 char *access_list_str) 3030{ 3031 int ret; 3032 struct prefix_ipv4 p; 3033 u_char distance; 3034 struct route_node *rn; 3035 struct rip_distance *rdistance; 3036 3037 ret = str2prefix_ipv4 (ip_str, &p); 3038 if (ret == 0) 3039 { 3040 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); 3041 return CMD_WARNING; 3042 } 3043 3044 distance = atoi (distance_str); 3045 3046 /* Get RIP distance node. */ 3047 rn = route_node_get (rip_distance_table, (struct prefix *) &p); 3048 if (rn->info) 3049 { 3050 rdistance = rn->info; 3051 route_unlock_node (rn); 3052 } 3053 else 3054 { 3055 rdistance = rip_distance_new (); 3056 rn->info = rdistance; 3057 } 3058 3059 /* Set distance value. */ 3060 rdistance->distance = distance; 3061 3062 /* Reset access-list configuration. */ 3063 if (rdistance->access_list) 3064 { 3065 free (rdistance->access_list); 3066 rdistance->access_list = NULL; 3067 } 3068 if (access_list_str) 3069 rdistance->access_list = strdup (access_list_str); 3070 3071 return CMD_SUCCESS; 3072} 3073 3074int 3075rip_distance_unset (struct vty *vty, char *distance_str, char *ip_str, 3076 char *access_list_str) 3077{ 3078 int ret; 3079 struct prefix_ipv4 p; 3080 u_char distance; 3081 struct route_node *rn; 3082 struct rip_distance *rdistance; 3083 3084 ret = str2prefix_ipv4 (ip_str, &p); 3085 if (ret == 0) 3086 { 3087 vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); 3088 return CMD_WARNING; 3089 } 3090 3091 distance = atoi (distance_str); 3092 3093 rn = route_node_lookup (rip_distance_table, (struct prefix *)&p); 3094 if (! rn) 3095 { 3096 vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE); 3097 return CMD_WARNING; 3098 } 3099 3100 rdistance = rn->info; 3101 3102 if (rdistance->access_list) 3103 free (rdistance->access_list); 3104 rip_distance_free (rdistance); 3105 3106 rn->info = NULL; 3107 route_unlock_node (rn); 3108 route_unlock_node (rn); 3109 3110 return CMD_SUCCESS; 3111} 3112 3113void 3114rip_distance_reset () 3115{ 3116 struct route_node *rn; 3117 struct rip_distance *rdistance; 3118 3119 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) 3120 if ((rdistance = rn->info) != NULL) 3121 { 3122 if (rdistance->access_list) 3123 free (rdistance->access_list); 3124 rip_distance_free (rdistance); 3125 rn->info = NULL; 3126 route_unlock_node (rn); 3127 } 3128} 3129 3130/* Apply RIP information to distance method. */ 3131u_char 3132rip_distance_apply (struct rip_info *rinfo) 3133{ 3134 struct route_node *rn; 3135 struct prefix_ipv4 p; 3136 struct rip_distance *rdistance; 3137 struct access_list *alist; 3138 3139 if (! rip) 3140 return 0; 3141 3142 memset (&p, 0, sizeof (struct prefix_ipv4)); 3143 p.family = AF_INET; 3144 p.prefix = rinfo->from; 3145 p.prefixlen = IPV4_MAX_BITLEN; 3146 3147 /* Check source address. */ 3148 rn = route_node_match (rip_distance_table, (struct prefix *) &p); 3149 if (rn) 3150 { 3151 rdistance = rn->info; 3152 route_unlock_node (rn); 3153 3154 if (rdistance->access_list) 3155 { 3156 alist = access_list_lookup (AFI_IP, rdistance->access_list); 3157 if (alist == NULL) 3158 return 0; 3159 if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY) 3160 return 0; 3161 3162 return rdistance->distance; 3163 } 3164 else 3165 return rdistance->distance; 3166 } 3167 3168 if (rip->distance) 3169 return rip->distance; 3170 3171 return 0; 3172} 3173 3174#ifdef FOX_CMD_SUPPORT 3175void 3176rip_distance_show (struct vty *vty) 3177{ 3178 struct route_node *rn; 3179 struct rip_distance *rdistance; 3180 int header = 1; 3181 char buf[BUFSIZ]; 3182 3183 vty_out (vty, " Distance: (default is %d)%s", 3184 rip->distance ? rip->distance :ZEBRA_RIP_DISTANCE_DEFAULT, 3185 VTY_NEWLINE); 3186 3187 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) 3188 if ((rdistance = rn->info) != NULL) 3189 { 3190 if (header) 3191 { 3192 vty_out (vty, " Address Distance List%s", 3193 VTY_NEWLINE); 3194 header = 0; 3195 } 3196 sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); 3197 vty_out (vty, " %-20s %4d %s%s", 3198 buf, rdistance->distance, 3199 rdistance->access_list ? rdistance->access_list : "", 3200 VTY_NEWLINE); 3201 } 3202} 3203 3204DEFUN (rip_distance, 3205 rip_distance_cmd, 3206 "distance <1-255>", 3207 "Administrative distance\n" 3208 "Distance value\n") 3209{ 3210 rip->distance = atoi (argv[0]); 3211 return CMD_SUCCESS; 3212} 3213 3214DEFUN (no_rip_distance, 3215 no_rip_distance_cmd, 3216 "no distance <1-255>", 3217 NO_STR 3218 "Administrative distance\n" 3219 "Distance value\n") 3220{ 3221 rip->distance = 0; 3222 return CMD_SUCCESS; 3223} 3224 3225DEFUN (rip_distance_source, 3226 rip_distance_source_cmd, 3227 "distance <1-255> A.B.C.D/M", 3228 "Administrative distance\n" 3229 "Distance value\n" 3230 "IP source prefix\n") 3231{ 3232 rip_distance_set (vty, argv[0], argv[1], NULL); 3233 return CMD_SUCCESS; 3234} 3235 3236DEFUN (no_rip_distance_source, 3237 no_rip_distance_source_cmd, 3238 "no distance <1-255> A.B.C.D/M", 3239 NO_STR 3240 "Administrative distance\n" 3241 "Distance value\n" 3242 "IP source prefix\n") 3243{ 3244 rip_distance_unset (vty, argv[0], argv[1], NULL); 3245 return CMD_SUCCESS; 3246} 3247 3248DEFUN (rip_distance_source_access_list, 3249 rip_distance_source_access_list_cmd, 3250 "distance <1-255> A.B.C.D/M WORD", 3251 "Administrative distance\n" 3252 "Distance value\n" 3253 "IP source prefix\n" 3254 "Access list name\n") 3255{ 3256 rip_distance_set (vty, argv[0], argv[1], argv[2]); 3257 return CMD_SUCCESS; 3258} 3259 3260DEFUN (no_rip_distance_source_access_list, 3261 no_rip_distance_source_access_list_cmd, 3262 "no distance <1-255> A.B.C.D/M WORD", 3263 NO_STR 3264 "Administrative distance\n" 3265 "Distance value\n" 3266 "IP source prefix\n" 3267 "Access list name\n") 3268{ 3269 rip_distance_unset (vty, argv[0], argv[1], argv[2]); 3270 return CMD_SUCCESS; 3271} 3272 3273/* Print out routes update time. */ 3274void 3275rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo) 3276{ 3277 struct timeval timer_now; 3278 time_t clock; 3279 struct tm *tm; 3280#define TIME_BUF 25 3281 char timebuf [TIME_BUF]; 3282 struct thread *thread; 3283 3284 gettimeofday (&timer_now, NULL); 3285 3286 if ((thread = rinfo->t_timeout) != NULL) 3287 { 3288 clock = thread->u.sands.tv_sec - timer_now.tv_sec; 3289 tm = gmtime (&clock); 3290 strftime (timebuf, TIME_BUF, "%M:%S", tm); 3291 vty_out (vty, "%5s", timebuf); 3292 } 3293 else if ((thread = rinfo->t_garbage_collect) != NULL) 3294 { 3295 clock = thread->u.sands.tv_sec - timer_now.tv_sec; 3296 tm = gmtime (&clock); 3297 strftime (timebuf, TIME_BUF, "%M:%S", tm); 3298 vty_out (vty, "%5s", timebuf); 3299 } 3300} 3301 3302char * 3303rip_route_type_print (int sub_type) 3304{ 3305 switch (sub_type) 3306 { 3307 case RIP_ROUTE_RTE: 3308 return "n"; 3309 case RIP_ROUTE_STATIC: 3310 return "s"; 3311 case RIP_ROUTE_DEFAULT: 3312 return "d"; 3313 case RIP_ROUTE_REDISTRIBUTE: 3314 return "r"; 3315 case RIP_ROUTE_INTERFACE: 3316 return "i"; 3317 default: 3318 return "?"; 3319 } 3320} 3321 3322DEFUN (show_ip_rip, 3323 show_ip_rip_cmd, 3324 "show ip rip", 3325 SHOW_STR 3326 IP_STR 3327 "Show RIP routes\n") 3328{ 3329 struct route_node *np; 3330 struct rip_info *rinfo; 3331 3332 if (! rip) 3333 return CMD_SUCCESS; 3334 3335 vty_out (vty, "Codes: R - RIP, C - connected, O - OSPF, B - BGP%s" 3336 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s" 3337 " (i) - interface%s%s" 3338 " Network Next Hop Metric From Time%s", 3339 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); 3340 3341 for (np = route_top (rip->table); np; np = route_next (np)) 3342 if ((rinfo = np->info) != NULL) 3343 { 3344 int len; 3345 3346 len = vty_out (vty, "%s(%s) %s/%d", 3347 /* np->lock, For debugging. */ 3348 route_info[rinfo->type].str, 3349 rip_route_type_print (rinfo->sub_type), 3350 inet_ntoa (np->p.u.prefix4), np->p.prefixlen); 3351 3352 len = 24 - len; 3353 3354 if (len > 0) 3355 vty_out (vty, "%*s", len, " "); 3356 3357 if (rinfo->nexthop.s_addr) 3358 vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop), 3359 rinfo->metric); 3360 else 3361 vty_out (vty, "0.0.0.0 %2d ", rinfo->metric); 3362 3363 /* Route which exist in kernel routing table. */ 3364 if ((rinfo->type == ZEBRA_ROUTE_RIP) && 3365 (rinfo->sub_type == RIP_ROUTE_RTE)) 3366 { 3367 vty_out (vty, "%-15s ", inet_ntoa (rinfo->from)); 3368 rip_vty_out_uptime (vty, rinfo); 3369 } 3370 else if (rinfo->metric == RIP_METRIC_INFINITY) 3371 { 3372 vty_out (vty, "self "); 3373 rip_vty_out_uptime (vty, rinfo); 3374 } 3375 else 3376 vty_out (vty, "self"); 3377 3378 vty_out (vty, "%s", VTY_NEWLINE); 3379 } 3380 return CMD_SUCCESS; 3381} 3382 3383/* Return next event time. */ 3384int 3385rip_next_thread_timer (struct thread *thread) 3386{ 3387 struct timeval timer_now; 3388 3389 gettimeofday (&timer_now, NULL); 3390 3391 return thread->u.sands.tv_sec - timer_now.tv_sec; 3392} 3393 3394DEFUN (show_ip_protocols_rip, 3395 show_ip_protocols_rip_cmd, 3396 "show ip protocols", 3397 SHOW_STR 3398 IP_STR 3399 "IP routing protocol process parameters and statistics\n") 3400{ 3401 listnode node; 3402 struct interface *ifp; 3403 struct rip_interface *ri; 3404 extern struct message ri_version_msg[]; 3405 char *send_version; 3406 char *receive_version; 3407 3408 if (! rip) 3409 return CMD_SUCCESS; 3410 3411 vty_out (vty, "Routing Protocol is \"rip\"%s", VTY_NEWLINE); 3412 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,", 3413 rip->update_time); 3414 vty_out (vty, " next due in %d seconds%s", 3415 rip_next_thread_timer (rip->t_update), 3416 VTY_NEWLINE); 3417 vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time); 3418 vty_out (vty, " garbage collect after %ld seconds%s", rip->garbage_time, 3419 VTY_NEWLINE); 3420 3421 /* Filtering status show. */ 3422 config_show_distribute (vty); 3423 3424 /* Default metric information. */ 3425 vty_out (vty, " Default redistribution metric is %d%s", 3426 rip->default_metric, VTY_NEWLINE); 3427 3428 /* Redistribute information. */ 3429 vty_out (vty, " Redistributing:"); 3430 config_write_rip_redistribute (vty, 0); 3431 vty_out (vty, "%s", VTY_NEWLINE); 3432 3433 vty_out (vty, " Default version control: send version %d,", rip->version); 3434 vty_out (vty, " receive version %d %s", rip->version, 3435 VTY_NEWLINE); 3436 3437 vty_out (vty, " Interface Send Recv Key-chain%s", VTY_NEWLINE); 3438 3439 for (node = listhead (iflist); node; node = nextnode (node)) 3440 { 3441 ifp = getdata (node); 3442 ri = ifp->info; 3443 3444 if (ri->enable_network || ri->enable_interface) 3445 { 3446 if (ri->ri_send == RI_RIP_UNSPEC) 3447 send_version = lookup (ri_version_msg, rip->version); 3448 else 3449 send_version = lookup (ri_version_msg, ri->ri_send); 3450 3451 if (ri->ri_receive == RI_RIP_UNSPEC) 3452 receive_version = lookup (ri_version_msg, rip->version); 3453 else 3454 receive_version = lookup (ri_version_msg, ri->ri_receive); 3455 3456 vty_out (vty, " %-17s%-3s %-3s %s%s", ifp->name, 3457 send_version, 3458 receive_version, 3459 ri->key_chain ? ri->key_chain : "", 3460 VTY_NEWLINE); 3461 } 3462 } 3463 3464 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE); 3465 config_write_rip_network (vty, 0); 3466 3467 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE); 3468 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE); 3469 rip_peer_display (vty); 3470 3471 rip_distance_show (vty); 3472 3473 return CMD_SUCCESS; 3474} 3475#endif /* FOX_CMD_SUPPORT */ 3476 3477/* RIP configuration write function. */ 3478int 3479config_write_rip (struct vty *vty) 3480{ 3481#ifdef FOX_CMD_SUPPORT 3482 int write = 0; 3483 struct route_node *rn; 3484 struct rip_distance *rdistance; 3485 3486 if (rip) 3487 { 3488 /* Router RIP statement. */ 3489 vty_out (vty, "router rip%s", VTY_NEWLINE); 3490 write++; 3491 3492 /* RIP version statement. Default is RIP version 2. */ 3493 if (rip->version != RIPv2) 3494 vty_out (vty, " version %d%s", rip->version, 3495 VTY_NEWLINE); 3496 3497 /* RIP timer configuration. */ 3498 if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT 3499 || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT 3500 || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT) 3501 vty_out (vty, " timers basic %lu %lu %lu%s", 3502 rip->update_time, 3503 rip->timeout_time, 3504 rip->garbage_time, 3505 VTY_NEWLINE); 3506 3507 /* Default information configuration. */ 3508 if (rip->default_information) 3509 { 3510 if (rip->default_information_route_map) 3511 vty_out (vty, " default-information originate route-map %s%s", 3512 rip->default_information_route_map, VTY_NEWLINE); 3513 else 3514 vty_out (vty, " default-information originate%s", 3515 VTY_NEWLINE); 3516 } 3517 3518 /* Redistribute configuration. */ 3519 config_write_rip_redistribute (vty, 1); 3520 3521#ifdef FOX_LIST_SUPPORT 3522 /* RIP offset-list configuration. */ 3523 config_write_rip_offset_list (vty); 3524#endif /* FOX_LIST_SUPPORT */ 3525 3526 /* RIP enabled network and interface configuration. */ 3527 config_write_rip_network (vty, 1); 3528 3529 /* RIP default metric configuration */ 3530 if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT) 3531 vty_out (vty, " default-metric %d%s", 3532 rip->default_metric, VTY_NEWLINE); 3533 3534 /* Distribute configuration. */ 3535 write += config_write_distribute (vty); 3536 3537 /* Distance configuration. */ 3538 if (rip->distance) 3539 vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE); 3540 3541 /* RIP source IP prefix distance configuration. */ 3542 for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) 3543 if ((rdistance = rn->info) != NULL) 3544 vty_out (vty, " distance %d %s/%d %s%s", rdistance->distance, 3545 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, 3546 rdistance->access_list ? rdistance->access_list : "", 3547 VTY_NEWLINE); 3548 3549 /* RIP static route configuration. */ 3550 for (rn = route_top (rip->route); rn; rn = route_next (rn)) 3551 if (rn->info) 3552 vty_out (vty, " route %s/%d%s", 3553 inet_ntoa (rn->p.u.prefix4), 3554 rn->p.prefixlen, 3555 VTY_NEWLINE); 3556 3557 } 3558 return write; 3559#endif /* FOX_CMD_SUPPORT */ 3560} 3561 3562/* RIP node structure. */ 3563struct cmd_node rip_node = 3564{ 3565 RIP_NODE, 3566 "%s(config-router)# ", 3567 1 3568}; 3569 3570/* Distribute-list update functions. */ 3571void 3572rip_distribute_update (struct distribute *dist) 3573{ 3574 struct interface *ifp; 3575 struct rip_interface *ri; 3576 struct access_list *alist; 3577 struct prefix_list *plist; 3578 3579 if (! dist->ifname) 3580 return; 3581 3582 ifp = if_lookup_by_name (dist->ifname); 3583 if (ifp == NULL) 3584 return; 3585 3586 ri = ifp->info; 3587 3588 if (dist->list[DISTRIBUTE_IN]) 3589 { 3590 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]); 3591 if (alist) 3592 ri->list[RIP_FILTER_IN] = alist; 3593 else 3594 ri->list[RIP_FILTER_IN] = NULL; 3595 } 3596 else 3597 ri->list[RIP_FILTER_IN] = NULL; 3598 3599 if (dist->list[DISTRIBUTE_OUT]) 3600 { 3601 alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]); 3602 if (alist) 3603 ri->list[RIP_FILTER_OUT] = alist; 3604 else 3605 ri->list[RIP_FILTER_OUT] = NULL; 3606 } 3607 else 3608 ri->list[RIP_FILTER_OUT] = NULL; 3609 3610 if (dist->prefix[DISTRIBUTE_IN]) 3611 { 3612#ifdef FOX_LIST_SUPPORT 3613 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]); 3614 if (plist) 3615 ri->prefix[RIP_FILTER_IN] = plist; 3616 else 3617#endif /* FOX_LIST_SUPPORT */ 3618 ri->prefix[RIP_FILTER_IN] = NULL; 3619 } 3620 else 3621 ri->prefix[RIP_FILTER_IN] = NULL; 3622 3623 if (dist->prefix[DISTRIBUTE_OUT]) 3624 { 3625#ifdef FOX_LIST_SUPPORT 3626 plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]); 3627 if (plist) 3628 ri->prefix[RIP_FILTER_OUT] = plist; 3629 else 3630#endif /* FOX_LIST_SUPPORT */ 3631 ri->prefix[RIP_FILTER_OUT] = NULL; 3632 } 3633 else 3634 ri->prefix[RIP_FILTER_OUT] = NULL; 3635} 3636 3637void 3638rip_distribute_update_interface (struct interface *ifp) 3639{ 3640 struct distribute *dist; 3641 3642 dist = distribute_lookup (ifp->name); 3643 if (dist) 3644 rip_distribute_update (dist); 3645} 3646 3647/* Update all interface's distribute list. */ 3648void 3649rip_distribute_update_all () 3650{ 3651 struct interface *ifp; 3652 listnode node; 3653 3654 for (node = listhead (iflist); node; nextnode (node)) 3655 { 3656 ifp = getdata (node); 3657 rip_distribute_update_interface (ifp); 3658 } 3659} 3660 3661/* Delete all added rip route. */ 3662void 3663rip_clean () 3664{ 3665 int i; 3666 struct route_node *rp; 3667 struct rip_info *rinfo; 3668 3669 if (rip) 3670 { 3671 /* Clear RIP routes */ 3672 for (rp = route_top (rip->table); rp; rp = route_next (rp)) 3673 if ((rinfo = rp->info) != NULL) 3674 { 3675 if (rinfo->type == ZEBRA_ROUTE_RIP && 3676 rinfo->sub_type == RIP_ROUTE_RTE) 3677 rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, 3678 &rinfo->nexthop, rinfo->metric); 3679 3680 RIP_TIMER_OFF (rinfo->t_timeout); 3681 RIP_TIMER_OFF (rinfo->t_garbage_collect); 3682 3683 rp->info = NULL; 3684 route_unlock_node (rp); 3685 3686 rip_info_free (rinfo); 3687 } 3688 3689 /* Cancel RIP related timers. */ 3690 RIP_TIMER_OFF (rip->t_update); 3691 RIP_TIMER_OFF (rip->t_triggered_update); 3692 RIP_TIMER_OFF (rip->t_triggered_interval); 3693 3694 /* Cancel read thread. */ 3695 if (rip->t_read) 3696 { 3697 thread_cancel (rip->t_read); 3698 rip->t_read = NULL; 3699 } 3700 3701 /* Close RIP socket. */ 3702 if (rip->sock >= 0) 3703 { 3704 close (rip->sock); 3705 rip->sock = -1; 3706 } 3707 3708 /* Static RIP route configuration. */ 3709 for (rp = route_top (rip->route); rp; rp = route_next (rp)) 3710 if (rp->info) 3711 { 3712 rp->info = NULL; 3713 route_unlock_node (rp); 3714 } 3715 3716 /* RIP neighbor configuration. */ 3717 for (rp = route_top (rip->neighbor); rp; rp = route_next (rp)) 3718 if (rp->info) 3719 { 3720 rp->info = NULL; 3721 route_unlock_node (rp); 3722 } 3723 3724 /* Redistribute related clear. */ 3725 if (rip->default_information_route_map) 3726 free (rip->default_information_route_map); 3727 3728 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 3729 if (rip->route_map[i].name) 3730 free (rip->route_map[i].name); 3731 3732 XFREE (MTYPE_ROUTE_TABLE, rip->table); 3733 XFREE (MTYPE_ROUTE_TABLE, rip->route); 3734 XFREE (MTYPE_ROUTE_TABLE, rip->neighbor); 3735 3736 XFREE (MTYPE_RIP, rip); 3737 rip = NULL; 3738 } 3739 3740 rip_clean_network (); 3741 rip_passive_interface_clean (); 3742#ifdef FOX_LIST_SUPPORT 3743 rip_offset_clean (); 3744#endif /* FOX_LIST_SUPPORT */ 3745 rip_interface_clean (); 3746 rip_distance_reset (); 3747 rip_redistribute_clean (); 3748} 3749 3750/* Reset all values to the default settings. */ 3751void 3752rip_reset () 3753{ 3754 /* Reset global counters. */ 3755 rip_global_route_changes = 0; 3756 rip_global_queries = 0; 3757 3758 /* Call ripd related reset functions. */ 3759#ifdef FOX_RIP_DEBUG 3760 rip_debug_reset (); 3761#endif /* FOX_RIP_DEBUG */ 3762#ifdef FOX_LIST_SUPPORT 3763 rip_route_map_reset (); 3764 3765 /* Call library reset functions. */ 3766 vty_reset (); 3767#endif /* FOX_LIST_SUPPORT */ 3768 access_list_reset (); 3769#ifdef FOX_LIST_SUPPORT 3770 prefix_list_reset (); 3771#endif /* FOX_LIST_SUPPORT */ 3772 3773 distribute_list_reset (); 3774 3775 rip_interface_reset (); 3776 rip_distance_reset (); 3777 3778 rip_zclient_reset (); 3779} 3780 3781/* Allocate new rip structure and set default value. */ 3782void 3783rip_init () 3784{ 3785 /* Randomize for triggered update random(). */ 3786 srand (time (NULL)); 3787 3788 /* Install top nodes. */ 3789 install_node (&rip_node, config_write_rip); 3790 3791#ifdef FOX_CMD_SUPPORT 3792 /* Install rip commands. */ 3793 install_element (VIEW_NODE, &show_ip_rip_cmd); 3794 install_element (VIEW_NODE, &show_ip_protocols_rip_cmd); 3795 install_element (ENABLE_NODE, &show_ip_rip_cmd); 3796 install_element (ENABLE_NODE, &show_ip_protocols_rip_cmd); 3797#endif /* FOX_CMD_SUPPORT */ 3798 install_element (CONFIG_NODE, &router_rip_cmd); 3799 install_element (CONFIG_NODE, &no_router_rip_cmd); 3800 3801 install_default (RIP_NODE); 3802#ifdef FOX_CMD_SUPPORT 3803 install_element (RIP_NODE, &rip_version_cmd); 3804#endif /* FOX_CMD_SUPPORT */ 3805 3806#ifdef FOX_CMD_SUPPORT 3807 install_element (RIP_NODE, &no_rip_version_cmd); 3808 install_element (RIP_NODE, &no_rip_version_val_cmd); 3809 install_element (RIP_NODE, &rip_default_metric_cmd); 3810 install_element (RIP_NODE, &no_rip_default_metric_cmd); 3811 install_element (RIP_NODE, &no_rip_default_metric_val_cmd); 3812 install_element (RIP_NODE, &rip_timers_cmd); 3813 install_element (RIP_NODE, &no_rip_timers_cmd); 3814 install_element (RIP_NODE, &rip_route_cmd); 3815 install_element (RIP_NODE, &no_rip_route_cmd); 3816 install_element (RIP_NODE, &rip_distance_cmd); 3817 install_element (RIP_NODE, &no_rip_distance_cmd); 3818 install_element (RIP_NODE, &rip_distance_source_cmd); 3819 install_element (RIP_NODE, &no_rip_distance_source_cmd); 3820 install_element (RIP_NODE, &rip_distance_source_access_list_cmd); 3821 install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd); 3822#endif /* FOX_CMD_SUPPORT */ 3823 3824#ifdef FOX_RIP_DEBUG 3825 /* Debug related init. */ 3826 rip_debug_init (); 3827#endif /* FOX_RIP_DEBUG */ 3828 3829#ifdef FOX_LIST_SUPPORT 3830 /* Filter related init. */ 3831 rip_route_map_init (); 3832 rip_offset_init (); 3833#endif /* FOX_RIP_DEBUG */ 3834 3835 /* SNMP init. */ 3836#ifdef HAVE_SNMP 3837 rip_snmp_init (); 3838#endif /* HAVE_SNMP */ 3839 3840 /* Access list install. */ 3841 access_list_init (); 3842 access_list_add_hook (rip_distribute_update_all); 3843 access_list_delete_hook (rip_distribute_update_all); 3844 3845#ifdef FOX_LIST_SUPPORT 3846 /* Prefix list initialize.*/ 3847 prefix_list_init (); 3848 prefix_list_add_hook (rip_distribute_update_all); 3849 prefix_list_delete_hook (rip_distribute_update_all); 3850#endif /* FOX_LIST_SUPPORT */ 3851 3852 /* Distribute list install. */ 3853 distribute_list_init (RIP_NODE); 3854 distribute_list_add_hook (rip_distribute_update); 3855 distribute_list_delete_hook (rip_distribute_update); 3856 3857 /* Distance control. */ 3858 rip_distance_table = route_table_init (); 3859 3860 /*foxconn added start by EricHuang, 11/05/2007 */ 3861//#ifdef U12H072 3862/* Foxconn mark start by aspen Bai, 07/17/2008 */ 3863//#if (defined(U12H072) || defined(U12H083) || defined(U12H081)) 3864/* Foxconn mark end by aspen Bai, 07/17/2008 */ 3865 fox_get_rtinfo(); 3866/* Foxconn mark start by aspen Bai, 07/17/2008 */ 3867//#endif 3868/* Foxconn mark end by aspen Bai, 07/17/2008 */ 3869 /*foxconn added end by EricHuang, 11/05/2007 */ 3870} 3871