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