blob: 453637c31edb44ce5bf78641b186095bf2441564 [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};
paul718e3742002-12-13 20:15:29 +000075
hassoa94434b2003-05-25 17:10:12 +000076int
77ripng_route_rte (struct ripng_info *rinfo)
78{
79 return (rinfo->type == ZEBRA_ROUTE_RIPNG && rinfo->sub_type == RIPNG_ROUTE_RTE);
80}
81
paul718e3742002-12-13 20:15:29 +000082/* Allocate new ripng information. */
83struct ripng_info *
84ripng_info_new ()
85{
86 struct ripng_info *new;
87
88 new = XCALLOC (MTYPE_RIPNG_ROUTE, sizeof (struct ripng_info));
89 return new;
90}
91
92/* Free ripng information. */
93void
94ripng_info_free (struct ripng_info *rinfo)
95{
96 XFREE (MTYPE_RIPNG_ROUTE, rinfo);
97}
98
paul718e3742002-12-13 20:15:29 +000099/* Create ripng socket. */
100int
101ripng_make_socket (void)
102{
103 int ret;
104 int sock;
105 struct sockaddr_in6 ripaddr;
106
107 sock = socket (AF_INET6, SOCK_DGRAM, 0);
108 if (sock < 0)
109 {
110 zlog (NULL, LOG_ERR, "Can't make ripng socket");
111 return sock;
112 }
113
114 ret = setsockopt_so_recvbuf (sock, 8096);
115 if (ret < 0)
116 return ret;
117 ret = setsockopt_ipv6_pktinfo (sock, 1);
118 if (ret < 0)
119 return ret;
120 ret = setsockopt_ipv6_multicast_hops (sock, 255);
121 if (ret < 0)
122 return ret;
123 ret = setsockopt_ipv6_multicast_loop (sock, 0);
124 if (ret < 0)
125 return ret;
126 ret = setsockopt_ipv6_hoplimit (sock, 1);
127 if (ret < 0)
128 return ret;
129
130 memset (&ripaddr, 0, sizeof (ripaddr));
131 ripaddr.sin6_family = AF_INET6;
132#ifdef SIN6_LEN
133 ripaddr.sin6_len = sizeof (struct sockaddr_in6);
134#endif /* SIN6_LEN */
135 ripaddr.sin6_port = htons (RIPNG_PORT_DEFAULT);
136
paul27d47aa2003-11-17 09:04:53 +0000137 if (ripngd_privs.change (ZPRIVS_RAISE))
138 zlog_err ("ripng_make_socket: could not raise privs");
139
paul718e3742002-12-13 20:15:29 +0000140 ret = bind (sock, (struct sockaddr *) &ripaddr, sizeof (ripaddr));
141 if (ret < 0)
paul27d47aa2003-11-17 09:04:53 +0000142 {
ajs6099b3b2004-11-20 02:06:59 +0000143 zlog (NULL, LOG_ERR, "Can't bind ripng socket: %s.", safe_strerror (errno));
paul27d47aa2003-11-17 09:04:53 +0000144 if (ripngd_privs.change (ZPRIVS_LOWER))
145 zlog_err ("ripng_make_socket: could not lower privs");
146 return ret;
147 }
148 if (ripngd_privs.change (ZPRIVS_LOWER))
149 zlog_err ("ripng_make_socket: could not lower privs");
paul718e3742002-12-13 20:15:29 +0000150 return sock;
151}
152
153/* Send RIPng packet. */
154int
155ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to,
156 struct interface *ifp)
157{
158 int ret;
159 struct msghdr msg;
160 struct iovec iov;
161 struct cmsghdr *cmsgptr;
162 char adata [256];
163 struct in6_pktinfo *pkt;
164 struct sockaddr_in6 addr;
165
hassoa94434b2003-05-25 17:10:12 +0000166 if (IS_RIPNG_DEBUG_SEND) {
167 if (to)
hasso3a2ce6a2005-04-08 01:30:51 +0000168 zlog_debug ("send to %s", inet6_ntoa (to->sin6_addr));
ajsc6106812004-12-08 19:51:16 +0000169 zlog_debug (" send interface %s", ifp->name);
170 zlog_debug (" send packet size %d", bufsize);
hassoa94434b2003-05-25 17:10:12 +0000171 }
paul718e3742002-12-13 20:15:29 +0000172
173 memset (&addr, 0, sizeof (struct sockaddr_in6));
174 addr.sin6_family = AF_INET6;
175#ifdef SIN6_LEN
176 addr.sin6_len = sizeof (struct sockaddr_in6);
177#endif /* SIN6_LEN */
178 addr.sin6_flowinfo = htonl (RIPNG_PRIORITY_DEFAULT);
179
180 /* When destination is specified. */
181 if (to != NULL)
182 {
183 addr.sin6_addr = to->sin6_addr;
184 addr.sin6_port = to->sin6_port;
185 }
186 else
187 {
188 inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr);
189 addr.sin6_port = htons (RIPNG_PORT_DEFAULT);
190 }
191
192 msg.msg_name = (void *) &addr;
193 msg.msg_namelen = sizeof (struct sockaddr_in6);
194 msg.msg_iov = &iov;
195 msg.msg_iovlen = 1;
196 msg.msg_control = (void *) adata;
197 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
198
199 iov.iov_base = buf;
200 iov.iov_len = bufsize;
201
202 cmsgptr = (struct cmsghdr *)adata;
203 cmsgptr->cmsg_len = CMSG_LEN(sizeof (struct in6_pktinfo));
204 cmsgptr->cmsg_level = IPPROTO_IPV6;
205 cmsgptr->cmsg_type = IPV6_PKTINFO;
206
207 pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
208 memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
209 pkt->ipi6_ifindex = ifp->ifindex;
210
211 ret = sendmsg (ripng->sock, &msg, 0);
212
hassoa94434b2003-05-25 17:10:12 +0000213 if (ret < 0) {
214 if (to)
215 zlog_err ("RIPng send fail on %s to %s: %s", ifp->name,
hasso3a2ce6a2005-04-08 01:30:51 +0000216 inet6_ntoa (to->sin6_addr), safe_strerror (errno));
hassoa94434b2003-05-25 17:10:12 +0000217 else
ajs6099b3b2004-11-20 02:06:59 +0000218 zlog_err ("RIPng send fail on %s: %s", ifp->name, safe_strerror (errno));
hassoa94434b2003-05-25 17:10:12 +0000219 }
paul718e3742002-12-13 20:15:29 +0000220
221 return ret;
222}
223
224/* Receive UDP RIPng packet from socket. */
225int
226ripng_recv_packet (int sock, u_char *buf, int bufsize,
227 struct sockaddr_in6 *from, unsigned int *ifindex,
228 int *hoplimit)
229{
230 int ret;
231 struct msghdr msg;
232 struct iovec iov;
233 struct cmsghdr *cmsgptr;
234 struct in6_addr dst;
235
236 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
237 point I can't determine size of cmsghdr */
238 char adata[1024];
239
240 /* Fill in message and iovec. */
241 msg.msg_name = (void *) from;
242 msg.msg_namelen = sizeof (struct sockaddr_in6);
243 msg.msg_iov = &iov;
244 msg.msg_iovlen = 1;
245 msg.msg_control = (void *) adata;
246 msg.msg_controllen = sizeof adata;
247 iov.iov_base = buf;
248 iov.iov_len = bufsize;
249
250 /* If recvmsg fail return minus value. */
251 ret = recvmsg (sock, &msg, 0);
252 if (ret < 0)
253 return ret;
254
ajsb99760a2005-01-04 16:24:43 +0000255 for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
paul718e3742002-12-13 20:15:29 +0000256 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
257 {
258 /* I want interface index which this packet comes from. */
259 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
260 cmsgptr->cmsg_type == IPV6_PKTINFO)
261 {
262 struct in6_pktinfo *ptr;
263
264 ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
265 *ifindex = ptr->ipi6_ifindex;
266 dst = ptr->ipi6_addr;
267
268 if (*ifindex == 0)
269 zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
270 }
271
272 /* Incoming packet's multicast hop limit. */
273 if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
274 cmsgptr->cmsg_type == IPV6_HOPLIMIT)
275 *hoplimit = *((int *) CMSG_DATA (cmsgptr));
276 }
277
278 /* Hoplimit check shold be done when destination address is
279 multicast address. */
280 if (! IN6_IS_ADDR_MULTICAST (&dst))
281 *hoplimit = -1;
282
283 return ret;
284}
285
286/* Dump rip packet */
287void
hasso7a1d5832004-10-08 06:32:23 +0000288ripng_packet_dump (struct ripng_packet *packet, int size, const char *sndrcv)
paul718e3742002-12-13 20:15:29 +0000289{
290 caddr_t lim;
291 struct rte *rte;
hasso7a1d5832004-10-08 06:32:23 +0000292 const char *command_str;
paul718e3742002-12-13 20:15:29 +0000293
294 /* Set command string. */
295 if (packet->command == RIPNG_REQUEST)
296 command_str = "request";
297 else if (packet->command == RIPNG_RESPONSE)
298 command_str = "response";
299 else
300 command_str = "unknown";
301
302 /* Dump packet header. */
ajsc6106812004-12-08 19:51:16 +0000303 zlog_debug ("%s %s version %d packet size %d",
paul718e3742002-12-13 20:15:29 +0000304 sndrcv, command_str, packet->version, size);
305
306 /* Dump each routing table entry. */
307 rte = packet->rte;
308
309 for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
310 {
311 if (rte->metric == RIPNG_METRIC_NEXTHOP)
hasso3a2ce6a2005-04-08 01:30:51 +0000312 zlog_debug (" nexthop %s/%d", inet6_ntoa (rte->addr), rte->prefixlen);
paul718e3742002-12-13 20:15:29 +0000313 else
ajsc6106812004-12-08 19:51:16 +0000314 zlog_debug (" %s/%d metric %d tag %d",
hasso3a2ce6a2005-04-08 01:30:51 +0000315 inet6_ntoa (rte->addr), rte->prefixlen,
paul718e3742002-12-13 20:15:29 +0000316 rte->metric, ntohs (rte->tag));
317 }
318}
319
320/* RIPng next hop address RTE (Route Table Entry). */
321void
322ripng_nexthop_rte (struct rte *rte,
323 struct sockaddr_in6 *from,
324 struct ripng_nexthop *nexthop)
325{
326 char buf[INET6_BUFSIZ];
327
328 /* Logging before checking RTE. */
329 if (IS_RIPNG_DEBUG_RECV)
ajsc6106812004-12-08 19:51:16 +0000330 zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
hasso3a2ce6a2005-04-08 01:30:51 +0000331 inet6_ntoa (rte->addr), ntohs (rte->tag), rte->prefixlen);
paul718e3742002-12-13 20:15:29 +0000332
333 /* RFC2080 2.1.1 Next Hop:
334 The route tag and prefix length in the next hop RTE must be
335 set to zero on sending and ignored on receiption. */
336 if (ntohs (rte->tag) != 0)
337 zlog_warn ("RIPng nexthop RTE with non zero tag value %d from %s",
hasso3a2ce6a2005-04-08 01:30:51 +0000338 ntohs (rte->tag), inet6_ntoa (from->sin6_addr));
paul718e3742002-12-13 20:15:29 +0000339
340 if (rte->prefixlen != 0)
341 zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
hasso3a2ce6a2005-04-08 01:30:51 +0000342 rte->prefixlen, inet6_ntoa (from->sin6_addr));
paul718e3742002-12-13 20:15:29 +0000343
344 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
345 next hop RTE indicates that the next hop address should be the
346 originator of the RIPng advertisement. An address specified as a
347 next hop must be a link-local address. */
348 if (IN6_IS_ADDR_UNSPECIFIED (&rte->addr))
349 {
350 nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
351 memset (&nexthop->address, 0, sizeof (struct in6_addr));
352 return;
353 }
354
355 if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
356 {
357 nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
358 IPV6_ADDR_COPY (&nexthop->address, &rte->addr);
359 return;
360 }
361
362 /* The purpose of the next hop RTE is to eliminate packets being
363 routed through extra hops in the system. It is particularly useful
364 when RIPng is not being run on all of the routers on a network.
365 Note that next hop RTE is "advisory". That is, if the provided
366 information is ignored, a possibly sub-optimal, but absolutely
367 valid, route may be taken. If the received next hop address is not
368 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
369 zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s",
hasso3a2ce6a2005-04-08 01:30:51 +0000370 inet6_ntoa (rte->addr),
paul718e3742002-12-13 20:15:29 +0000371 inet_ntop (AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ));
372
373 nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
374 memset (&nexthop->address, 0, sizeof (struct in6_addr));
375
376 return;
377}
378
379/* If ifp has same link-local address then return 1. */
380int
381ripng_lladdr_check (struct interface *ifp, struct in6_addr *addr)
382{
paul1eb8ef22005-04-07 07:30:20 +0000383 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000384 struct connected *connected;
385 struct prefix *p;
386
paul1eb8ef22005-04-07 07:30:20 +0000387 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
388 {
389 p = connected->address;
paul718e3742002-12-13 20:15:29 +0000390
paul1eb8ef22005-04-07 07:30:20 +0000391 if (p->family == AF_INET6 &&
392 IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6) &&
393 IN6_ARE_ADDR_EQUAL (&p->u.prefix6, addr))
394 return 1;
395 }
paul718e3742002-12-13 20:15:29 +0000396 return 0;
397}
398
399/* RIPng route garbage collect timer. */
400int
401ripng_garbage_collect (struct thread *t)
402{
403 struct ripng_info *rinfo;
404 struct route_node *rp;
405
406 rinfo = THREAD_ARG (t);
407 rinfo->t_garbage_collect = NULL;
408
409 /* Off timeout timer. */
410 RIPNG_TIMER_OFF (rinfo->t_timeout);
411
412 /* Get route_node pointer. */
413 rp = rinfo->rp;
414
paul718e3742002-12-13 20:15:29 +0000415 /* Unlock route_node. */
416 rp->info = NULL;
417 route_unlock_node (rp);
418
419 /* Free RIPng routing information. */
420 ripng_info_free (rinfo);
421
422 return 0;
423}
424
425/* Timeout RIPng routes. */
426int
427ripng_timeout (struct thread *t)
428{
429 struct ripng_info *rinfo;
430 struct route_node *rp;
431
432 rinfo = THREAD_ARG (t);
433 rinfo->t_timeout = NULL;
434
435 /* Get route_node pointer. */
436 rp = rinfo->rp;
437
438 /* - The garbage-collection timer is set for 120 seconds. */
439 RIPNG_TIMER_ON (rinfo->t_garbage_collect, ripng_garbage_collect,
440 ripng->garbage_time);
441
hassoa94434b2003-05-25 17:10:12 +0000442 /* Delete this route from the kernel. */
443 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
444 rinfo->ifindex);
paul718e3742002-12-13 20:15:29 +0000445 /* - The metric for the route is set to 16 (infinity). This causes
446 the route to be removed from service. */
447 rinfo->metric = RIPNG_METRIC_INFINITY;
hassoa94434b2003-05-25 17:10:12 +0000448 rinfo->flags &= ~RIPNG_RTF_FIB;
449
450 /* Aggregate count decrement. */
451 ripng_aggregate_decrement (rp, rinfo);
paul718e3742002-12-13 20:15:29 +0000452
453 /* - The route change flag is to indicate that this entry has been
454 changed. */
455 rinfo->flags |= RIPNG_RTF_CHANGED;
456
457 /* - The output process is signalled to trigger a response. */
458 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
459
460 return 0;
461}
462
463void
464ripng_timeout_update (struct ripng_info *rinfo)
465{
466 if (rinfo->metric != RIPNG_METRIC_INFINITY)
467 {
468 RIPNG_TIMER_OFF (rinfo->t_timeout);
469 RIPNG_TIMER_ON (rinfo->t_timeout, ripng_timeout, ripng->timeout_time);
470 }
471}
472
hassoa94434b2003-05-25 17:10:12 +0000473int
474ripng_incoming_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
475{
476 struct distribute *dist;
477 struct access_list *alist;
478 struct prefix_list *plist;
479
480 /* Input distribute-list filtering. */
481 if (ri->list[RIPNG_FILTER_IN])
482 {
483 if (access_list_apply (ri->list[RIPNG_FILTER_IN],
484 (struct prefix *) p) == FILTER_DENY)
485 {
486 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000487 zlog_debug ("%s/%d filtered by distribute in",
hasso3a2ce6a2005-04-08 01:30:51 +0000488 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000489 return -1;
490 }
491 }
492 if (ri->prefix[RIPNG_FILTER_IN])
493 {
494 if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN],
495 (struct prefix *) p) == PREFIX_DENY)
496 {
497 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000498 zlog_debug ("%s/%d filtered by prefix-list in",
hasso3a2ce6a2005-04-08 01:30:51 +0000499 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000500 return -1;
501 }
502 }
503
504 /* All interface filter check. */
505 dist = distribute_lookup (NULL);
506 if (dist)
507 {
508 if (dist->list[DISTRIBUTE_IN])
509 {
510 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
511
512 if (alist)
513 {
514 if (access_list_apply (alist,
515 (struct prefix *) p) == FILTER_DENY)
516 {
517 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000518 zlog_debug ("%s/%d filtered by distribute in",
hasso3a2ce6a2005-04-08 01:30:51 +0000519 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000520 return -1;
521 }
522 }
523 }
524 if (dist->prefix[DISTRIBUTE_IN])
525 {
526 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
527
528 if (plist)
529 {
530 if (prefix_list_apply (plist,
531 (struct prefix *) p) == PREFIX_DENY)
532 {
533 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000534 zlog_debug ("%s/%d filtered by prefix-list in",
hasso3a2ce6a2005-04-08 01:30:51 +0000535 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000536 return -1;
537 }
538 }
539 }
540 }
541 return 0;
542}
543
544int
545ripng_outgoing_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
546{
547 struct distribute *dist;
548 struct access_list *alist;
549 struct prefix_list *plist;
550
551 if (ri->list[RIPNG_FILTER_OUT])
552 {
553 if (access_list_apply (ri->list[RIPNG_FILTER_OUT],
554 (struct prefix *) p) == FILTER_DENY)
555 {
556 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000557 zlog_debug ("%s/%d is filtered by distribute out",
hasso3a2ce6a2005-04-08 01:30:51 +0000558 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000559 return -1;
560 }
561 }
562 if (ri->prefix[RIPNG_FILTER_OUT])
563 {
564 if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT],
565 (struct prefix *) p) == PREFIX_DENY)
566 {
567 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000568 zlog_debug ("%s/%d is filtered by prefix-list out",
hasso3a2ce6a2005-04-08 01:30:51 +0000569 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000570 return -1;
571 }
572 }
573
574 /* All interface filter check. */
575 dist = distribute_lookup (NULL);
576 if (dist)
577 {
578 if (dist->list[DISTRIBUTE_OUT])
579 {
580 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
581
582 if (alist)
583 {
584 if (access_list_apply (alist,
585 (struct prefix *) p) == FILTER_DENY)
586 {
587 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000588 zlog_debug ("%s/%d filtered by distribute out",
hasso3a2ce6a2005-04-08 01:30:51 +0000589 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000590 return -1;
591 }
592 }
593 }
594 if (dist->prefix[DISTRIBUTE_OUT])
595 {
596 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
597
598 if (plist)
599 {
600 if (prefix_list_apply (plist,
601 (struct prefix *) p) == PREFIX_DENY)
602 {
603 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000604 zlog_debug ("%s/%d filtered by prefix-list out",
hasso3a2ce6a2005-04-08 01:30:51 +0000605 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000606 return -1;
607 }
608 }
609 }
610 }
611 return 0;
612}
613
paul718e3742002-12-13 20:15:29 +0000614/* Process RIPng route according to RFC2080. */
615void
616ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
617 struct ripng_nexthop *ripng_nexthop,
618 struct interface *ifp)
619{
hassoa94434b2003-05-25 17:10:12 +0000620 int ret;
paul718e3742002-12-13 20:15:29 +0000621 struct prefix_ipv6 p;
622 struct route_node *rp;
623 struct ripng_info *rinfo;
624 struct ripng_interface *ri;
625 struct in6_addr *nexthop;
626 u_char oldmetric;
627 int same = 0;
628
629 /* Make prefix structure. */
630 memset (&p, 0, sizeof (struct prefix_ipv6));
631 p.family = AF_INET6;
632 /* p.prefix = rte->addr; */
633 IPV6_ADDR_COPY (&p.prefix, &rte->addr);
634 p.prefixlen = rte->prefixlen;
635
636 /* Make sure mask is applied. */
637 /* XXX We have to check the prefix is valid or not before call
638 apply_mask_ipv6. */
639 apply_mask_ipv6 (&p);
640
641 /* Apply input filters. */
642 ri = ifp->info;
643
hassoa94434b2003-05-25 17:10:12 +0000644 ret = ripng_incoming_filter (&p, ri);
645 if (ret < 0)
646 return;
paul718e3742002-12-13 20:15:29 +0000647
648 /* Modify entry. */
649 if (ri->routemap[RIPNG_FILTER_IN])
650 {
651 int ret;
652 struct ripng_info newinfo;
653
paul41ce9262003-04-19 15:54:03 +0000654 memset (&newinfo, 0, sizeof (struct ripng_info));
hassoa94434b2003-05-25 17:10:12 +0000655 newinfo.type = ZEBRA_ROUTE_RIPNG;
656 newinfo.sub_type = RIPNG_ROUTE_RTE;
657 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
658 newinfo.nexthop = ripng_nexthop->address;
659 else
660 newinfo.nexthop = from->sin6_addr;
661 newinfo.from = from->sin6_addr;
662 newinfo.ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000663 newinfo.metric = rte->metric;
hassoa94434b2003-05-25 17:10:12 +0000664 newinfo.metric_out = rte->metric; /* XXX */
665 newinfo.tag = ntohs(rte->tag); /* XXX */
paul718e3742002-12-13 20:15:29 +0000666
667 ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN],
668 (struct prefix *)&p, RMAP_RIPNG, &newinfo);
669
670 if (ret == RMAP_DENYMATCH)
671 {
672 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000673 zlog_debug ("RIPng %s/%d is filtered by route-map in",
hasso3a2ce6a2005-04-08 01:30:51 +0000674 inet6_ntoa (p.prefix), p.prefixlen);
paul718e3742002-12-13 20:15:29 +0000675 return;
676 }
677
hassoa94434b2003-05-25 17:10:12 +0000678 /* Get back the object */
679 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) {
680 if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) {
681 /* the nexthop get changed by the routemap */
682 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop))
683 ripng_nexthop->address = newinfo.nexthop;
684 else
685 ripng_nexthop->address = in6addr_any;
686 }
687 } else {
688 if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) {
689 /* the nexthop get changed by the routemap */
690 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) {
691 ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
692 ripng_nexthop->address = newinfo.nexthop;
693 }
694 }
695 }
696 rte->tag = htons(newinfo.tag_out); /* XXX */
697 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
paul718e3742002-12-13 20:15:29 +0000698 }
699
hassoa94434b2003-05-25 17:10:12 +0000700 /* Once the entry has been validated, update the metric by
701 * adding the cost of the network on wich the message
702 * arrived. If the result is greater than infinity, use infinity
703 * (RFC2453 Sec. 3.9.2)
704 **/
705
706 /* Zebra ripngd can handle offset-list in. */
707 ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric);
708
709 /* If offset-list does not modify the metric use interface's
710 * one. */
711 if (! ret)
712 rte->metric += ifp->metric;
713
714 if (rte->metric > RIPNG_METRIC_INFINITY)
715 rte->metric = RIPNG_METRIC_INFINITY;
716
paul718e3742002-12-13 20:15:29 +0000717 /* Set nexthop pointer. */
718 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
719 nexthop = &ripng_nexthop->address;
720 else
721 nexthop = &from->sin6_addr;
722
723 /* Lookup RIPng routing table. */
724 rp = route_node_get (ripng->table, (struct prefix *) &p);
725
hassoa94434b2003-05-25 17:10:12 +0000726 /* Sanity check */
727 rinfo = rp->info;
728 if (rinfo)
729 {
730 /* Redistributed route check. */
731 if (rinfo->type != ZEBRA_ROUTE_RIPNG
732 && rinfo->metric != RIPNG_METRIC_INFINITY)
733 return;
734
735 /* Local static route. */
736 if (rinfo->type == ZEBRA_ROUTE_RIPNG
737 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
738 (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))
739 && rinfo->metric != RIPNG_METRIC_INFINITY)
740 return;
741 }
742
paul718e3742002-12-13 20:15:29 +0000743 if (rp->info == NULL)
744 {
745 /* Now, check to see whether there is already an explicit route
746 for the destination prefix. If there is no such route, add
747 this route to the routing table, unless the metric is
748 infinity (there is no point in adding a route which
749 unusable). */
750 if (rte->metric != RIPNG_METRIC_INFINITY)
751 {
752 rinfo = ripng_info_new ();
753
754 /* - Setting the destination prefix and length to those in
755 the RTE. */
756 rp->info = rinfo;
757 rinfo->rp = rp;
758
759 /* - Setting the metric to the newly calculated metric (as
760 described above). */
761 rinfo->metric = rte->metric;
762 rinfo->tag = ntohs (rte->tag);
763
764 /* - Set the next hop address to be the address of the router
765 from which the datagram came or the next hop address
766 specified by a next hop RTE. */
767 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
768 IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
769 rinfo->ifindex = ifp->ifindex;
770
771 /* - Initialize the timeout for the route. If the
772 garbage-collection timer is running for this route, stop it. */
773 ripng_timeout_update (rinfo);
774
775 /* - Set the route change flag. */
776 rinfo->flags |= RIPNG_RTF_CHANGED;
777
778 /* - Signal the output process to trigger an update (see section
779 2.5). */
780 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
781
782 /* Finally, route goes into the kernel. */
783 rinfo->type = ZEBRA_ROUTE_RIPNG;
784 rinfo->sub_type = RIPNG_ROUTE_RTE;
785
786 ripng_zebra_ipv6_add (&p, &rinfo->nexthop, rinfo->ifindex);
787 rinfo->flags |= RIPNG_RTF_FIB;
788
789 /* Aggregate check. */
790 ripng_aggregate_increment (rp, rinfo);
791 }
792 }
793 else
794 {
795 rinfo = rp->info;
796
797 /* If there is an existing route, compare the next hop address
798 to the address of the router from which the datagram came.
799 If this datagram is from the same router as the existing
800 route, reinitialize the timeout. */
801 same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr)
802 && (rinfo->ifindex == ifp->ifindex));
803
804 if (same)
805 ripng_timeout_update (rinfo);
806
807 /* Next, compare the metrics. If the datagram is from the same
808 router as the existing route, and the new metric is different
809 than the old one; or, if the new metric is lower than the old
810 one; do the following actions: */
811 if ((same && rinfo->metric != rte->metric) ||
812 rte->metric < rinfo->metric)
813 {
814 /* - Adopt the route from the datagram. That is, put the
815 new metric in, and adjust the next hop address (if
816 necessary). */
817 oldmetric = rinfo->metric;
818 rinfo->metric = rte->metric;
819 rinfo->tag = ntohs (rte->tag);
hassoa94434b2003-05-25 17:10:12 +0000820 IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
821 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000822
hassoa94434b2003-05-25 17:10:12 +0000823 /* Should a new route to this network be established
824 while the garbage-collection timer is running, the
825 new route will replace the one that is about to be
826 deleted. In this case the garbage-collection timer
827 must be cleared. */
828
829 if (oldmetric == RIPNG_METRIC_INFINITY &&
830 rinfo->metric < RIPNG_METRIC_INFINITY)
831 {
832 rinfo->type = ZEBRA_ROUTE_RIPNG;
833 rinfo->sub_type = RIPNG_ROUTE_RTE;
834
835 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
836
837 if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
838 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
839
840 ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);
841 rinfo->flags |= RIPNG_RTF_FIB;
842
843 /* The aggregation counter needs to be updated because
844 the prefixes, which are into the gc, have been
845 removed from the aggregator (see ripng_timout). */
846 ripng_aggregate_increment (rp, rinfo);
847 }
848
849 /* Update nexthop and/or metric value. */
850 if (oldmetric != RIPNG_METRIC_INFINITY)
paul718e3742002-12-13 20:15:29 +0000851 {
852 ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
853 ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);
854 rinfo->flags |= RIPNG_RTF_FIB;
855
hassoa94434b2003-05-25 17:10:12 +0000856 if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
857 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000858 }
paul718e3742002-12-13 20:15:29 +0000859
860 /* - Set the route change flag and signal the output process
861 to trigger an update. */
862 rinfo->flags |= RIPNG_RTF_CHANGED;
863 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
864
865 /* - If the new metric is infinity, start the deletion
866 process (described above); */
867 if (rinfo->metric == RIPNG_METRIC_INFINITY)
868 {
869 /* If the new metric is infinity, the deletion process
870 begins for the route, which is no longer used for
871 routing packets. Note that the deletion process is
872 started only when the metric is first set to
873 infinity. If the metric was already infinity, then a
874 new deletion process is not started. */
875 if (oldmetric != RIPNG_METRIC_INFINITY)
876 {
877 /* - The garbage-collection timer is set for 120 seconds. */
878 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
879 ripng_garbage_collect, ripng->garbage_time);
880 RIPNG_TIMER_OFF (rinfo->t_timeout);
881
882 /* - The metric for the route is set to 16
883 (infinity). This causes the route to be removed
884 from service.*/
hassoa94434b2003-05-25 17:10:12 +0000885 ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
886 rinfo->flags &= ~RIPNG_RTF_FIB;
887
888 /* Aggregate count decrement. */
889 ripng_aggregate_decrement (rp, rinfo);
890
paul718e3742002-12-13 20:15:29 +0000891 /* - The route change flag is to indicate that this
892 entry has been changed. */
893 /* - The output process is signalled to trigger a
894 response. */
895 ; /* Above processes are already done previously. */
896 }
897 }
898 else
899 {
900 /* otherwise, re-initialize the timeout. */
901 ripng_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000902 }
903 }
904 /* Unlock tempolary lock of the route. */
905 route_unlock_node (rp);
906 }
907}
908
909/* Add redistributed route to RIPng table. */
910void
911ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p,
hassoa94434b2003-05-25 17:10:12 +0000912 unsigned int ifindex, struct in6_addr *nexthop)
paul718e3742002-12-13 20:15:29 +0000913{
914 struct route_node *rp;
915 struct ripng_info *rinfo;
916
917 /* Redistribute route */
918 if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
919 return;
920 if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
921 return;
hassoa94434b2003-05-25 17:10:12 +0000922#if defined (MUSICA) || defined (LINUX)
923 /* XXX As long as the RIPng redistribution is applied to all the connected
924 * routes, one needs to filter the ::/96 prefixes.
925 * However it could be a wanted case, it will be removed soon.
926 */
927 if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
928 (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
929 return;
930#endif /* MUSICA or LINUX */
paul718e3742002-12-13 20:15:29 +0000931
932 rp = route_node_get (ripng->table, (struct prefix *) p);
933 rinfo = rp->info;
934
935 if (rinfo)
936 {
hassoa94434b2003-05-25 17:10:12 +0000937 if (rinfo->type == ZEBRA_ROUTE_CONNECT
938 && rinfo->sub_type == RIPNG_ROUTE_INTERFACE
939 && rinfo->metric != RIPNG_METRIC_INFINITY) {
940 route_unlock_node (rp);
941 return;
942 }
943
944 /* Manually configured RIPng route check.
945 * They have the precedence on all the other entries.
946 **/
947 if (rinfo->type == ZEBRA_ROUTE_RIPNG
948 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
949 (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) {
950 if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) &&
951 (sub_type != RIPNG_ROUTE_DEFAULT))) {
952 route_unlock_node (rp);
953 return;
954 }
955 }
956
paul718e3742002-12-13 20:15:29 +0000957 RIPNG_TIMER_OFF (rinfo->t_timeout);
958 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
hassoa94434b2003-05-25 17:10:12 +0000959
960 /* Tells the other daemons about the deletion of
961 * this RIPng route
962 **/
963 if (ripng_route_rte (rinfo))
964 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
965 rinfo->metric);
966
967 rp->info = NULL;
968 ripng_info_free (rinfo);
969
paul718e3742002-12-13 20:15:29 +0000970 route_unlock_node (rp);
hassoa94434b2003-05-25 17:10:12 +0000971
paul718e3742002-12-13 20:15:29 +0000972 }
hassoa94434b2003-05-25 17:10:12 +0000973
974 rinfo = ripng_info_new ();
paul718e3742002-12-13 20:15:29 +0000975
976 rinfo->type = type;
977 rinfo->sub_type = sub_type;
978 rinfo->ifindex = ifindex;
979 rinfo->metric = 1;
paul718e3742002-12-13 20:15:29 +0000980 rinfo->rp = rp;
hassoa94434b2003-05-25 17:10:12 +0000981
982 if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop))
983 rinfo->nexthop = *nexthop;
984
985 rinfo->flags |= RIPNG_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000986 rp->info = rinfo;
hassoa94434b2003-05-25 17:10:12 +0000987
988 /* Aggregate check. */
989 ripng_aggregate_increment (rp, rinfo);
990
991 rinfo->flags |= RIPNG_RTF_CHANGED;
992
993 if (IS_RIPNG_DEBUG_EVENT) {
994 if (!nexthop)
ajsc6106812004-12-08 19:51:16 +0000995 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso3a2ce6a2005-04-08 01:30:51 +0000996 inet6_ntoa(p->prefix), p->prefixlen,
hassoa94434b2003-05-25 17:10:12 +0000997 ifindex2ifname(ifindex));
998 else
ajsc6106812004-12-08 19:51:16 +0000999 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso3a2ce6a2005-04-08 01:30:51 +00001000 inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop),
hassoa94434b2003-05-25 17:10:12 +00001001 ifindex2ifname(ifindex));
1002 }
1003
1004 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +00001005}
1006
1007/* Delete redistributed route to RIPng table. */
1008void
1009ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p,
1010 unsigned int ifindex)
1011{
1012 struct route_node *rp;
1013 struct ripng_info *rinfo;
1014
1015 if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
1016 return;
1017 if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
1018 return;
hassoa94434b2003-05-25 17:10:12 +00001019#if defined (MUSICA) || defined (LINUX)
1020 /* XXX As long as the RIPng redistribution is applied to all the connected
1021 * routes, one needs to filter the ::/96 prefixes.
1022 * However it could be a wanted case, it will be removed soon.
1023 */
1024 if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
1025 (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
1026 return;
1027#endif /* MUSICA or LINUX */
paul718e3742002-12-13 20:15:29 +00001028
1029 rp = route_node_lookup (ripng->table, (struct prefix *) p);
1030
1031 if (rp)
1032 {
1033 rinfo = rp->info;
1034
1035 if (rinfo != NULL
1036 && rinfo->type == type
1037 && rinfo->sub_type == sub_type
1038 && rinfo->ifindex == ifindex)
1039 {
hassoa94434b2003-05-25 17:10:12 +00001040 /* Perform poisoned reverse. */
1041 rinfo->metric = RIPNG_METRIC_INFINITY;
1042 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
1043 ripng_garbage_collect, ripng->garbage_time);
paul718e3742002-12-13 20:15:29 +00001044 RIPNG_TIMER_OFF (rinfo->t_timeout);
hassoa94434b2003-05-25 17:10:12 +00001045
1046 /* Aggregate count decrement. */
1047 ripng_aggregate_decrement (rp, rinfo);
1048
1049 rinfo->flags |= RIPNG_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +00001050
hassoa94434b2003-05-25 17:10:12 +00001051 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001052 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso3a2ce6a2005-04-08 01:30:51 +00001053 inet6_ntoa(p->prefix), p->prefixlen,
hassoa94434b2003-05-25 17:10:12 +00001054 ifindex2ifname(ifindex));
paul718e3742002-12-13 20:15:29 +00001055
hassoa94434b2003-05-25 17:10:12 +00001056 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +00001057 }
paul718e3742002-12-13 20:15:29 +00001058 }
1059}
1060
1061/* Withdraw redistributed route. */
1062void
1063ripng_redistribute_withdraw (int type)
1064{
1065 struct route_node *rp;
1066 struct ripng_info *rinfo;
1067
hassoa94434b2003-05-25 17:10:12 +00001068 if (!ripng)
1069 return;
1070
paul718e3742002-12-13 20:15:29 +00001071 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1072 if ((rinfo = rp->info) != NULL)
1073 {
hassoa94434b2003-05-25 17:10:12 +00001074 if ((rinfo->type == type)
1075 && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE))
paul718e3742002-12-13 20:15:29 +00001076 {
hassoa94434b2003-05-25 17:10:12 +00001077 /* Perform poisoned reverse. */
1078 rinfo->metric = RIPNG_METRIC_INFINITY;
1079 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
1080 ripng_garbage_collect, ripng->garbage_time);
paul718e3742002-12-13 20:15:29 +00001081 RIPNG_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +00001082
hassoa94434b2003-05-25 17:10:12 +00001083 /* Aggregate count decrement. */
1084 ripng_aggregate_decrement (rp, rinfo);
paul718e3742002-12-13 20:15:29 +00001085
hassoa94434b2003-05-25 17:10:12 +00001086 rinfo->flags |= RIPNG_RTF_CHANGED;
1087
1088 if (IS_RIPNG_DEBUG_EVENT) {
1089 struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p;
1090
ajsc6106812004-12-08 19:51:16 +00001091 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
hasso3a2ce6a2005-04-08 01:30:51 +00001092 inet6_ntoa(p->prefix), p->prefixlen,
hassoa94434b2003-05-25 17:10:12 +00001093 ifindex2ifname(rinfo->ifindex));
1094 }
1095
1096 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +00001097 }
1098 }
1099}
1100
1101/* RIP routing information. */
1102void
1103ripng_response_process (struct ripng_packet *packet, int size,
1104 struct sockaddr_in6 *from, struct interface *ifp,
1105 int hoplimit)
1106{
1107 caddr_t lim;
1108 struct rte *rte;
1109 struct ripng_nexthop nexthop;
1110
1111 /* RFC2080 2.4.2 Response Messages:
1112 The Response must be ignored if it is not from the RIPng port. */
1113 if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT)
1114 {
1115 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
hasso3a2ce6a2005-04-08 01:30:51 +00001116 ntohs (from->sin6_port), inet6_ntoa (from->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001117 ripng_peer_bad_packet (from);
paul718e3742002-12-13 20:15:29 +00001118 return;
1119 }
1120
1121 /* The datagram's IPv6 source address should be checked to see
1122 whether the datagram is from a valid neighbor; the source of the
1123 datagram must be a link-local address. */
1124 if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr))
1125 {
1126 zlog_warn ("RIPng packet comes from non link local address %s",
hasso3a2ce6a2005-04-08 01:30:51 +00001127 inet6_ntoa (from->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001128 ripng_peer_bad_packet (from);
paul718e3742002-12-13 20:15:29 +00001129 return;
1130 }
1131
1132 /* It is also worth checking to see whether the response is from one
1133 of the router's own addresses. Interfaces on broadcast networks
1134 may receive copies of their own multicasts immediately. If a
1135 router processes its own output as new input, confusion is likely,
1136 and such datagrams must be ignored. */
1137 if (ripng_lladdr_check (ifp, &from->sin6_addr))
1138 {
1139 zlog_warn ("RIPng packet comes from my own link local address %s",
hasso3a2ce6a2005-04-08 01:30:51 +00001140 inet6_ntoa (from->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001141 ripng_peer_bad_packet (from);
paul718e3742002-12-13 20:15:29 +00001142 return;
1143 }
1144
1145 /* As an additional check, periodic advertisements must have their
1146 hop counts set to 255, and inbound, multicast packets sent from the
1147 RIPng port (i.e. periodic advertisement or triggered update
1148 packets) must be examined to ensure that the hop count is 255. */
1149 if (hoplimit >= 0 && hoplimit != 255)
1150 {
1151 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
hasso3a2ce6a2005-04-08 01:30:51 +00001152 hoplimit, inet6_ntoa (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
hassoa94434b2003-05-25 17:10:12 +00001157 /* Update RIPng peer. */
1158 ripng_peer_update (from, packet->version);
1159
paul718e3742002-12-13 20:15:29 +00001160 /* Reset nexthop. */
1161 memset (&nexthop, 0, sizeof (struct ripng_nexthop));
1162 nexthop.flag = RIPNG_NEXTHOP_UNSPEC;
1163
1164 /* Set RTE pointer. */
1165 rte = packet->rte;
1166
1167 for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++)
1168 {
1169 /* First of all, we have to check this RTE is next hop RTE or
1170 not. Next hop RTE is completely different with normal RTE so
1171 we need special treatment. */
1172 if (rte->metric == RIPNG_METRIC_NEXTHOP)
1173 {
1174 ripng_nexthop_rte (rte, from, &nexthop);
1175 continue;
1176 }
1177
1178 /* RTE information validation. */
1179
1180 /* - is the destination prefix valid (e.g., not a multicast
1181 prefix and not a link-local address) A link-local address
1182 should never be present in an RTE. */
1183 if (IN6_IS_ADDR_MULTICAST (&rte->addr))
1184 {
1185 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
hasso3a2ce6a2005-04-08 01:30:51 +00001186 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
hassoa94434b2003-05-25 17:10:12 +00001187 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001188 continue;
1189 }
1190 if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
1191 {
1192 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
hasso3a2ce6a2005-04-08 01:30:51 +00001193 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
hassoa94434b2003-05-25 17:10:12 +00001194 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001195 continue;
1196 }
1197 if (IN6_IS_ADDR_LOOPBACK (&rte->addr))
1198 {
1199 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
hasso3a2ce6a2005-04-08 01:30:51 +00001200 inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
hassoa94434b2003-05-25 17:10:12 +00001201 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001202 continue;
1203 }
1204
1205 /* - is the prefix length valid (i.e., between 0 and 128,
1206 inclusive) */
1207 if (rte->prefixlen > 128)
1208 {
1209 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
hasso3a2ce6a2005-04-08 01:30:51 +00001210 inet6_ntoa (rte->addr), rte->prefixlen,
1211 inet6_ntoa (from->sin6_addr), ifp->name);
hassoa94434b2003-05-25 17:10:12 +00001212 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001213 continue;
1214 }
1215
1216 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1217 if (! (rte->metric >= 1 && rte->metric <= 16))
1218 {
1219 zlog_warn ("Invalid metric %d from %s%%%s", rte->metric,
hasso3a2ce6a2005-04-08 01:30:51 +00001220 inet6_ntoa (from->sin6_addr), ifp->name);
hassoa94434b2003-05-25 17:10:12 +00001221 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001222 continue;
1223 }
1224
hassoa94434b2003-05-25 17:10:12 +00001225 /* Vincent: XXX Should we compute the direclty reachable nexthop
1226 * for our RIPng network ?
1227 **/
paul718e3742002-12-13 20:15:29 +00001228
1229 /* Routing table updates. */
1230 ripng_route_process (rte, from, &nexthop, ifp);
1231 }
1232}
1233
1234/* Response to request message. */
1235void
1236ripng_request_process (struct ripng_packet *packet,int size,
1237 struct sockaddr_in6 *from, struct interface *ifp)
1238{
1239 caddr_t lim;
1240 struct rte *rte;
1241 struct prefix_ipv6 p;
1242 struct route_node *rp;
1243 struct ripng_info *rinfo;
1244 struct ripng_interface *ri;
1245
hassoa94434b2003-05-25 17:10:12 +00001246 /* Does not reponse to the requests on the loopback interfaces */
1247 if (if_is_loopback (ifp))
1248 return;
1249
paul718e3742002-12-13 20:15:29 +00001250 /* Check RIPng process is enabled on this interface. */
1251 ri = ifp->info;
1252 if (! ri->running)
1253 return;
1254
1255 /* When passive interface is specified, suppress responses */
1256 if (ri->passive)
1257 return;
1258
hassoa94434b2003-05-25 17:10:12 +00001259 /* RIPng peer update. */
1260 ripng_peer_update (from, packet->version);
1261
paul718e3742002-12-13 20:15:29 +00001262 lim = ((caddr_t) packet) + size;
1263 rte = packet->rte;
1264
1265 /* The Request is processed entry by entry. If there are no
1266 entries, no response is given. */
1267 if (lim == (caddr_t) rte)
1268 return;
1269
1270 /* There is one special case. If there is exactly one entry in the
1271 request, and it has a destination prefix of zero, a prefix length
1272 of zero, and a metric of infinity (i.e., 16), then this is a
1273 request to send the entire routing table. In that case, a call
1274 is made to the output process to send the routing table to the
1275 requesting address/port. */
1276 if (lim == ((caddr_t) (rte + 1)) &&
1277 IN6_IS_ADDR_UNSPECIFIED (&rte->addr) &&
1278 rte->prefixlen == 0 &&
1279 rte->metric == RIPNG_METRIC_INFINITY)
1280 {
1281 /* All route with split horizon */
hassoa94434b2003-05-25 17:10:12 +00001282 ripng_output_process (ifp, from, ripng_all_route);
paul718e3742002-12-13 20:15:29 +00001283 }
1284 else
1285 {
1286 /* Except for this special case, processing is quite simple.
1287 Examine the list of RTEs in the Request one by one. For each
1288 entry, look up the destination in the router's routing
1289 database and, if there is a route, put that route's metric in
1290 the metric field of the RTE. If there is no explicit route
1291 to the specified destination, put infinity in the metric
1292 field. Once all the entries have been filled in, change the
1293 command from Request to Response and send the datagram back
1294 to the requestor. */
1295 memset (&p, 0, sizeof (struct prefix_ipv6));
1296 p.family = AF_INET6;
1297
1298 for (; ((caddr_t) rte) < lim; rte++)
1299 {
1300 p.prefix = rte->addr;
1301 p.prefixlen = rte->prefixlen;
1302 apply_mask_ipv6 (&p);
1303
1304 rp = route_node_lookup (ripng->table, (struct prefix *) &p);
1305
1306 if (rp)
1307 {
1308 rinfo = rp->info;
1309 rte->metric = rinfo->metric;
1310 route_unlock_node (rp);
1311 }
1312 else
1313 rte->metric = RIPNG_METRIC_INFINITY;
1314 }
1315 packet->command = RIPNG_RESPONSE;
1316
1317 ripng_send_packet ((caddr_t) packet, size, from, ifp);
1318 }
1319}
1320
1321/* First entry point of reading RIPng packet. */
1322int
1323ripng_read (struct thread *thread)
1324{
1325 int len;
1326 int sock;
1327 struct sockaddr_in6 from;
1328 struct ripng_packet *packet;
1329 unsigned int ifindex;
1330 struct interface *ifp;
1331 int hoplimit = -1;
1332
1333 /* Check ripng is active and alive. */
1334 assert (ripng != NULL);
1335 assert (ripng->sock >= 0);
1336
1337 /* Fetch thread data and set read pointer to empty for event
1338 managing. `sock' sould be same as ripng->sock. */
1339 sock = THREAD_FD (thread);
1340 ripng->t_read = NULL;
1341
1342 /* Add myself to the next event. */
1343 ripng_event (RIPNG_READ, sock);
1344
1345 /* Read RIPng packet. */
1346 len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf),
1347 STREAM_SIZE (ripng->ibuf), &from, &ifindex,
1348 &hoplimit);
1349 if (len < 0)
1350 {
ajs6099b3b2004-11-20 02:06:59 +00001351 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001352 return len;
1353 }
1354
1355 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1356 (4)) must be multiple size of one RTE size (20). */
1357 if (((len - 4) % 20) != 0)
1358 {
1359 zlog_warn ("RIPng invalid packet size %d from %s", len,
hasso3a2ce6a2005-04-08 01:30:51 +00001360 inet6_ntoa (from.sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001361 ripng_peer_bad_packet (&from);
paul718e3742002-12-13 20:15:29 +00001362 return 0;
1363 }
1364
1365 packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf);
1366 ifp = if_lookup_by_index (ifindex);
1367
1368 /* RIPng packet received. */
1369 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001370 zlog_debug ("RIPng packet received from %s port %d on %s",
hasso3a2ce6a2005-04-08 01:30:51 +00001371 inet6_ntoa (from.sin6_addr), ntohs (from.sin6_port),
paul718e3742002-12-13 20:15:29 +00001372 ifp ? ifp->name : "unknown");
1373
1374 /* Logging before packet checking. */
1375 if (IS_RIPNG_DEBUG_RECV)
1376 ripng_packet_dump (packet, len, "RECV");
1377
1378 /* Packet comes from unknown interface. */
1379 if (ifp == NULL)
1380 {
1381 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex);
1382 return 0;
1383 }
1384
1385 /* Packet version mismatch checking. */
1386 if (packet->version != ripng->version)
1387 {
1388 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1389 packet->version, ripng->version);
hassoa94434b2003-05-25 17:10:12 +00001390 ripng_peer_bad_packet (&from);
paul718e3742002-12-13 20:15:29 +00001391 return 0;
1392 }
1393
1394 /* Process RIPng packet. */
1395 switch (packet->command)
1396 {
1397 case RIPNG_REQUEST:
1398 ripng_request_process (packet, len, &from, ifp);
1399 break;
1400 case RIPNG_RESPONSE:
1401 ripng_response_process (packet, len, &from, ifp, hoplimit);
1402 break;
1403 default:
1404 zlog_warn ("Invalid RIPng command %d", packet->command);
hassoa94434b2003-05-25 17:10:12 +00001405 ripng_peer_bad_packet (&from);
paul718e3742002-12-13 20:15:29 +00001406 break;
1407 }
1408 return 0;
1409}
1410
1411/* Walk down the RIPng routing table then clear changed flag. */
1412void
1413ripng_clear_changed_flag ()
1414{
1415 struct route_node *rp;
1416 struct ripng_info *rinfo;
1417
1418 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1419 if ((rinfo = rp->info) != NULL)
1420 if (rinfo->flags & RIPNG_RTF_CHANGED)
1421 rinfo->flags &= ~RIPNG_RTF_CHANGED;
1422}
1423
1424/* Regular update of RIPng route. Send all routing formation to RIPng
1425 enabled interface. */
1426int
1427ripng_update (struct thread *t)
1428{
hasso52dc7ee2004-09-23 19:18:23 +00001429 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001430 struct interface *ifp;
1431 struct ripng_interface *ri;
1432
1433 /* Clear update timer thread. */
1434 ripng->t_update = NULL;
1435
1436 /* Logging update event. */
1437 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001438 zlog_debug ("RIPng update timer expired!");
paul718e3742002-12-13 20:15:29 +00001439
1440 /* Supply routes to each interface. */
paul1eb8ef22005-04-07 07:30:20 +00001441 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001442 {
paul718e3742002-12-13 20:15:29 +00001443 ri = ifp->info;
1444
1445 if (if_is_loopback (ifp) || ! if_is_up (ifp))
1446 continue;
1447
1448 if (! ri->running)
1449 continue;
1450
1451 /* When passive interface is specified, suppress announce to the
1452 interface. */
1453 if (ri->passive)
1454 continue;
1455
1456#if RIPNG_ADVANCED
1457 if (ri->ri_send == RIPNG_SEND_OFF)
1458 {
1459 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001460 zlog (NULL, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001461 "[Event] RIPng send to if %d is suppressed by config",
1462 ifp->ifindex);
1463 continue;
1464 }
1465#endif /* RIPNG_ADVANCED */
1466
hassoa94434b2003-05-25 17:10:12 +00001467 ripng_output_process (ifp, NULL, ripng_all_route);
paul718e3742002-12-13 20:15:29 +00001468 }
1469
1470 /* Triggered updates may be suppressed if a regular update is due by
1471 the time the triggered update would be sent. */
1472 if (ripng->t_triggered_interval)
1473 {
1474 thread_cancel (ripng->t_triggered_interval);
1475 ripng->t_triggered_interval = NULL;
1476 }
1477 ripng->trigger = 0;
1478
1479 /* Reset flush event. */
1480 ripng_event (RIPNG_UPDATE_EVENT, 0);
1481
1482 return 0;
1483}
1484
1485/* Triggered update interval timer. */
1486int
1487ripng_triggered_interval (struct thread *t)
1488{
1489 ripng->t_triggered_interval = NULL;
1490
1491 if (ripng->trigger)
1492 {
1493 ripng->trigger = 0;
1494 ripng_triggered_update (t);
1495 }
1496 return 0;
1497}
1498
1499/* Execute triggered update. */
1500int
1501ripng_triggered_update (struct thread *t)
1502{
hasso52dc7ee2004-09-23 19:18:23 +00001503 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001504 struct interface *ifp;
1505 struct ripng_interface *ri;
1506 int interval;
1507
1508 ripng->t_triggered_update = NULL;
1509
1510 /* Cancel interval timer. */
1511 if (ripng->t_triggered_interval)
1512 {
1513 thread_cancel (ripng->t_triggered_interval);
1514 ripng->t_triggered_interval = NULL;
1515 }
1516 ripng->trigger = 0;
1517
1518 /* Logging triggered update. */
1519 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001520 zlog_debug ("RIPng triggered update!");
paul718e3742002-12-13 20:15:29 +00001521
1522 /* Split Horizon processing is done when generating triggered
1523 updates as well as normal updates (see section 2.6). */
paul1eb8ef22005-04-07 07:30:20 +00001524 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
paul718e3742002-12-13 20:15:29 +00001525 {
paul718e3742002-12-13 20:15:29 +00001526 ri = ifp->info;
1527
1528 if (if_is_loopback (ifp) || ! if_is_up (ifp))
1529 continue;
1530
1531 if (! ri->running)
1532 continue;
1533
1534 /* When passive interface is specified, suppress announce to the
1535 interface. */
1536 if (ri->passive)
1537 continue;
1538
hassoa94434b2003-05-25 17:10:12 +00001539 ripng_output_process (ifp, NULL, ripng_changed_route);
paul718e3742002-12-13 20:15:29 +00001540 }
1541
1542 /* Once all of the triggered updates have been generated, the route
1543 change flags should be cleared. */
1544 ripng_clear_changed_flag ();
1545
1546 /* After a triggered update is sent, a timer should be set for a
1547 random interval between 1 and 5 seconds. If other changes that
1548 would trigger updates occur before the timer expires, a single
1549 update is triggered when the timer expires. */
1550 interval = (random () % 5) + 1;
1551
1552 ripng->t_triggered_interval =
1553 thread_add_timer (master, ripng_triggered_interval, NULL, interval);
1554
1555 return 0;
1556}
1557
1558/* Write routing table entry to the stream and return next index of
1559 the routing table entry in the stream. */
1560int
1561ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
hassoa94434b2003-05-25 17:10:12 +00001562 struct in6_addr *nexthop, u_int16_t tag, u_char metric)
paul718e3742002-12-13 20:15:29 +00001563{
1564 /* RIPng packet header. */
1565 if (num == 0)
1566 {
1567 stream_putc (s, RIPNG_RESPONSE);
1568 stream_putc (s, RIPNG_V1);
1569 stream_putw (s, 0);
1570 }
1571
1572 /* Write routing table entry. */
hassoa94434b2003-05-25 17:10:12 +00001573 if (!nexthop)
hassoc9e52be2004-09-26 16:09:34 +00001574 stream_write (s, (u_char *) &p->prefix, sizeof (struct in6_addr));
hassoa94434b2003-05-25 17:10:12 +00001575 else
hassoc9e52be2004-09-26 16:09:34 +00001576 stream_write (s, (u_char *) nexthop, sizeof (struct in6_addr));
paul718e3742002-12-13 20:15:29 +00001577 stream_putw (s, tag);
hassoa94434b2003-05-25 17:10:12 +00001578 if (p)
1579 stream_putc (s, p->prefixlen);
1580 else
1581 stream_putc (s, 0);
paul718e3742002-12-13 20:15:29 +00001582 stream_putc (s, metric);
1583
1584 return ++num;
1585}
1586
1587/* Send RESPONSE message to specified destination. */
1588void
1589ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,
hassoa94434b2003-05-25 17:10:12 +00001590 int route_type)
paul718e3742002-12-13 20:15:29 +00001591{
1592 int ret;
paul718e3742002-12-13 20:15:29 +00001593 struct route_node *rp;
1594 struct ripng_info *rinfo;
1595 struct ripng_interface *ri;
1596 struct ripng_aggregate *aggregate;
1597 struct prefix_ipv6 *p;
hassoa94434b2003-05-25 17:10:12 +00001598 struct list * ripng_rte_list;
paul718e3742002-12-13 20:15:29 +00001599
hassoa94434b2003-05-25 17:10:12 +00001600 if (IS_RIPNG_DEBUG_EVENT) {
1601 if (to)
ajsc6106812004-12-08 19:51:16 +00001602 zlog_debug ("RIPng update routes to neighbor %s",
hasso3a2ce6a2005-04-08 01:30:51 +00001603 inet6_ntoa(to->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001604 else
ajsc6106812004-12-08 19:51:16 +00001605 zlog_debug ("RIPng update routes on interface %s", ifp->name);
hassoa94434b2003-05-25 17:10:12 +00001606 }
paul718e3742002-12-13 20:15:29 +00001607
paul718e3742002-12-13 20:15:29 +00001608 /* Get RIPng interface. */
1609 ri = ifp->info;
hassoa94434b2003-05-25 17:10:12 +00001610
1611 ripng_rte_list = ripng_rte_new();
1612
paul718e3742002-12-13 20:15:29 +00001613 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1614 {
1615 if ((rinfo = rp->info) != NULL && rinfo->suppress == 0)
1616 {
hassoa94434b2003-05-25 17:10:12 +00001617 /* If no route-map are applied, the RTE will be these following
1618 * informations.
1619 */
paul718e3742002-12-13 20:15:29 +00001620 p = (struct prefix_ipv6 *) &rp->p;
hassoa94434b2003-05-25 17:10:12 +00001621 rinfo->metric_out = rinfo->metric;
1622 rinfo->tag_out = rinfo->tag;
1623 memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out));
1624 /* In order to avoid some local loops,
1625 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1626 * otherwise set it to 0. The nexthop should not be propagated
1627 * beyond the local broadcast/multicast area in order
1628 * to avoid an IGP multi-level recursive look-up.
1629 */
1630 if (rinfo->ifindex == ifp->ifindex)
1631 rinfo->nexthop_out = rinfo->nexthop;
1632
1633 /* Apply output filters. */
1634 ret = ripng_outgoing_filter (p, ri);
1635 if (ret < 0)
1636 continue;
paul718e3742002-12-13 20:15:29 +00001637
1638 /* Changed route only output. */
1639 if (route_type == ripng_changed_route &&
1640 (! (rinfo->flags & RIPNG_RTF_CHANGED)))
1641 continue;
1642
1643 /* Split horizon. */
hassoa94434b2003-05-25 17:10:12 +00001644 if (ri->split_horizon == RIPNG_SPLIT_HORIZON)
1645 {
1646 /* We perform split horizon for RIPng routes. */
1647 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
1648 rinfo->ifindex == ifp->ifindex)
1649 continue;
1650 }
paul718e3742002-12-13 20:15:29 +00001651
1652 /* Preparation for route-map. */
hassoa94434b2003-05-25 17:10:12 +00001653 rinfo->metric_set = 0;
1654 /* nexthop_out,
1655 * metric_out
1656 * and tag_out are already initialized.
1657 */
paul718e3742002-12-13 20:15:29 +00001658
hassoa94434b2003-05-25 17:10:12 +00001659 /* Interface route-map */
paul718e3742002-12-13 20:15:29 +00001660 if (ri->routemap[RIPNG_FILTER_OUT])
1661 {
1662 int ret;
paul718e3742002-12-13 20:15:29 +00001663
1664 ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
1665 (struct prefix *) p, RMAP_RIPNG,
hassoa94434b2003-05-25 17:10:12 +00001666 rinfo);
paul718e3742002-12-13 20:15:29 +00001667
1668 if (ret == RMAP_DENYMATCH)
1669 {
1670 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +00001671 zlog_debug ("RIPng %s/%d is filtered by route-map out",
hasso3a2ce6a2005-04-08 01:30:51 +00001672 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +00001673 continue;
paul718e3742002-12-13 20:15:29 +00001674 }
1675
paul718e3742002-12-13 20:15:29 +00001676 }
1677
hassoa94434b2003-05-25 17:10:12 +00001678 /* Redistribute route-map. */
1679 if (ripng->route_map[rinfo->type].name)
paul718e3742002-12-13 20:15:29 +00001680 {
hassoa94434b2003-05-25 17:10:12 +00001681 int ret;
1682
1683 ret = route_map_apply (ripng->route_map[rinfo->type].map,
1684 (struct prefix *) p, RMAP_RIPNG,
hassobb3a0232003-06-02 10:38:15 +00001685 rinfo);
hassoa94434b2003-05-25 17:10:12 +00001686
1687 if (ret == RMAP_DENYMATCH)
paul718e3742002-12-13 20:15:29 +00001688 {
hassoa94434b2003-05-25 17:10:12 +00001689 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +00001690 zlog_debug ("RIPng %s/%d is filtered by route-map",
hasso3a2ce6a2005-04-08 01:30:51 +00001691 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +00001692 continue;
paul718e3742002-12-13 20:15:29 +00001693 }
hassoa94434b2003-05-25 17:10:12 +00001694 }
paul718e3742002-12-13 20:15:29 +00001695
hassoa94434b2003-05-25 17:10:12 +00001696 /* When the route-map does not set metric. */
1697 if (! rinfo->metric_set)
1698 {
1699 /* If the redistribute metric is set. */
1700 if (ripng->route_map[rinfo->type].metric_config
1701 && rinfo->metric != RIPNG_METRIC_INFINITY)
paul718e3742002-12-13 20:15:29 +00001702 {
hassoa94434b2003-05-25 17:10:12 +00001703 rinfo->metric_out = ripng->route_map[rinfo->type].metric;
1704 }
1705 else
1706 {
1707 /* If the route is not connected or localy generated
1708 one, use default-metric value */
1709 if (rinfo->type != ZEBRA_ROUTE_RIPNG
1710 && rinfo->type != ZEBRA_ROUTE_CONNECT
paul718e3742002-12-13 20:15:29 +00001711 && rinfo->metric != RIPNG_METRIC_INFINITY)
hassoa94434b2003-05-25 17:10:12 +00001712 rinfo->metric_out = ripng->default_metric;
paul718e3742002-12-13 20:15:29 +00001713 }
1714 }
1715
hassoa94434b2003-05-25 17:10:12 +00001716 /* Apply offset-list */
1717 if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
1718 ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00001719
hassoa94434b2003-05-25 17:10:12 +00001720 if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
1721 rinfo->metric_out = RIPNG_METRIC_INFINITY;
1722
1723 /* Perform split-horizon with poisoned reverse
1724 * for RIPng routes.
1725 **/
1726 if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) {
1727 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
1728 rinfo->ifindex == ifp->ifindex)
1729 rinfo->metric_out = RIPNG_METRIC_INFINITY;
1730 }
1731
1732 /* Add RTE to the list */
1733 ripng_rte_add(ripng_rte_list, p, rinfo, NULL);
paul718e3742002-12-13 20:15:29 +00001734 }
hassoa94434b2003-05-25 17:10:12 +00001735
1736 /* Process the aggregated RTE entry */
paul718e3742002-12-13 20:15:29 +00001737 if ((aggregate = rp->aggregate) != NULL &&
1738 aggregate->count > 0 &&
1739 aggregate->suppress == 0)
1740 {
hassoa94434b2003-05-25 17:10:12 +00001741 /* If no route-map are applied, the RTE will be these following
1742 * informations.
1743 */
paul718e3742002-12-13 20:15:29 +00001744 p = (struct prefix_ipv6 *) &rp->p;
hassoa94434b2003-05-25 17:10:12 +00001745 aggregate->metric_set = 0;
1746 aggregate->metric_out = aggregate->metric;
1747 aggregate->tag_out = aggregate->tag;
1748 memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out));
paul718e3742002-12-13 20:15:29 +00001749
1750 /* Apply output filters.*/
hassoa94434b2003-05-25 17:10:12 +00001751 ret = ripng_outgoing_filter (p, ri);
1752 if (ret < 0)
1753 continue;
paul718e3742002-12-13 20:15:29 +00001754
hassoa94434b2003-05-25 17:10:12 +00001755 /* Interface route-map */
paul718e3742002-12-13 20:15:29 +00001756 if (ri->routemap[RIPNG_FILTER_OUT])
1757 {
1758 int ret;
1759 struct ripng_info newinfo;
1760
hassoa94434b2003-05-25 17:10:12 +00001761 /* let's cast the aggregate structure to ripng_info */
paul718e3742002-12-13 20:15:29 +00001762 memset (&newinfo, 0, sizeof (struct ripng_info));
hassoa94434b2003-05-25 17:10:12 +00001763 /* the nexthop is :: */
1764 newinfo.metric = aggregate->metric;
1765 newinfo.metric_out = aggregate->metric_out;
1766 newinfo.tag = aggregate->tag;
1767 newinfo.tag_out = aggregate->tag_out;
paul718e3742002-12-13 20:15:29 +00001768
1769 ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
1770 (struct prefix *) p, RMAP_RIPNG,
1771 &newinfo);
1772
1773 if (ret == RMAP_DENYMATCH)
1774 {
1775 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +00001776 zlog_debug ("RIPng %s/%d is filtered by route-map out",
hasso3a2ce6a2005-04-08 01:30:51 +00001777 inet6_ntoa (p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +00001778 continue;
paul718e3742002-12-13 20:15:29 +00001779 }
1780
hassoa94434b2003-05-25 17:10:12 +00001781 aggregate->metric_out = newinfo.metric_out;
1782 aggregate->tag_out = newinfo.tag_out;
1783 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out))
1784 aggregate->nexthop_out = newinfo.nexthop_out;
paul718e3742002-12-13 20:15:29 +00001785 }
1786
hassoa94434b2003-05-25 17:10:12 +00001787 /* There is no redistribute routemap for the aggregated RTE */
1788
paul718e3742002-12-13 20:15:29 +00001789 /* Changed route only output. */
hassoa94434b2003-05-25 17:10:12 +00001790 /* XXX, vincent, in order to increase time convergence,
1791 * it should be announced if a child has changed.
1792 */
paul718e3742002-12-13 20:15:29 +00001793 if (route_type == ripng_changed_route)
1794 continue;
1795
hassoa94434b2003-05-25 17:10:12 +00001796 /* Apply offset-list */
1797 if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
1798 ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out);
paul718e3742002-12-13 20:15:29 +00001799
hassoa94434b2003-05-25 17:10:12 +00001800 if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
1801 aggregate->metric_out = RIPNG_METRIC_INFINITY;
1802
1803 /* Add RTE to the list */
1804 ripng_rte_add(ripng_rte_list, p, NULL, aggregate);
paul718e3742002-12-13 20:15:29 +00001805 }
1806
1807 }
paul718e3742002-12-13 20:15:29 +00001808
hassoa94434b2003-05-25 17:10:12 +00001809 /* Flush the list */
1810 ripng_rte_send(ripng_rte_list, ifp, to);
1811 ripng_rte_free(ripng_rte_list);
paul718e3742002-12-13 20:15:29 +00001812}
1813
1814/* Create new RIPng instance and set it to global variable. */
1815int
1816ripng_create ()
1817{
1818 /* ripng should be NULL. */
1819 assert (ripng == NULL);
1820
1821 /* Allocaste RIPng instance. */
hassoa94434b2003-05-25 17:10:12 +00001822 ripng = XMALLOC (MTYPE_RIPNG, sizeof (struct ripng));
paul718e3742002-12-13 20:15:29 +00001823 memset (ripng, 0, sizeof (struct ripng));
1824
1825 /* Default version and timer values. */
1826 ripng->version = RIPNG_V1;
1827 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
1828 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
1829 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
1830 ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
1831
1832 /* Make buffer. */
1833 ripng->ibuf = stream_new (RIPNG_MAX_PACKET_SIZE * 5);
1834 ripng->obuf = stream_new (RIPNG_MAX_PACKET_SIZE);
1835
1836 /* Initialize RIPng routig table. */
1837 ripng->table = route_table_init ();
1838 ripng->route = route_table_init ();
1839 ripng->aggregate = route_table_init ();
1840
1841 /* Make socket. */
1842 ripng->sock = ripng_make_socket ();
1843 if (ripng->sock < 0)
1844 return ripng->sock;
1845
1846 /* Threads. */
1847 ripng_event (RIPNG_READ, ripng->sock);
1848 ripng_event (RIPNG_UPDATE_EVENT, 1);
1849
1850 return 0;
1851}
1852
hassoa94434b2003-05-25 17:10:12 +00001853/* Send RIPng request to the interface. */
paul718e3742002-12-13 20:15:29 +00001854int
1855ripng_request (struct interface *ifp)
1856{
1857 struct rte *rte;
1858 struct ripng_packet ripng_packet;
1859
hassoa94434b2003-05-25 17:10:12 +00001860 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1861 if (if_is_loopback(ifp))
1862 return 0;
1863
1864 /* If interface is down, don't send RIP packet. */
1865 if (! if_is_up (ifp))
1866 return 0;
1867
paul718e3742002-12-13 20:15:29 +00001868 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001869 zlog_debug ("RIPng send request to %s", ifp->name);
paul718e3742002-12-13 20:15:29 +00001870
1871 memset (&ripng_packet, 0, sizeof (ripng_packet));
1872 ripng_packet.command = RIPNG_REQUEST;
1873 ripng_packet.version = RIPNG_V1;
1874 rte = ripng_packet.rte;
1875 rte->metric = RIPNG_METRIC_INFINITY;
1876
1877 return ripng_send_packet ((caddr_t) &ripng_packet, sizeof (ripng_packet),
1878 NULL, ifp);
1879}
1880
paul718e3742002-12-13 20:15:29 +00001881
1882int
1883ripng_update_jitter (int time)
1884{
1885 return ((rand () % (time + 1)) - (time / 2));
1886}
1887
1888void
1889ripng_event (enum ripng_event event, int sock)
1890{
paul718e3742002-12-13 20:15:29 +00001891 int jitter = 0;
1892
1893 switch (event)
1894 {
1895 case RIPNG_READ:
1896 if (!ripng->t_read)
1897 ripng->t_read = thread_add_read (master, ripng_read, NULL, sock);
1898 break;
1899 case RIPNG_UPDATE_EVENT:
1900 if (ripng->t_update)
1901 {
1902 thread_cancel (ripng->t_update);
1903 ripng->t_update = NULL;
1904 }
1905 /* Update timer jitter. */
1906 jitter = ripng_update_jitter (ripng->update_time);
1907
1908 ripng->t_update =
1909 thread_add_timer (master, ripng_update, NULL,
1910 sock ? 2 : ripng->update_time + jitter);
1911 break;
1912 case RIPNG_TRIGGERED_UPDATE:
1913 if (ripng->t_triggered_interval)
1914 ripng->trigger = 1;
1915 else if (! ripng->t_triggered_update)
1916 ripng->t_triggered_update =
1917 thread_add_event (master, ripng_triggered_update, NULL, 0);
1918 break;
1919 default:
1920 break;
1921 }
1922}
1923
hasso7a1d5832004-10-08 06:32:23 +00001924/* Each route type's strings and default preference.
1925 * FIXME: ISIS? What are these distance values? */
paul718e3742002-12-13 20:15:29 +00001926struct
1927{
1928 int key;
hasso7a1d5832004-10-08 06:32:23 +00001929 const char *str;
1930 const char *str_long;
paul718e3742002-12-13 20:15:29 +00001931 int distance;
1932} route_info[] =
1933{
1934 { ZEBRA_ROUTE_SYSTEM, "X", "system", 10},
1935 { ZEBRA_ROUTE_KERNEL, "K", "kernel", 20},
1936 { ZEBRA_ROUTE_CONNECT, "C", "connected", 30},
1937 { ZEBRA_ROUTE_STATIC, "S", "static", 40},
1938 { ZEBRA_ROUTE_RIP, "R", "rip", 50},
1939 { ZEBRA_ROUTE_RIPNG, "R", "ripng", 50},
1940 { ZEBRA_ROUTE_OSPF, "O", "ospf", 60},
1941 { ZEBRA_ROUTE_OSPF6, "O", "ospf6", 60},
1942 { ZEBRA_ROUTE_BGP, "B", "bgp", 70},
1943};
1944
paul718e3742002-12-13 20:15:29 +00001945/* Print out routes update time. */
1946static void
1947ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo)
1948{
1949 struct timeval timer_now;
1950 time_t clock;
1951 struct tm *tm;
1952#define TIME_BUF 25
1953 char timebuf [TIME_BUF];
1954 struct thread *thread;
1955
1956 gettimeofday (&timer_now, NULL);
1957
1958 if ((thread = rinfo->t_timeout) != NULL)
1959 {
1960 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
1961 tm = gmtime (&clock);
1962 strftime (timebuf, TIME_BUF, "%M:%S", tm);
1963 vty_out (vty, "%5s", timebuf);
1964 }
1965 else if ((thread = rinfo->t_garbage_collect) != NULL)
1966 {
1967 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
1968 tm = gmtime (&clock);
1969 strftime (timebuf, TIME_BUF, "%M:%S", tm);
1970 vty_out (vty, "%5s", timebuf);
1971 }
1972}
1973
hassoa94434b2003-05-25 17:10:12 +00001974char *
1975ripng_route_subtype_print (struct ripng_info *rinfo)
1976{
1977 static char str[3];
1978 memset(str, 0, 3);
1979
1980 if (rinfo->suppress)
1981 strcat(str, "S");
1982
1983 switch (rinfo->sub_type)
1984 {
1985 case RIPNG_ROUTE_RTE:
1986 strcat(str, "n");
1987 break;
1988 case RIPNG_ROUTE_STATIC:
1989 strcat(str, "s");
1990 break;
1991 case RIPNG_ROUTE_DEFAULT:
1992 strcat(str, "d");
1993 break;
1994 case RIPNG_ROUTE_REDISTRIBUTE:
1995 strcat(str, "r");
1996 break;
1997 case RIPNG_ROUTE_INTERFACE:
1998 strcat(str, "i");
1999 break;
2000 default:
2001 strcat(str, "?");
2002 break;
2003 }
2004
2005 return str;
2006}
2007
paul718e3742002-12-13 20:15:29 +00002008DEFUN (show_ipv6_ripng,
2009 show_ipv6_ripng_cmd,
2010 "show ipv6 ripng",
2011 SHOW_STR
hasso8d0f15f2004-09-11 16:33:28 +00002012 IPV6_STR
paul718e3742002-12-13 20:15:29 +00002013 "Show RIPng routes\n")
2014{
2015 struct route_node *rp;
2016 struct ripng_info *rinfo;
2017 struct ripng_aggregate *aggregate;
2018 struct prefix_ipv6 *p;
2019 int len;
2020
hassoa94434b2003-05-25 17:10:12 +00002021 if (! ripng)
2022 return CMD_SUCCESS;
2023
paul718e3742002-12-13 20:15:29 +00002024 /* Header of display. */
hassoa94434b2003-05-25 17:10:12 +00002025 vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2026 "Sub-codes:%s"
2027 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2028 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2029 " Network Next Hop Via Metric Tag Time%s",
2030 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
paul718e3742002-12-13 20:15:29 +00002031 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
2032
2033 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
2034 {
2035 if ((aggregate = rp->aggregate) != NULL)
2036 {
2037 p = (struct prefix_ipv6 *) &rp->p;
2038
2039#ifdef DEBUG
hassoa94434b2003-05-25 17:10:12 +00002040 len = vty_out (vty, "R(a) %d/%d %s/%d ",
paul718e3742002-12-13 20:15:29 +00002041 aggregate->count, aggregate->suppress,
hasso3a2ce6a2005-04-08 01:30:51 +00002042 inet6_ntoa (p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +00002043#else
hassoa94434b2003-05-25 17:10:12 +00002044 len = vty_out (vty, "R(a) %s/%d ",
hasso3a2ce6a2005-04-08 01:30:51 +00002045 inet6_ntoa (p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +00002046#endif /* DEBUG */
hassoa94434b2003-05-25 17:10:12 +00002047 vty_out (vty, "%s", VTY_NEWLINE);
2048 vty_out (vty, "%*s", 18, " ");
paul718e3742002-12-13 20:15:29 +00002049
hassoa94434b2003-05-25 17:10:12 +00002050 vty_out (vty, "%*s", 28, " ");
2051 vty_out (vty, "self %2d %3d%s", aggregate->metric,
paul718e3742002-12-13 20:15:29 +00002052 aggregate->tag,
2053 VTY_NEWLINE);
2054 }
2055
2056 if ((rinfo = rp->info) != NULL)
2057 {
2058 p = (struct prefix_ipv6 *) &rp->p;
2059
2060#ifdef DEBUG
hassoa94434b2003-05-25 17:10:12 +00002061 len = vty_out (vty, "%s(%s) 0/%d %s/%d ",
paul718e3742002-12-13 20:15:29 +00002062 route_info[rinfo->type].str,
hassoa94434b2003-05-25 17:10:12 +00002063 ripng_route_subtype_print(rinfo),
paul718e3742002-12-13 20:15:29 +00002064 rinfo->suppress,
hasso3a2ce6a2005-04-08 01:30:51 +00002065 inet6_ntoa (p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +00002066#else
hassoa94434b2003-05-25 17:10:12 +00002067 len = vty_out (vty, "%s(%s) %s/%d ",
paul718e3742002-12-13 20:15:29 +00002068 route_info[rinfo->type].str,
hassoa94434b2003-05-25 17:10:12 +00002069 ripng_route_subtype_print(rinfo),
hasso3a2ce6a2005-04-08 01:30:51 +00002070 inet6_ntoa (p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +00002071#endif /* DEBUG */
hassoa94434b2003-05-25 17:10:12 +00002072 vty_out (vty, "%s", VTY_NEWLINE);
2073 vty_out (vty, "%*s", 18, " ");
hasso3a2ce6a2005-04-08 01:30:51 +00002074 len = vty_out (vty, "%s", inet6_ntoa (rinfo->nexthop));
paul718e3742002-12-13 20:15:29 +00002075
hassoa94434b2003-05-25 17:10:12 +00002076 len = 28 - len;
2077 if (len > 0)
2078 len = vty_out (vty, "%*s", len, " ");
2079
2080 /* from */
2081 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2082 (rinfo->sub_type == RIPNG_ROUTE_RTE))
2083 {
2084 len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex));
2085 } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
2086 {
2087 len = vty_out (vty, "kill");
2088 } else
2089 len = vty_out (vty, "self");
2090
2091 len = 9 - len;
paul718e3742002-12-13 20:15:29 +00002092 if (len > 0)
2093 vty_out (vty, "%*s", len, " ");
2094
hassoa94434b2003-05-25 17:10:12 +00002095 vty_out (vty, " %2d %3d ",
2096 rinfo->metric, rinfo->tag);
paul718e3742002-12-13 20:15:29 +00002097
hassoa94434b2003-05-25 17:10:12 +00002098 /* time */
2099 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2100 (rinfo->sub_type == RIPNG_ROUTE_RTE))
2101 {
2102 /* RTE from remote RIP routers */
paul718e3742002-12-13 20:15:29 +00002103 ripng_vty_out_uptime (vty, rinfo);
hassoa94434b2003-05-25 17:10:12 +00002104 } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
2105 {
2106 /* poisonous reversed routes (gc) */
2107 ripng_vty_out_uptime (vty, rinfo);
2108 }
paul718e3742002-12-13 20:15:29 +00002109
2110 vty_out (vty, "%s", VTY_NEWLINE);
2111 }
2112 }
2113
2114 return CMD_SUCCESS;
2115}
2116
hassoa94434b2003-05-25 17:10:12 +00002117/* Return next event time. */
2118static int
2119ripng_next_thread_timer (struct thread *thread)
2120{
2121 struct timeval timer_now;
2122
2123 gettimeofday (&timer_now, NULL);
2124
2125 return thread->u.sands.tv_sec - timer_now.tv_sec;
2126}
2127
2128DEFUN (show_ipv6_ripng_status,
2129 show_ipv6_ripng_status_cmd,
2130 "show ipv6 ripng status",
2131 SHOW_STR
hasso8d0f15f2004-09-11 16:33:28 +00002132 IPV6_STR
hassoa94434b2003-05-25 17:10:12 +00002133 "Show RIPng routes\n"
2134 "IPv6 routing protocol process parameters and statistics\n")
2135{
hasso52dc7ee2004-09-23 19:18:23 +00002136 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +00002137 struct interface *ifp;
hassoa94434b2003-05-25 17:10:12 +00002138 int ripng_network_write (struct vty *, int);
2139 void ripng_redistribute_write (struct vty *, int);
2140
2141 if (! ripng)
2142 return CMD_SUCCESS;
2143
2144 vty_out (vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE);
2145 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
2146 ripng->update_time);
2147 vty_out (vty, " next due in %d seconds%s",
2148 ripng_next_thread_timer (ripng->t_update),
2149 VTY_NEWLINE);
2150 vty_out (vty, " Timeout after %ld seconds,", ripng->timeout_time);
2151 vty_out (vty, " garbage collect after %ld seconds%s", ripng->garbage_time,
2152 VTY_NEWLINE);
2153
2154 /* Filtering status show. */
2155 config_show_distribute (vty);
2156
2157 /* Default metric information. */
2158 vty_out (vty, " Default redistribution metric is %d%s",
2159 ripng->default_metric, VTY_NEWLINE);
2160
2161 /* Redistribute information. */
2162 vty_out (vty, " Redistributing:");
2163 ripng_redistribute_write (vty, 0);
2164 vty_out (vty, "%s", VTY_NEWLINE);
2165
2166 vty_out (vty, " Default version control: send version %d,", ripng->version);
2167 vty_out (vty, " receive version %d %s", ripng->version,
2168 VTY_NEWLINE);
2169
2170 vty_out (vty, " Interface Send Recv%s", VTY_NEWLINE);
2171
paul1eb8ef22005-04-07 07:30:20 +00002172 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
hassoa94434b2003-05-25 17:10:12 +00002173 {
2174 struct ripng_interface *ri;
paul1eb8ef22005-04-07 07:30:20 +00002175
hassoa94434b2003-05-25 17:10:12 +00002176 ri = ifp->info;
2177
2178 if (ri->enable_network || ri->enable_interface)
2179 {
2180
2181 vty_out (vty, " %-17s%-3d %-3d%s", ifp->name,
2182 ripng->version,
2183 ripng->version,
2184 VTY_NEWLINE);
2185 }
2186 }
2187
2188 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
2189 ripng_network_write (vty, 0);
2190
2191 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
2192 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
2193 ripng_peer_display (vty);
2194
2195 return CMD_SUCCESS;
2196}
2197
paul718e3742002-12-13 20:15:29 +00002198DEFUN (router_ripng,
2199 router_ripng_cmd,
2200 "router ripng",
2201 "Enable a routing process\n"
2202 "Make RIPng instance command\n")
2203{
2204 int ret;
2205
2206 vty->node = RIPNG_NODE;
2207
2208 if (!ripng)
2209 {
2210 ret = ripng_create ();
2211
2212 /* Notice to user we couldn't create RIPng. */
2213 if (ret < 0)
2214 {
2215 zlog_warn ("can't create RIPng");
2216 return CMD_WARNING;
2217 }
2218 }
2219
2220 return CMD_SUCCESS;
2221}
2222
hassoa94434b2003-05-25 17:10:12 +00002223DEFUN (no_router_ripng,
2224 no_router_ripng_cmd,
2225 "no router ripng",
2226 NO_STR
2227 "Enable a routing process\n"
2228 "Make RIPng instance command\n")
2229{
2230 if(ripng)
2231 ripng_clean();
2232 return CMD_SUCCESS;
2233}
2234
paul718e3742002-12-13 20:15:29 +00002235DEFUN (ripng_route,
2236 ripng_route_cmd,
2237 "route IPV6ADDR",
2238 "Static route setup\n"
2239 "Set static RIPng route announcement\n")
2240{
2241 int ret;
2242 struct prefix_ipv6 p;
2243 struct route_node *rp;
2244
2245 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2246 if (ret <= 0)
2247 {
2248 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2249 return CMD_WARNING;
2250 }
2251 apply_mask_ipv6 (&p);
2252
2253 rp = route_node_get (ripng->route, (struct prefix *) &p);
2254 if (rp->info)
2255 {
2256 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2257 route_unlock_node (rp);
2258 return CMD_WARNING;
2259 }
2260 rp->info = (void *)1;
2261
hassoa94434b2003-05-25 17:10:12 +00002262 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL);
paul718e3742002-12-13 20:15:29 +00002263
2264 return CMD_SUCCESS;
2265}
2266
2267DEFUN (no_ripng_route,
2268 no_ripng_route_cmd,
2269 "no route IPV6ADDR",
2270 NO_STR
2271 "Static route setup\n"
2272 "Delete static RIPng route announcement\n")
2273{
2274 int ret;
2275 struct prefix_ipv6 p;
2276 struct route_node *rp;
2277
2278 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2279 if (ret <= 0)
2280 {
2281 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2282 return CMD_WARNING;
2283 }
2284 apply_mask_ipv6 (&p);
2285
2286 rp = route_node_lookup (ripng->route, (struct prefix *) &p);
2287 if (! rp)
2288 {
2289 vty_out (vty, "Can't find static route.%s", VTY_NEWLINE);
2290 return CMD_WARNING;
2291 }
2292
2293 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
2294 route_unlock_node (rp);
2295
2296 rp->info = NULL;
2297 route_unlock_node (rp);
2298
2299 return CMD_SUCCESS;
2300}
2301
2302DEFUN (ripng_aggregate_address,
2303 ripng_aggregate_address_cmd,
2304 "aggregate-address X:X::X:X/M",
2305 "Set aggregate RIPng route announcement\n"
2306 "Aggregate network\n")
2307{
2308 int ret;
2309 struct prefix p;
2310 struct route_node *node;
2311
2312 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2313 if (ret <= 0)
2314 {
2315 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2316 return CMD_WARNING;
2317 }
2318
2319 /* Check aggregate alredy exist or not. */
2320 node = route_node_get (ripng->aggregate, &p);
2321 if (node->info)
2322 {
2323 vty_out (vty, "There is already same aggregate route.%s", VTY_NEWLINE);
2324 route_unlock_node (node);
2325 return CMD_WARNING;
2326 }
2327 node->info = (void *)1;
2328
2329 ripng_aggregate_add (&p);
2330
2331 return CMD_SUCCESS;
2332}
2333
2334DEFUN (no_ripng_aggregate_address,
2335 no_ripng_aggregate_address_cmd,
2336 "no aggregate-address X:X::X:X/M",
2337 NO_STR
2338 "Delete aggregate RIPng route announcement\n"
2339 "Aggregate network")
2340{
2341 int ret;
2342 struct prefix p;
2343 struct route_node *rn;
2344
2345 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &p);
2346 if (ret <= 0)
2347 {
2348 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2349 return CMD_WARNING;
2350 }
2351
2352 rn = route_node_lookup (ripng->aggregate, &p);
2353 if (! rn)
2354 {
2355 vty_out (vty, "Can't find aggregate route.%s", VTY_NEWLINE);
2356 return CMD_WARNING;
2357 }
2358 route_unlock_node (rn);
2359 rn->info = NULL;
2360 route_unlock_node (rn);
2361
2362 ripng_aggregate_delete (&p);
2363
2364 return CMD_SUCCESS;
2365}
2366
2367DEFUN (ripng_default_metric,
2368 ripng_default_metric_cmd,
2369 "default-metric <1-16>",
2370 "Set a metric of redistribute routes\n"
2371 "Default metric\n")
2372{
2373 if (ripng)
2374 {
2375 ripng->default_metric = atoi (argv[0]);
2376 }
2377 return CMD_SUCCESS;
2378}
2379
2380DEFUN (no_ripng_default_metric,
2381 no_ripng_default_metric_cmd,
2382 "no default-metric",
2383 NO_STR
2384 "Set a metric of redistribute routes\n"
2385 "Default metric\n")
2386{
2387 if (ripng)
2388 {
2389 ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
2390 }
2391 return CMD_SUCCESS;
2392}
2393
2394ALIAS (no_ripng_default_metric,
2395 no_ripng_default_metric_val_cmd,
2396 "no default-metric <1-16>",
2397 NO_STR
2398 "Set a metric of redistribute routes\n"
2399 "Default metric\n")
2400
2401#if 0
2402/* RIPng update timer setup. */
2403DEFUN (ripng_update_timer,
2404 ripng_update_timer_cmd,
2405 "update-timer SECOND",
2406 "Set RIPng update timer in seconds\n"
2407 "Seconds\n")
2408{
2409 unsigned long update;
2410 char *endptr = NULL;
2411
2412 update = strtoul (argv[0], &endptr, 10);
2413 if (update == ULONG_MAX || *endptr != '\0')
2414 {
2415 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2416 return CMD_WARNING;
2417 }
2418
2419 ripng->update_time = update;
2420
2421 ripng_event (RIPNG_UPDATE_EVENT, 0);
2422 return CMD_SUCCESS;
2423}
2424
2425DEFUN (no_ripng_update_timer,
2426 no_ripng_update_timer_cmd,
2427 "no update-timer SECOND",
2428 NO_STR
2429 "Unset RIPng update timer in seconds\n"
2430 "Seconds\n")
2431{
2432 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2433 ripng_event (RIPNG_UPDATE_EVENT, 0);
2434 return CMD_SUCCESS;
2435}
2436
2437/* RIPng timeout timer setup. */
2438DEFUN (ripng_timeout_timer,
2439 ripng_timeout_timer_cmd,
2440 "timeout-timer SECOND",
2441 "Set RIPng timeout timer in seconds\n"
2442 "Seconds\n")
2443{
2444 unsigned long timeout;
2445 char *endptr = NULL;
2446
2447 timeout = strtoul (argv[0], &endptr, 10);
2448 if (timeout == ULONG_MAX || *endptr != '\0')
2449 {
2450 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2451 return CMD_WARNING;
2452 }
2453
2454 ripng->timeout_time = timeout;
2455
2456 return CMD_SUCCESS;
2457}
2458
2459DEFUN (no_ripng_timeout_timer,
2460 no_ripng_timeout_timer_cmd,
2461 "no timeout-timer SECOND",
2462 NO_STR
2463 "Unset RIPng timeout timer in seconds\n"
2464 "Seconds\n")
2465{
2466 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2467 return CMD_SUCCESS;
2468}
2469
2470/* RIPng garbage timer setup. */
2471DEFUN (ripng_garbage_timer,
2472 ripng_garbage_timer_cmd,
2473 "garbage-timer SECOND",
2474 "Set RIPng garbage timer in seconds\n"
2475 "Seconds\n")
2476{
2477 unsigned long garbage;
2478 char *endptr = NULL;
2479
2480 garbage = strtoul (argv[0], &endptr, 10);
2481 if (garbage == ULONG_MAX || *endptr != '\0')
2482 {
2483 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2484 return CMD_WARNING;
2485 }
2486
2487 ripng->garbage_time = garbage;
2488
2489 return CMD_SUCCESS;
2490}
2491
2492DEFUN (no_ripng_garbage_timer,
2493 no_ripng_garbage_timer_cmd,
2494 "no garbage-timer SECOND",
2495 NO_STR
2496 "Unset RIPng garbage timer in seconds\n"
2497 "Seconds\n")
2498{
2499 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2500 return CMD_SUCCESS;
2501}
2502#endif /* 0 */
2503
2504DEFUN (ripng_timers,
2505 ripng_timers_cmd,
2506 "timers basic <0-65535> <0-65535> <0-65535>",
2507 "RIPng timers setup\n"
2508 "Basic timer\n"
2509 "Routing table update timer value in second. Default is 30.\n"
2510 "Routing information timeout timer. Default is 180.\n"
2511 "Garbage collection timer. Default is 120.\n")
2512{
2513 unsigned long update;
2514 unsigned long timeout;
2515 unsigned long garbage;
2516 char *endptr = NULL;
2517
2518 update = strtoul (argv[0], &endptr, 10);
2519 if (update == ULONG_MAX || *endptr != '\0')
2520 {
2521 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2522 return CMD_WARNING;
2523 }
2524
2525 timeout = strtoul (argv[1], &endptr, 10);
2526 if (timeout == ULONG_MAX || *endptr != '\0')
2527 {
2528 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2529 return CMD_WARNING;
2530 }
2531
2532 garbage = strtoul (argv[2], &endptr, 10);
2533 if (garbage == ULONG_MAX || *endptr != '\0')
2534 {
2535 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2536 return CMD_WARNING;
2537 }
2538
2539 /* Set each timer value. */
2540 ripng->update_time = update;
2541 ripng->timeout_time = timeout;
2542 ripng->garbage_time = garbage;
2543
2544 /* Reset update timer thread. */
2545 ripng_event (RIPNG_UPDATE_EVENT, 0);
2546
2547 return CMD_SUCCESS;
2548}
2549
2550DEFUN (no_ripng_timers,
2551 no_ripng_timers_cmd,
2552 "no timers basic",
2553 NO_STR
2554 "RIPng timers setup\n"
2555 "Basic timer\n")
2556{
2557 /* Set each timer value to the default. */
2558 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2559 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2560 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2561
2562 /* Reset update timer thread. */
2563 ripng_event (RIPNG_UPDATE_EVENT, 0);
2564
2565 return CMD_SUCCESS;
2566}
2567
hassoa94434b2003-05-25 17:10:12 +00002568ALIAS (no_ripng_timers,
2569 no_ripng_timers_val_cmd,
2570 "no timers basic <0-65535> <0-65535> <0-65535>",
2571 NO_STR
2572 "RIPng timers setup\n"
2573 "Basic timer\n"
2574 "Routing table update timer value in second. Default is 30.\n"
2575 "Routing information timeout timer. Default is 180.\n"
2576 "Garbage collection timer. Default is 120.\n")
paul718e3742002-12-13 20:15:29 +00002577
2578DEFUN (show_ipv6_protocols, show_ipv6_protocols_cmd,
2579 "show ipv6 protocols",
2580 SHOW_STR
hasso8d0f15f2004-09-11 16:33:28 +00002581 IPV6_STR
paul718e3742002-12-13 20:15:29 +00002582 "Routing protocol information")
2583{
2584 if (! ripng)
2585 return CMD_SUCCESS;
2586
2587 vty_out (vty, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE);
2588
2589 vty_out (vty, "Sending updates every %ld seconds, next due in %d seconds%s",
2590 ripng->update_time, 0,
2591 VTY_NEWLINE);
2592
2593 vty_out (vty, "Timerout after %ld seconds, garbage correct %ld%s",
2594 ripng->timeout_time,
2595 ripng->garbage_time,
2596 VTY_NEWLINE);
2597
2598 vty_out (vty, "Outgoing update filter list for all interfaces is not set");
2599 vty_out (vty, "Incoming update filter list for all interfaces is not set");
2600
2601 return CMD_SUCCESS;
2602}
2603
2604/* Please be carefull to use this command. */
paula2c62832003-04-23 17:01:31 +00002605DEFUN (ripng_default_information_originate,
2606 ripng_default_information_originate_cmd,
paul718e3742002-12-13 20:15:29 +00002607 "default-information originate",
2608 "Default route information\n"
2609 "Distribute default route\n")
2610{
2611 struct prefix_ipv6 p;
2612
hassoa94434b2003-05-25 17:10:12 +00002613 if (! ripng ->default_information) {
2614 ripng->default_information = 1;
paul718e3742002-12-13 20:15:29 +00002615
hassoa94434b2003-05-25 17:10:12 +00002616 str2prefix_ipv6 ("::/0", &p);
2617 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL);
2618 }
paul718e3742002-12-13 20:15:29 +00002619
2620 return CMD_SUCCESS;
2621}
2622
paula2c62832003-04-23 17:01:31 +00002623DEFUN (no_ripng_default_information_originate,
2624 no_ripng_default_information_originate_cmd,
paul718e3742002-12-13 20:15:29 +00002625 "no default-information originate",
2626 NO_STR
2627 "Default route information\n"
2628 "Distribute default route\n")
2629{
2630 struct prefix_ipv6 p;
2631
hassoa94434b2003-05-25 17:10:12 +00002632 if (ripng->default_information) {
2633 ripng->default_information = 0;
paul718e3742002-12-13 20:15:29 +00002634
hassoa94434b2003-05-25 17:10:12 +00002635 str2prefix_ipv6 ("::/0", &p);
2636 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0);
2637 }
paul718e3742002-12-13 20:15:29 +00002638
2639 return CMD_SUCCESS;
2640}
2641
2642/* RIPng configuration write function. */
2643int
2644ripng_config_write (struct vty *vty)
2645{
hassoa94434b2003-05-25 17:10:12 +00002646 int ripng_network_write (struct vty *, int);
2647 void ripng_redistribute_write (struct vty *, int);
paul718e3742002-12-13 20:15:29 +00002648 int write = 0;
2649 struct route_node *rp;
2650
2651 if (ripng)
2652 {
2653
2654 /* RIPng router. */
2655 vty_out (vty, "router ripng%s", VTY_NEWLINE);
2656
2657 if (ripng->default_information)
2658 vty_out (vty, " default-information originate%s", VTY_NEWLINE);
2659
hassoa94434b2003-05-25 17:10:12 +00002660 ripng_network_write (vty, 1);
paul718e3742002-12-13 20:15:29 +00002661
2662 /* RIPng default metric configuration */
2663 if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT)
2664 vty_out (vty, " default-metric %d%s",
2665 ripng->default_metric, VTY_NEWLINE);
2666
hassoa94434b2003-05-25 17:10:12 +00002667 ripng_redistribute_write (vty, 1);
2668
2669 /* RIP offset-list configuration. */
2670 config_write_ripng_offset_list (vty);
paul718e3742002-12-13 20:15:29 +00002671
2672 /* RIPng aggregate routes. */
2673 for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
2674 if (rp->info != NULL)
2675 vty_out (vty, " aggregate-address %s/%d%s",
hasso3a2ce6a2005-04-08 01:30:51 +00002676 inet6_ntoa (rp->p.u.prefix6),
paul718e3742002-12-13 20:15:29 +00002677 rp->p.prefixlen,
2678
2679 VTY_NEWLINE);
2680
2681 /* RIPng static routes. */
2682 for (rp = route_top (ripng->route); rp; rp = route_next (rp))
2683 if (rp->info != NULL)
hasso3a2ce6a2005-04-08 01:30:51 +00002684 vty_out (vty, " route %s/%d%s", inet6_ntoa (rp->p.u.prefix6),
paul718e3742002-12-13 20:15:29 +00002685 rp->p.prefixlen,
2686 VTY_NEWLINE);
2687
2688 /* RIPng timers configuration. */
2689 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT ||
2690 ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT ||
2691 ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
2692 {
2693 vty_out (vty, " timers basic %ld %ld %ld%s",
2694 ripng->update_time,
2695 ripng->timeout_time,
2696 ripng->garbage_time,
2697 VTY_NEWLINE);
2698 }
2699#if 0
2700 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT)
2701 vty_out (vty, " update-timer %d%s", ripng->update_time,
2702 VTY_NEWLINE);
2703 if (ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT)
2704 vty_out (vty, " timeout-timer %d%s", ripng->timeout_time,
2705 VTY_NEWLINE);
2706 if (ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
2707 vty_out (vty, " garbage-timer %d%s", ripng->garbage_time,
2708 VTY_NEWLINE);
2709#endif /* 0 */
2710
2711 write += config_write_distribute (vty);
2712
2713 write += config_write_if_rmap (vty);
2714
2715 write++;
2716 }
2717 return write;
2718}
2719
2720/* RIPng node structure. */
2721struct cmd_node cmd_ripng_node =
2722{
2723 RIPNG_NODE,
2724 "%s(config-router)# ",
2725 1,
2726};
2727
2728void
2729ripng_distribute_update (struct distribute *dist)
2730{
2731 struct interface *ifp;
2732 struct ripng_interface *ri;
2733 struct access_list *alist;
2734 struct prefix_list *plist;
2735
2736 if (! dist->ifname)
2737 return;
2738
2739 ifp = if_lookup_by_name (dist->ifname);
2740 if (ifp == NULL)
2741 return;
2742
2743 ri = ifp->info;
2744
2745 if (dist->list[DISTRIBUTE_IN])
2746 {
2747 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
2748 if (alist)
2749 ri->list[RIPNG_FILTER_IN] = alist;
2750 else
2751 ri->list[RIPNG_FILTER_IN] = NULL;
2752 }
2753 else
2754 ri->list[RIPNG_FILTER_IN] = NULL;
2755
2756 if (dist->list[DISTRIBUTE_OUT])
2757 {
2758 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
2759 if (alist)
2760 ri->list[RIPNG_FILTER_OUT] = alist;
2761 else
2762 ri->list[RIPNG_FILTER_OUT] = NULL;
2763 }
2764 else
2765 ri->list[RIPNG_FILTER_OUT] = NULL;
2766
2767 if (dist->prefix[DISTRIBUTE_IN])
2768 {
2769 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
2770 if (plist)
2771 ri->prefix[RIPNG_FILTER_IN] = plist;
2772 else
2773 ri->prefix[RIPNG_FILTER_IN] = NULL;
2774 }
2775 else
2776 ri->prefix[RIPNG_FILTER_IN] = NULL;
2777
2778 if (dist->prefix[DISTRIBUTE_OUT])
2779 {
2780 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
2781 if (plist)
2782 ri->prefix[RIPNG_FILTER_OUT] = plist;
2783 else
2784 ri->prefix[RIPNG_FILTER_OUT] = NULL;
2785 }
2786 else
2787 ri->prefix[RIPNG_FILTER_OUT] = NULL;
2788}
hassoa94434b2003-05-25 17:10:12 +00002789
paul718e3742002-12-13 20:15:29 +00002790void
2791ripng_distribute_update_interface (struct interface *ifp)
2792{
2793 struct distribute *dist;
2794
2795 dist = distribute_lookup (ifp->name);
2796 if (dist)
2797 ripng_distribute_update (dist);
2798}
2799
2800/* Update all interface's distribute list. */
2801void
hassoc9e52be2004-09-26 16:09:34 +00002802ripng_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00002803{
2804 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00002805 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002806
paul1eb8ef22005-04-07 07:30:20 +00002807 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2808 ripng_distribute_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00002809}
hassoc9e52be2004-09-26 16:09:34 +00002810
2811void
2812ripng_distribute_update_all_wrapper (struct access_list *notused)
2813{
2814 ripng_distribute_update_all(NULL);
2815}
hassoa94434b2003-05-25 17:10:12 +00002816
2817/* delete all the added ripng routes. */
2818void
2819ripng_clean()
2820{
2821 int i;
2822 struct route_node *rp;
2823 struct ripng_info *rinfo;
2824
2825 if (ripng) {
2826 /* Clear RIPng routes */
2827 for (rp = route_top (ripng->table); rp; rp = route_next (rp)) {
2828 if ((rinfo = rp->info) != NULL) {
2829 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2830 (rinfo->sub_type == RIPNG_ROUTE_RTE))
2831 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p,
2832 &rinfo->nexthop, rinfo->metric);
2833
2834 RIPNG_TIMER_OFF (rinfo->t_timeout);
2835 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
2836
2837 rp->info = NULL;
2838 route_unlock_node (rp);
2839
2840 ripng_info_free(rinfo);
2841 }
2842 }
2843
2844 /* Cancel the RIPng timers */
2845 RIPNG_TIMER_OFF (ripng->t_update);
2846 RIPNG_TIMER_OFF (ripng->t_triggered_update);
2847 RIPNG_TIMER_OFF (ripng->t_triggered_interval);
2848
2849 /* Cancel the read thread */
2850 if (ripng->t_read) {
2851 thread_cancel (ripng->t_read);
2852 ripng->t_read = NULL;
2853 }
2854
2855 /* Close the RIPng socket */
2856 if (ripng->sock >= 0) {
2857 close(ripng->sock);
2858 ripng->sock = -1;
2859 }
2860
2861 /* Static RIPng route configuration. */
2862 for (rp = route_top (ripng->route); rp; rp = route_next (rp))
2863 if (rp->info) {
2864 rp->info = NULL;
2865 route_unlock_node (rp);
2866 }
2867
2868 /* RIPng aggregated prefixes */
2869 for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
2870 if (rp->info) {
2871 rp->info = NULL;
2872 route_unlock_node (rp);
2873 }
2874
2875 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2876 if (ripng->route_map[i].name)
2877 free (ripng->route_map[i].name);
2878
2879 XFREE (MTYPE_ROUTE_TABLE, ripng->table);
2880 XFREE (MTYPE_ROUTE_TABLE, ripng->route);
2881 XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate);
2882
2883 XFREE (MTYPE_RIPNG, ripng);
2884 ripng = NULL;
2885 } /* if (ripng) */
2886
2887 ripng_clean_network();
2888 ripng_passive_interface_clean ();
2889 ripng_offset_clean ();
2890 ripng_interface_clean ();
2891 ripng_redistribute_clean ();
2892}
2893
2894/* Reset all values to the default settings. */
2895void
2896ripng_reset ()
2897{
2898 /* Call ripd related reset functions. */
2899 ripng_debug_reset ();
2900 ripng_route_map_reset ();
2901
2902 /* Call library reset functions. */
2903 vty_reset ();
2904 access_list_reset ();
2905 prefix_list_reset ();
2906
2907 distribute_list_reset ();
2908
2909 ripng_interface_reset ();
2910
2911 ripng_zclient_reset ();
2912}
paul718e3742002-12-13 20:15:29 +00002913
2914void
2915ripng_if_rmap_update (struct if_rmap *if_rmap)
2916{
2917 struct interface *ifp;
2918 struct ripng_interface *ri;
2919 struct route_map *rmap;
2920
2921 ifp = if_lookup_by_name (if_rmap->ifname);
2922 if (ifp == NULL)
2923 return;
2924
2925 ri = ifp->info;
2926
2927 if (if_rmap->routemap[IF_RMAP_IN])
2928 {
2929 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
2930 if (rmap)
2931 ri->routemap[IF_RMAP_IN] = rmap;
2932 else
2933 ri->routemap[IF_RMAP_IN] = NULL;
2934 }
2935 else
2936 ri->routemap[RIPNG_FILTER_IN] = NULL;
2937
2938 if (if_rmap->routemap[IF_RMAP_OUT])
2939 {
2940 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
2941 if (rmap)
2942 ri->routemap[IF_RMAP_OUT] = rmap;
2943 else
2944 ri->routemap[IF_RMAP_OUT] = NULL;
2945 }
2946 else
2947 ri->routemap[RIPNG_FILTER_OUT] = NULL;
2948}
2949
2950void
2951ripng_if_rmap_update_interface (struct interface *ifp)
2952{
2953 struct if_rmap *if_rmap;
2954
2955 if_rmap = if_rmap_lookup (ifp->name);
2956 if (if_rmap)
2957 ripng_if_rmap_update (if_rmap);
2958}
2959
2960void
2961ripng_routemap_update_redistribute (void)
2962{
2963 int i;
2964
2965 if (ripng)
2966 {
2967 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2968 {
2969 if (ripng->route_map[i].name)
2970 ripng->route_map[i].map =
2971 route_map_lookup_by_name (ripng->route_map[i].name);
2972 }
2973 }
2974}
2975
2976void
hasso98b718a2004-10-11 12:57:57 +00002977ripng_routemap_update (const char *unused)
paul718e3742002-12-13 20:15:29 +00002978{
2979 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00002980 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002981
paul1eb8ef22005-04-07 07:30:20 +00002982 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2983 ripng_if_rmap_update_interface (ifp);
paul718e3742002-12-13 20:15:29 +00002984
2985 ripng_routemap_update_redistribute ();
2986}
2987
2988/* Initialize ripng structure and set commands. */
2989void
2990ripng_init ()
2991{
2992 /* Randomize. */
2993 srand (time (NULL));
2994
2995 /* Install RIPNG_NODE. */
2996 install_node (&cmd_ripng_node, ripng_config_write);
2997
2998 /* Install ripng commands. */
2999 install_element (VIEW_NODE, &show_ipv6_ripng_cmd);
hassoa94434b2003-05-25 17:10:12 +00003000 install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd);
paul718e3742002-12-13 20:15:29 +00003001
3002 install_element (ENABLE_NODE, &show_ipv6_ripng_cmd);
hassoa94434b2003-05-25 17:10:12 +00003003 install_element (ENABLE_NODE, &show_ipv6_ripng_status_cmd);
paul718e3742002-12-13 20:15:29 +00003004
3005 install_element (CONFIG_NODE, &router_ripng_cmd);
hassoa94434b2003-05-25 17:10:12 +00003006 install_element (CONFIG_NODE, &no_router_ripng_cmd);
paul718e3742002-12-13 20:15:29 +00003007
3008 install_default (RIPNG_NODE);
3009 install_element (RIPNG_NODE, &ripng_route_cmd);
3010 install_element (RIPNG_NODE, &no_ripng_route_cmd);
3011 install_element (RIPNG_NODE, &ripng_aggregate_address_cmd);
3012 install_element (RIPNG_NODE, &no_ripng_aggregate_address_cmd);
3013
3014 install_element (RIPNG_NODE, &ripng_default_metric_cmd);
3015 install_element (RIPNG_NODE, &no_ripng_default_metric_cmd);
3016 install_element (RIPNG_NODE, &no_ripng_default_metric_val_cmd);
3017
3018 install_element (RIPNG_NODE, &ripng_timers_cmd);
3019 install_element (RIPNG_NODE, &no_ripng_timers_cmd);
hassoa94434b2003-05-25 17:10:12 +00003020 install_element (RIPNG_NODE, &no_ripng_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003021#if 0
3022 install_element (RIPNG_NODE, &ripng_update_timer_cmd);
3023 install_element (RIPNG_NODE, &no_ripng_update_timer_cmd);
3024 install_element (RIPNG_NODE, &ripng_timeout_timer_cmd);
3025 install_element (RIPNG_NODE, &no_ripng_timeout_timer_cmd);
3026 install_element (RIPNG_NODE, &ripng_garbage_timer_cmd);
3027 install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd);
3028#endif /* 0 */
3029
paula2c62832003-04-23 17:01:31 +00003030 install_element (RIPNG_NODE, &ripng_default_information_originate_cmd);
3031 install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd);
paul718e3742002-12-13 20:15:29 +00003032
3033 ripng_if_init ();
3034 ripng_debug_init ();
3035
3036 /* Access list install. */
3037 access_list_init ();
hassoc9e52be2004-09-26 16:09:34 +00003038 access_list_add_hook (ripng_distribute_update_all_wrapper);
3039 access_list_delete_hook (ripng_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00003040
3041 /* Prefix list initialize.*/
3042 prefix_list_init ();
3043 prefix_list_add_hook (ripng_distribute_update_all);
3044 prefix_list_delete_hook (ripng_distribute_update_all);
3045
3046 /* Distribute list install. */
3047 distribute_list_init (RIPNG_NODE);
3048 distribute_list_add_hook (ripng_distribute_update);
3049 distribute_list_delete_hook (ripng_distribute_update);
3050
3051 /* Route-map for interface. */
3052 ripng_route_map_init ();
hassoa94434b2003-05-25 17:10:12 +00003053 ripng_offset_init ();
3054
paul718e3742002-12-13 20:15:29 +00003055 route_map_add_hook (ripng_routemap_update);
3056 route_map_delete_hook (ripng_routemap_update);
3057
hasso0750d212003-05-24 21:41:49 +00003058 if_rmap_init (RIPNG_NODE);
paul718e3742002-12-13 20:15:29 +00003059 if_rmap_hook_add (ripng_if_rmap_update);
3060 if_rmap_hook_delete (ripng_if_rmap_update);
3061}