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