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