blob: b6b5f5aefa4523119c541f477c051423a165506d [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)
hasso59209902005-04-05 14:36:49 +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,
hasso59209902005-04-05 14:36:49 +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)
hasso59209902005-04-05 14:36:49 +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",
hasso59209902005-04-05 14:36:49 +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",
hasso59209902005-04-05 14:36:49 +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",
hasso59209902005-04-05 14:36:49 +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",
hasso59209902005-04-05 14:36:49 +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",
hasso59209902005-04-05 14:36:49 +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{
hasso52dc7ee2004-09-23 19:18:23 +0000383 struct listnode *listnode;
paul718e3742002-12-13 20:15:29 +0000384 struct connected *connected;
385 struct prefix *p;
386
387 for (listnode = listhead (ifp->connected); listnode; nextnode (listnode))
388 if ((connected = getdata (listnode)) != NULL)
389 {
390 p = connected->address;
391
392 if (p->family == AF_INET6 &&
393 IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6) &&
394 IN6_ARE_ADDR_EQUAL (&p->u.prefix6, addr))
395 return 1;
396 }
397 return 0;
398}
399
400/* RIPng route garbage collect timer. */
401int
402ripng_garbage_collect (struct thread *t)
403{
404 struct ripng_info *rinfo;
405 struct route_node *rp;
406
407 rinfo = THREAD_ARG (t);
408 rinfo->t_garbage_collect = NULL;
409
410 /* Off timeout timer. */
411 RIPNG_TIMER_OFF (rinfo->t_timeout);
412
413 /* Get route_node pointer. */
414 rp = rinfo->rp;
415
paul718e3742002-12-13 20:15:29 +0000416 /* Unlock route_node. */
417 rp->info = NULL;
418 route_unlock_node (rp);
419
420 /* Free RIPng routing information. */
421 ripng_info_free (rinfo);
422
423 return 0;
424}
425
426/* Timeout RIPng routes. */
427int
428ripng_timeout (struct thread *t)
429{
430 struct ripng_info *rinfo;
431 struct route_node *rp;
432
433 rinfo = THREAD_ARG (t);
434 rinfo->t_timeout = NULL;
435
436 /* Get route_node pointer. */
437 rp = rinfo->rp;
438
439 /* - The garbage-collection timer is set for 120 seconds. */
440 RIPNG_TIMER_ON (rinfo->t_garbage_collect, ripng_garbage_collect,
441 ripng->garbage_time);
442
hassoa94434b2003-05-25 17:10:12 +0000443 /* Delete this route from the kernel. */
444 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
445 rinfo->ifindex);
paul718e3742002-12-13 20:15:29 +0000446 /* - The metric for the route is set to 16 (infinity). This causes
447 the route to be removed from service. */
448 rinfo->metric = RIPNG_METRIC_INFINITY;
hassoa94434b2003-05-25 17:10:12 +0000449 rinfo->flags &= ~RIPNG_RTF_FIB;
450
451 /* Aggregate count decrement. */
452 ripng_aggregate_decrement (rp, rinfo);
paul718e3742002-12-13 20:15:29 +0000453
454 /* - The route change flag is to indicate that this entry has been
455 changed. */
456 rinfo->flags |= RIPNG_RTF_CHANGED;
457
458 /* - The output process is signalled to trigger a response. */
459 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
460
461 return 0;
462}
463
464void
465ripng_timeout_update (struct ripng_info *rinfo)
466{
467 if (rinfo->metric != RIPNG_METRIC_INFINITY)
468 {
469 RIPNG_TIMER_OFF (rinfo->t_timeout);
470 RIPNG_TIMER_ON (rinfo->t_timeout, ripng_timeout, ripng->timeout_time);
471 }
472}
473
hassoa94434b2003-05-25 17:10:12 +0000474int
475ripng_incoming_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
476{
477 struct distribute *dist;
478 struct access_list *alist;
479 struct prefix_list *plist;
480
481 /* Input distribute-list filtering. */
482 if (ri->list[RIPNG_FILTER_IN])
483 {
484 if (access_list_apply (ri->list[RIPNG_FILTER_IN],
485 (struct prefix *) p) == FILTER_DENY)
486 {
487 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000488 zlog_debug ("%s/%d filtered by distribute in",
hasso59209902005-04-05 14:36:49 +0000489 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000490 return -1;
491 }
492 }
493 if (ri->prefix[RIPNG_FILTER_IN])
494 {
495 if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN],
496 (struct prefix *) p) == PREFIX_DENY)
497 {
498 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000499 zlog_debug ("%s/%d filtered by prefix-list in",
hasso59209902005-04-05 14:36:49 +0000500 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000501 return -1;
502 }
503 }
504
505 /* All interface filter check. */
506 dist = distribute_lookup (NULL);
507 if (dist)
508 {
509 if (dist->list[DISTRIBUTE_IN])
510 {
511 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
512
513 if (alist)
514 {
515 if (access_list_apply (alist,
516 (struct prefix *) p) == FILTER_DENY)
517 {
518 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000519 zlog_debug ("%s/%d filtered by distribute in",
hasso59209902005-04-05 14:36:49 +0000520 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000521 return -1;
522 }
523 }
524 }
525 if (dist->prefix[DISTRIBUTE_IN])
526 {
527 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
528
529 if (plist)
530 {
531 if (prefix_list_apply (plist,
532 (struct prefix *) p) == PREFIX_DENY)
533 {
534 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000535 zlog_debug ("%s/%d filtered by prefix-list in",
hasso59209902005-04-05 14:36:49 +0000536 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000537 return -1;
538 }
539 }
540 }
541 }
542 return 0;
543}
544
545int
546ripng_outgoing_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
547{
548 struct distribute *dist;
549 struct access_list *alist;
550 struct prefix_list *plist;
551
552 if (ri->list[RIPNG_FILTER_OUT])
553 {
554 if (access_list_apply (ri->list[RIPNG_FILTER_OUT],
555 (struct prefix *) p) == FILTER_DENY)
556 {
557 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000558 zlog_debug ("%s/%d is filtered by distribute out",
hasso59209902005-04-05 14:36:49 +0000559 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000560 return -1;
561 }
562 }
563 if (ri->prefix[RIPNG_FILTER_OUT])
564 {
565 if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT],
566 (struct prefix *) p) == PREFIX_DENY)
567 {
568 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000569 zlog_debug ("%s/%d is filtered by prefix-list out",
hasso59209902005-04-05 14:36:49 +0000570 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000571 return -1;
572 }
573 }
574
575 /* All interface filter check. */
576 dist = distribute_lookup (NULL);
577 if (dist)
578 {
579 if (dist->list[DISTRIBUTE_OUT])
580 {
581 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
582
583 if (alist)
584 {
585 if (access_list_apply (alist,
586 (struct prefix *) p) == FILTER_DENY)
587 {
588 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000589 zlog_debug ("%s/%d filtered by distribute out",
hasso59209902005-04-05 14:36:49 +0000590 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000591 return -1;
592 }
593 }
594 }
595 if (dist->prefix[DISTRIBUTE_OUT])
596 {
597 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
598
599 if (plist)
600 {
601 if (prefix_list_apply (plist,
602 (struct prefix *) p) == PREFIX_DENY)
603 {
604 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000605 zlog_debug ("%s/%d filtered by prefix-list out",
hasso59209902005-04-05 14:36:49 +0000606 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +0000607 return -1;
608 }
609 }
610 }
611 }
612 return 0;
613}
614
paul718e3742002-12-13 20:15:29 +0000615/* Process RIPng route according to RFC2080. */
616void
617ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
618 struct ripng_nexthop *ripng_nexthop,
619 struct interface *ifp)
620{
hassoa94434b2003-05-25 17:10:12 +0000621 int ret;
paul718e3742002-12-13 20:15:29 +0000622 struct prefix_ipv6 p;
623 struct route_node *rp;
624 struct ripng_info *rinfo;
625 struct ripng_interface *ri;
626 struct in6_addr *nexthop;
627 u_char oldmetric;
628 int same = 0;
629
630 /* Make prefix structure. */
631 memset (&p, 0, sizeof (struct prefix_ipv6));
632 p.family = AF_INET6;
633 /* p.prefix = rte->addr; */
634 IPV6_ADDR_COPY (&p.prefix, &rte->addr);
635 p.prefixlen = rte->prefixlen;
636
637 /* Make sure mask is applied. */
638 /* XXX We have to check the prefix is valid or not before call
639 apply_mask_ipv6. */
640 apply_mask_ipv6 (&p);
641
642 /* Apply input filters. */
643 ri = ifp->info;
644
hassoa94434b2003-05-25 17:10:12 +0000645 ret = ripng_incoming_filter (&p, ri);
646 if (ret < 0)
647 return;
paul718e3742002-12-13 20:15:29 +0000648
649 /* Modify entry. */
650 if (ri->routemap[RIPNG_FILTER_IN])
651 {
652 int ret;
653 struct ripng_info newinfo;
654
paul41ce9262003-04-19 15:54:03 +0000655 memset (&newinfo, 0, sizeof (struct ripng_info));
hassoa94434b2003-05-25 17:10:12 +0000656 newinfo.type = ZEBRA_ROUTE_RIPNG;
657 newinfo.sub_type = RIPNG_ROUTE_RTE;
658 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
659 newinfo.nexthop = ripng_nexthop->address;
660 else
661 newinfo.nexthop = from->sin6_addr;
662 newinfo.from = from->sin6_addr;
663 newinfo.ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000664 newinfo.metric = rte->metric;
hassoa94434b2003-05-25 17:10:12 +0000665 newinfo.metric_out = rte->metric; /* XXX */
666 newinfo.tag = ntohs(rte->tag); /* XXX */
paul718e3742002-12-13 20:15:29 +0000667
668 ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN],
669 (struct prefix *)&p, RMAP_RIPNG, &newinfo);
670
671 if (ret == RMAP_DENYMATCH)
672 {
673 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +0000674 zlog_debug ("RIPng %s/%d is filtered by route-map in",
hasso59209902005-04-05 14:36:49 +0000675 inet6_ntoa (&p.prefix), p.prefixlen);
paul718e3742002-12-13 20:15:29 +0000676 return;
677 }
678
hassoa94434b2003-05-25 17:10:12 +0000679 /* Get back the object */
680 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) {
681 if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) {
682 /* the nexthop get changed by the routemap */
683 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop))
684 ripng_nexthop->address = newinfo.nexthop;
685 else
686 ripng_nexthop->address = in6addr_any;
687 }
688 } else {
689 if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) {
690 /* the nexthop get changed by the routemap */
691 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) {
692 ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
693 ripng_nexthop->address = newinfo.nexthop;
694 }
695 }
696 }
697 rte->tag = htons(newinfo.tag_out); /* XXX */
698 rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
paul718e3742002-12-13 20:15:29 +0000699 }
700
hassoa94434b2003-05-25 17:10:12 +0000701 /* Once the entry has been validated, update the metric by
702 * adding the cost of the network on wich the message
703 * arrived. If the result is greater than infinity, use infinity
704 * (RFC2453 Sec. 3.9.2)
705 **/
706
707 /* Zebra ripngd can handle offset-list in. */
708 ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric);
709
710 /* If offset-list does not modify the metric use interface's
711 * one. */
712 if (! ret)
713 rte->metric += ifp->metric;
714
715 if (rte->metric > RIPNG_METRIC_INFINITY)
716 rte->metric = RIPNG_METRIC_INFINITY;
717
paul718e3742002-12-13 20:15:29 +0000718 /* Set nexthop pointer. */
719 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
720 nexthop = &ripng_nexthop->address;
721 else
722 nexthop = &from->sin6_addr;
723
724 /* Lookup RIPng routing table. */
725 rp = route_node_get (ripng->table, (struct prefix *) &p);
726
hassoa94434b2003-05-25 17:10:12 +0000727 /* Sanity check */
728 rinfo = rp->info;
729 if (rinfo)
730 {
731 /* Redistributed route check. */
732 if (rinfo->type != ZEBRA_ROUTE_RIPNG
733 && rinfo->metric != RIPNG_METRIC_INFINITY)
734 return;
735
736 /* Local static route. */
737 if (rinfo->type == ZEBRA_ROUTE_RIPNG
738 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
739 (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))
740 && rinfo->metric != RIPNG_METRIC_INFINITY)
741 return;
742 }
743
paul718e3742002-12-13 20:15:29 +0000744 if (rp->info == NULL)
745 {
746 /* Now, check to see whether there is already an explicit route
747 for the destination prefix. If there is no such route, add
748 this route to the routing table, unless the metric is
749 infinity (there is no point in adding a route which
750 unusable). */
751 if (rte->metric != RIPNG_METRIC_INFINITY)
752 {
753 rinfo = ripng_info_new ();
754
755 /* - Setting the destination prefix and length to those in
756 the RTE. */
757 rp->info = rinfo;
758 rinfo->rp = rp;
759
760 /* - Setting the metric to the newly calculated metric (as
761 described above). */
762 rinfo->metric = rte->metric;
763 rinfo->tag = ntohs (rte->tag);
764
765 /* - Set the next hop address to be the address of the router
766 from which the datagram came or the next hop address
767 specified by a next hop RTE. */
768 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
769 IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
770 rinfo->ifindex = ifp->ifindex;
771
772 /* - Initialize the timeout for the route. If the
773 garbage-collection timer is running for this route, stop it. */
774 ripng_timeout_update (rinfo);
775
776 /* - Set the route change flag. */
777 rinfo->flags |= RIPNG_RTF_CHANGED;
778
779 /* - Signal the output process to trigger an update (see section
780 2.5). */
781 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
782
783 /* Finally, route goes into the kernel. */
784 rinfo->type = ZEBRA_ROUTE_RIPNG;
785 rinfo->sub_type = RIPNG_ROUTE_RTE;
786
787 ripng_zebra_ipv6_add (&p, &rinfo->nexthop, rinfo->ifindex);
788 rinfo->flags |= RIPNG_RTF_FIB;
789
790 /* Aggregate check. */
791 ripng_aggregate_increment (rp, rinfo);
792 }
793 }
794 else
795 {
796 rinfo = rp->info;
797
798 /* If there is an existing route, compare the next hop address
799 to the address of the router from which the datagram came.
800 If this datagram is from the same router as the existing
801 route, reinitialize the timeout. */
802 same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr)
803 && (rinfo->ifindex == ifp->ifindex));
804
805 if (same)
806 ripng_timeout_update (rinfo);
807
808 /* Next, compare the metrics. If the datagram is from the same
809 router as the existing route, and the new metric is different
810 than the old one; or, if the new metric is lower than the old
811 one; do the following actions: */
812 if ((same && rinfo->metric != rte->metric) ||
813 rte->metric < rinfo->metric)
814 {
815 /* - Adopt the route from the datagram. That is, put the
816 new metric in, and adjust the next hop address (if
817 necessary). */
818 oldmetric = rinfo->metric;
819 rinfo->metric = rte->metric;
820 rinfo->tag = ntohs (rte->tag);
hassoa94434b2003-05-25 17:10:12 +0000821 IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
822 rinfo->ifindex = ifp->ifindex;
paul718e3742002-12-13 20:15:29 +0000823
hassoa94434b2003-05-25 17:10:12 +0000824 /* Should a new route to this network be established
825 while the garbage-collection timer is running, the
826 new route will replace the one that is about to be
827 deleted. In this case the garbage-collection timer
828 must be cleared. */
829
830 if (oldmetric == RIPNG_METRIC_INFINITY &&
831 rinfo->metric < RIPNG_METRIC_INFINITY)
832 {
833 rinfo->type = ZEBRA_ROUTE_RIPNG;
834 rinfo->sub_type = RIPNG_ROUTE_RTE;
835
836 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
837
838 if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
839 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
840
841 ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);
842 rinfo->flags |= RIPNG_RTF_FIB;
843
844 /* The aggregation counter needs to be updated because
845 the prefixes, which are into the gc, have been
846 removed from the aggregator (see ripng_timout). */
847 ripng_aggregate_increment (rp, rinfo);
848 }
849
850 /* Update nexthop and/or metric value. */
851 if (oldmetric != RIPNG_METRIC_INFINITY)
paul718e3742002-12-13 20:15:29 +0000852 {
853 ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
854 ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);
855 rinfo->flags |= RIPNG_RTF_FIB;
856
hassoa94434b2003-05-25 17:10:12 +0000857 if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
858 IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
paul718e3742002-12-13 20:15:29 +0000859 }
paul718e3742002-12-13 20:15:29 +0000860
861 /* - Set the route change flag and signal the output process
862 to trigger an update. */
863 rinfo->flags |= RIPNG_RTF_CHANGED;
864 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
865
866 /* - If the new metric is infinity, start the deletion
867 process (described above); */
868 if (rinfo->metric == RIPNG_METRIC_INFINITY)
869 {
870 /* If the new metric is infinity, the deletion process
871 begins for the route, which is no longer used for
872 routing packets. Note that the deletion process is
873 started only when the metric is first set to
874 infinity. If the metric was already infinity, then a
875 new deletion process is not started. */
876 if (oldmetric != RIPNG_METRIC_INFINITY)
877 {
878 /* - The garbage-collection timer is set for 120 seconds. */
879 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
880 ripng_garbage_collect, ripng->garbage_time);
881 RIPNG_TIMER_OFF (rinfo->t_timeout);
882
883 /* - The metric for the route is set to 16
884 (infinity). This causes the route to be removed
885 from service.*/
hassoa94434b2003-05-25 17:10:12 +0000886 ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
887 rinfo->flags &= ~RIPNG_RTF_FIB;
888
889 /* Aggregate count decrement. */
890 ripng_aggregate_decrement (rp, rinfo);
891
paul718e3742002-12-13 20:15:29 +0000892 /* - The route change flag is to indicate that this
893 entry has been changed. */
894 /* - The output process is signalled to trigger a
895 response. */
896 ; /* Above processes are already done previously. */
897 }
898 }
899 else
900 {
901 /* otherwise, re-initialize the timeout. */
902 ripng_timeout_update (rinfo);
paul718e3742002-12-13 20:15:29 +0000903 }
904 }
905 /* Unlock tempolary lock of the route. */
906 route_unlock_node (rp);
907 }
908}
909
910/* Add redistributed route to RIPng table. */
911void
912ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p,
hassoa94434b2003-05-25 17:10:12 +0000913 unsigned int ifindex, struct in6_addr *nexthop)
paul718e3742002-12-13 20:15:29 +0000914{
915 struct route_node *rp;
916 struct ripng_info *rinfo;
917
918 /* Redistribute route */
919 if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
920 return;
921 if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
922 return;
hassoa94434b2003-05-25 17:10:12 +0000923#if defined (MUSICA) || defined (LINUX)
924 /* XXX As long as the RIPng redistribution is applied to all the connected
925 * routes, one needs to filter the ::/96 prefixes.
926 * However it could be a wanted case, it will be removed soon.
927 */
928 if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
929 (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
930 return;
931#endif /* MUSICA or LINUX */
paul718e3742002-12-13 20:15:29 +0000932
933 rp = route_node_get (ripng->table, (struct prefix *) p);
934 rinfo = rp->info;
935
936 if (rinfo)
937 {
hassoa94434b2003-05-25 17:10:12 +0000938 if (rinfo->type == ZEBRA_ROUTE_CONNECT
939 && rinfo->sub_type == RIPNG_ROUTE_INTERFACE
940 && rinfo->metric != RIPNG_METRIC_INFINITY) {
941 route_unlock_node (rp);
942 return;
943 }
944
945 /* Manually configured RIPng route check.
946 * They have the precedence on all the other entries.
947 **/
948 if (rinfo->type == ZEBRA_ROUTE_RIPNG
949 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
950 (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) {
951 if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) &&
952 (sub_type != RIPNG_ROUTE_DEFAULT))) {
953 route_unlock_node (rp);
954 return;
955 }
956 }
957
paul718e3742002-12-13 20:15:29 +0000958 RIPNG_TIMER_OFF (rinfo->t_timeout);
959 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
hassoa94434b2003-05-25 17:10:12 +0000960
961 /* Tells the other daemons about the deletion of
962 * this RIPng route
963 **/
964 if (ripng_route_rte (rinfo))
965 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
966 rinfo->metric);
967
968 rp->info = NULL;
969 ripng_info_free (rinfo);
970
paul718e3742002-12-13 20:15:29 +0000971 route_unlock_node (rp);
hassoa94434b2003-05-25 17:10:12 +0000972
paul718e3742002-12-13 20:15:29 +0000973 }
hassoa94434b2003-05-25 17:10:12 +0000974
975 rinfo = ripng_info_new ();
paul718e3742002-12-13 20:15:29 +0000976
977 rinfo->type = type;
978 rinfo->sub_type = sub_type;
979 rinfo->ifindex = ifindex;
980 rinfo->metric = 1;
paul718e3742002-12-13 20:15:29 +0000981 rinfo->rp = rp;
hassoa94434b2003-05-25 17:10:12 +0000982
983 if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop))
984 rinfo->nexthop = *nexthop;
985
986 rinfo->flags |= RIPNG_RTF_FIB;
paul718e3742002-12-13 20:15:29 +0000987 rp->info = rinfo;
hassoa94434b2003-05-25 17:10:12 +0000988
989 /* Aggregate check. */
990 ripng_aggregate_increment (rp, rinfo);
991
992 rinfo->flags |= RIPNG_RTF_CHANGED;
993
994 if (IS_RIPNG_DEBUG_EVENT) {
995 if (!nexthop)
ajsc6106812004-12-08 19:51:16 +0000996 zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
hasso59209902005-04-05 14:36:49 +0000997 inet6_ntoa(&p->prefix), p->prefixlen,
hassoa94434b2003-05-25 17:10:12 +0000998 ifindex2ifname(ifindex));
999 else
ajsc6106812004-12-08 19:51:16 +00001000 zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
hasso59209902005-04-05 14:36:49 +00001001 inet6_ntoa(&p->prefix), p->prefixlen, inet6_ntoa(nexthop),
hassoa94434b2003-05-25 17:10:12 +00001002 ifindex2ifname(ifindex));
1003 }
1004
1005 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +00001006}
1007
1008/* Delete redistributed route to RIPng table. */
1009void
1010ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p,
1011 unsigned int ifindex)
1012{
1013 struct route_node *rp;
1014 struct ripng_info *rinfo;
1015
1016 if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
1017 return;
1018 if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
1019 return;
hassoa94434b2003-05-25 17:10:12 +00001020#if defined (MUSICA) || defined (LINUX)
1021 /* XXX As long as the RIPng redistribution is applied to all the connected
1022 * routes, one needs to filter the ::/96 prefixes.
1023 * However it could be a wanted case, it will be removed soon.
1024 */
1025 if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
1026 (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
1027 return;
1028#endif /* MUSICA or LINUX */
paul718e3742002-12-13 20:15:29 +00001029
1030 rp = route_node_lookup (ripng->table, (struct prefix *) p);
1031
1032 if (rp)
1033 {
1034 rinfo = rp->info;
1035
1036 if (rinfo != NULL
1037 && rinfo->type == type
1038 && rinfo->sub_type == sub_type
1039 && rinfo->ifindex == ifindex)
1040 {
hassoa94434b2003-05-25 17:10:12 +00001041 /* Perform poisoned reverse. */
1042 rinfo->metric = RIPNG_METRIC_INFINITY;
1043 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
1044 ripng_garbage_collect, ripng->garbage_time);
paul718e3742002-12-13 20:15:29 +00001045 RIPNG_TIMER_OFF (rinfo->t_timeout);
hassoa94434b2003-05-25 17:10:12 +00001046
1047 /* Aggregate count decrement. */
1048 ripng_aggregate_decrement (rp, rinfo);
1049
1050 rinfo->flags |= RIPNG_RTF_CHANGED;
paul718e3742002-12-13 20:15:29 +00001051
hassoa94434b2003-05-25 17:10:12 +00001052 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001053 zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
hasso59209902005-04-05 14:36:49 +00001054 inet6_ntoa(&p->prefix), p->prefixlen,
hassoa94434b2003-05-25 17:10:12 +00001055 ifindex2ifname(ifindex));
paul718e3742002-12-13 20:15:29 +00001056
hassoa94434b2003-05-25 17:10:12 +00001057 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +00001058 }
paul718e3742002-12-13 20:15:29 +00001059 }
1060}
1061
1062/* Withdraw redistributed route. */
1063void
1064ripng_redistribute_withdraw (int type)
1065{
1066 struct route_node *rp;
1067 struct ripng_info *rinfo;
1068
hassoa94434b2003-05-25 17:10:12 +00001069 if (!ripng)
1070 return;
1071
paul718e3742002-12-13 20:15:29 +00001072 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1073 if ((rinfo = rp->info) != NULL)
1074 {
hassoa94434b2003-05-25 17:10:12 +00001075 if ((rinfo->type == type)
1076 && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE))
paul718e3742002-12-13 20:15:29 +00001077 {
hassoa94434b2003-05-25 17:10:12 +00001078 /* Perform poisoned reverse. */
1079 rinfo->metric = RIPNG_METRIC_INFINITY;
1080 RIPNG_TIMER_ON (rinfo->t_garbage_collect,
1081 ripng_garbage_collect, ripng->garbage_time);
paul718e3742002-12-13 20:15:29 +00001082 RIPNG_TIMER_OFF (rinfo->t_timeout);
paul718e3742002-12-13 20:15:29 +00001083
hassoa94434b2003-05-25 17:10:12 +00001084 /* Aggregate count decrement. */
1085 ripng_aggregate_decrement (rp, rinfo);
paul718e3742002-12-13 20:15:29 +00001086
hassoa94434b2003-05-25 17:10:12 +00001087 rinfo->flags |= RIPNG_RTF_CHANGED;
1088
1089 if (IS_RIPNG_DEBUG_EVENT) {
1090 struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p;
1091
ajsc6106812004-12-08 19:51:16 +00001092 zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
hasso59209902005-04-05 14:36:49 +00001093 inet6_ntoa(&p->prefix), p->prefixlen,
hassoa94434b2003-05-25 17:10:12 +00001094 ifindex2ifname(rinfo->ifindex));
1095 }
1096
1097 ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
paul718e3742002-12-13 20:15:29 +00001098 }
1099 }
1100}
1101
1102/* RIP routing information. */
1103void
1104ripng_response_process (struct ripng_packet *packet, int size,
1105 struct sockaddr_in6 *from, struct interface *ifp,
1106 int hoplimit)
1107{
1108 caddr_t lim;
1109 struct rte *rte;
1110 struct ripng_nexthop nexthop;
1111
1112 /* RFC2080 2.4.2 Response Messages:
1113 The Response must be ignored if it is not from the RIPng port. */
1114 if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT)
1115 {
1116 zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
hasso59209902005-04-05 14:36:49 +00001117 ntohs (from->sin6_port), inet6_ntoa (&from->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001118 ripng_peer_bad_packet (from);
paul718e3742002-12-13 20:15:29 +00001119 return;
1120 }
1121
1122 /* The datagram's IPv6 source address should be checked to see
1123 whether the datagram is from a valid neighbor; the source of the
1124 datagram must be a link-local address. */
1125 if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr))
1126 {
1127 zlog_warn ("RIPng packet comes from non link local address %s",
hasso59209902005-04-05 14:36:49 +00001128 inet6_ntoa (&from->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001129 ripng_peer_bad_packet (from);
paul718e3742002-12-13 20:15:29 +00001130 return;
1131 }
1132
1133 /* It is also worth checking to see whether the response is from one
1134 of the router's own addresses. Interfaces on broadcast networks
1135 may receive copies of their own multicasts immediately. If a
1136 router processes its own output as new input, confusion is likely,
1137 and such datagrams must be ignored. */
1138 if (ripng_lladdr_check (ifp, &from->sin6_addr))
1139 {
1140 zlog_warn ("RIPng packet comes from my own link local address %s",
hasso59209902005-04-05 14:36:49 +00001141 inet6_ntoa (&from->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001142 ripng_peer_bad_packet (from);
paul718e3742002-12-13 20:15:29 +00001143 return;
1144 }
1145
1146 /* As an additional check, periodic advertisements must have their
1147 hop counts set to 255, and inbound, multicast packets sent from the
1148 RIPng port (i.e. periodic advertisement or triggered update
1149 packets) must be examined to ensure that the hop count is 255. */
1150 if (hoplimit >= 0 && hoplimit != 255)
1151 {
1152 zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
hasso59209902005-04-05 14:36:49 +00001153 hoplimit, inet6_ntoa (&from->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001154 ripng_peer_bad_packet (from);
paul718e3742002-12-13 20:15:29 +00001155 return;
1156 }
1157
hassoa94434b2003-05-25 17:10:12 +00001158 /* Update RIPng peer. */
1159 ripng_peer_update (from, packet->version);
1160
paul718e3742002-12-13 20:15:29 +00001161 /* Reset nexthop. */
1162 memset (&nexthop, 0, sizeof (struct ripng_nexthop));
1163 nexthop.flag = RIPNG_NEXTHOP_UNSPEC;
1164
1165 /* Set RTE pointer. */
1166 rte = packet->rte;
1167
1168 for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++)
1169 {
1170 /* First of all, we have to check this RTE is next hop RTE or
1171 not. Next hop RTE is completely different with normal RTE so
1172 we need special treatment. */
1173 if (rte->metric == RIPNG_METRIC_NEXTHOP)
1174 {
1175 ripng_nexthop_rte (rte, from, &nexthop);
1176 continue;
1177 }
1178
1179 /* RTE information validation. */
1180
1181 /* - is the destination prefix valid (e.g., not a multicast
1182 prefix and not a link-local address) A link-local address
1183 should never be present in an RTE. */
1184 if (IN6_IS_ADDR_MULTICAST (&rte->addr))
1185 {
1186 zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
hasso59209902005-04-05 14:36:49 +00001187 inet6_ntoa (&rte->addr), rte->prefixlen, rte->metric);
hassoa94434b2003-05-25 17:10:12 +00001188 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001189 continue;
1190 }
1191 if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
1192 {
1193 zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
hasso59209902005-04-05 14:36:49 +00001194 inet6_ntoa (&rte->addr), rte->prefixlen, rte->metric);
hassoa94434b2003-05-25 17:10:12 +00001195 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001196 continue;
1197 }
1198 if (IN6_IS_ADDR_LOOPBACK (&rte->addr))
1199 {
1200 zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
hasso59209902005-04-05 14:36:49 +00001201 inet6_ntoa (&rte->addr), rte->prefixlen, rte->metric);
hassoa94434b2003-05-25 17:10:12 +00001202 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001203 continue;
1204 }
1205
1206 /* - is the prefix length valid (i.e., between 0 and 128,
1207 inclusive) */
1208 if (rte->prefixlen > 128)
1209 {
1210 zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
hasso59209902005-04-05 14:36:49 +00001211 inet6_ntoa (&rte->addr), rte->prefixlen,
1212 inet6_ntoa (&from->sin6_addr), ifp->name);
hassoa94434b2003-05-25 17:10:12 +00001213 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001214 continue;
1215 }
1216
1217 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1218 if (! (rte->metric >= 1 && rte->metric <= 16))
1219 {
1220 zlog_warn ("Invalid metric %d from %s%%%s", rte->metric,
hasso59209902005-04-05 14:36:49 +00001221 inet6_ntoa (&from->sin6_addr), ifp->name);
hassoa94434b2003-05-25 17:10:12 +00001222 ripng_peer_bad_route (from);
paul718e3742002-12-13 20:15:29 +00001223 continue;
1224 }
1225
hassoa94434b2003-05-25 17:10:12 +00001226 /* Vincent: XXX Should we compute the direclty reachable nexthop
1227 * for our RIPng network ?
1228 **/
paul718e3742002-12-13 20:15:29 +00001229
1230 /* Routing table updates. */
1231 ripng_route_process (rte, from, &nexthop, ifp);
1232 }
1233}
1234
1235/* Response to request message. */
1236void
1237ripng_request_process (struct ripng_packet *packet,int size,
1238 struct sockaddr_in6 *from, struct interface *ifp)
1239{
1240 caddr_t lim;
1241 struct rte *rte;
1242 struct prefix_ipv6 p;
1243 struct route_node *rp;
1244 struct ripng_info *rinfo;
1245 struct ripng_interface *ri;
1246
hassoa94434b2003-05-25 17:10:12 +00001247 /* Does not reponse to the requests on the loopback interfaces */
1248 if (if_is_loopback (ifp))
1249 return;
1250
paul718e3742002-12-13 20:15:29 +00001251 /* Check RIPng process is enabled on this interface. */
1252 ri = ifp->info;
1253 if (! ri->running)
1254 return;
1255
1256 /* When passive interface is specified, suppress responses */
1257 if (ri->passive)
1258 return;
1259
hassoa94434b2003-05-25 17:10:12 +00001260 /* RIPng peer update. */
1261 ripng_peer_update (from, packet->version);
1262
paul718e3742002-12-13 20:15:29 +00001263 lim = ((caddr_t) packet) + size;
1264 rte = packet->rte;
1265
1266 /* The Request is processed entry by entry. If there are no
1267 entries, no response is given. */
1268 if (lim == (caddr_t) rte)
1269 return;
1270
1271 /* There is one special case. If there is exactly one entry in the
1272 request, and it has a destination prefix of zero, a prefix length
1273 of zero, and a metric of infinity (i.e., 16), then this is a
1274 request to send the entire routing table. In that case, a call
1275 is made to the output process to send the routing table to the
1276 requesting address/port. */
1277 if (lim == ((caddr_t) (rte + 1)) &&
1278 IN6_IS_ADDR_UNSPECIFIED (&rte->addr) &&
1279 rte->prefixlen == 0 &&
1280 rte->metric == RIPNG_METRIC_INFINITY)
1281 {
1282 /* All route with split horizon */
hassoa94434b2003-05-25 17:10:12 +00001283 ripng_output_process (ifp, from, ripng_all_route);
paul718e3742002-12-13 20:15:29 +00001284 }
1285 else
1286 {
1287 /* Except for this special case, processing is quite simple.
1288 Examine the list of RTEs in the Request one by one. For each
1289 entry, look up the destination in the router's routing
1290 database and, if there is a route, put that route's metric in
1291 the metric field of the RTE. If there is no explicit route
1292 to the specified destination, put infinity in the metric
1293 field. Once all the entries have been filled in, change the
1294 command from Request to Response and send the datagram back
1295 to the requestor. */
1296 memset (&p, 0, sizeof (struct prefix_ipv6));
1297 p.family = AF_INET6;
1298
1299 for (; ((caddr_t) rte) < lim; rte++)
1300 {
1301 p.prefix = rte->addr;
1302 p.prefixlen = rte->prefixlen;
1303 apply_mask_ipv6 (&p);
1304
1305 rp = route_node_lookup (ripng->table, (struct prefix *) &p);
1306
1307 if (rp)
1308 {
1309 rinfo = rp->info;
1310 rte->metric = rinfo->metric;
1311 route_unlock_node (rp);
1312 }
1313 else
1314 rte->metric = RIPNG_METRIC_INFINITY;
1315 }
1316 packet->command = RIPNG_RESPONSE;
1317
1318 ripng_send_packet ((caddr_t) packet, size, from, ifp);
1319 }
1320}
1321
1322/* First entry point of reading RIPng packet. */
1323int
1324ripng_read (struct thread *thread)
1325{
1326 int len;
1327 int sock;
1328 struct sockaddr_in6 from;
1329 struct ripng_packet *packet;
1330 unsigned int ifindex;
1331 struct interface *ifp;
1332 int hoplimit = -1;
1333
1334 /* Check ripng is active and alive. */
1335 assert (ripng != NULL);
1336 assert (ripng->sock >= 0);
1337
1338 /* Fetch thread data and set read pointer to empty for event
1339 managing. `sock' sould be same as ripng->sock. */
1340 sock = THREAD_FD (thread);
1341 ripng->t_read = NULL;
1342
1343 /* Add myself to the next event. */
1344 ripng_event (RIPNG_READ, sock);
1345
1346 /* Read RIPng packet. */
1347 len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf),
1348 STREAM_SIZE (ripng->ibuf), &from, &ifindex,
1349 &hoplimit);
1350 if (len < 0)
1351 {
ajs6099b3b2004-11-20 02:06:59 +00001352 zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +00001353 return len;
1354 }
1355
1356 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1357 (4)) must be multiple size of one RTE size (20). */
1358 if (((len - 4) % 20) != 0)
1359 {
1360 zlog_warn ("RIPng invalid packet size %d from %s", len,
hasso59209902005-04-05 14:36:49 +00001361 inet6_ntoa (&from.sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001362 ripng_peer_bad_packet (&from);
paul718e3742002-12-13 20:15:29 +00001363 return 0;
1364 }
1365
1366 packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf);
1367 ifp = if_lookup_by_index (ifindex);
1368
1369 /* RIPng packet received. */
1370 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001371 zlog_debug ("RIPng packet received from %s port %d on %s",
hasso59209902005-04-05 14:36:49 +00001372 inet6_ntoa (&from.sin6_addr), ntohs (from.sin6_port),
paul718e3742002-12-13 20:15:29 +00001373 ifp ? ifp->name : "unknown");
1374
1375 /* Logging before packet checking. */
1376 if (IS_RIPNG_DEBUG_RECV)
1377 ripng_packet_dump (packet, len, "RECV");
1378
1379 /* Packet comes from unknown interface. */
1380 if (ifp == NULL)
1381 {
1382 zlog_warn ("RIPng packet comes from unknown interface %d", ifindex);
1383 return 0;
1384 }
1385
1386 /* Packet version mismatch checking. */
1387 if (packet->version != ripng->version)
1388 {
1389 zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1390 packet->version, ripng->version);
hassoa94434b2003-05-25 17:10:12 +00001391 ripng_peer_bad_packet (&from);
paul718e3742002-12-13 20:15:29 +00001392 return 0;
1393 }
1394
1395 /* Process RIPng packet. */
1396 switch (packet->command)
1397 {
1398 case RIPNG_REQUEST:
1399 ripng_request_process (packet, len, &from, ifp);
1400 break;
1401 case RIPNG_RESPONSE:
1402 ripng_response_process (packet, len, &from, ifp, hoplimit);
1403 break;
1404 default:
1405 zlog_warn ("Invalid RIPng command %d", packet->command);
hassoa94434b2003-05-25 17:10:12 +00001406 ripng_peer_bad_packet (&from);
paul718e3742002-12-13 20:15:29 +00001407 break;
1408 }
1409 return 0;
1410}
1411
1412/* Walk down the RIPng routing table then clear changed flag. */
1413void
1414ripng_clear_changed_flag ()
1415{
1416 struct route_node *rp;
1417 struct ripng_info *rinfo;
1418
1419 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1420 if ((rinfo = rp->info) != NULL)
1421 if (rinfo->flags & RIPNG_RTF_CHANGED)
1422 rinfo->flags &= ~RIPNG_RTF_CHANGED;
1423}
1424
1425/* Regular update of RIPng route. Send all routing formation to RIPng
1426 enabled interface. */
1427int
1428ripng_update (struct thread *t)
1429{
hasso52dc7ee2004-09-23 19:18:23 +00001430 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001431 struct interface *ifp;
1432 struct ripng_interface *ri;
1433
1434 /* Clear update timer thread. */
1435 ripng->t_update = NULL;
1436
1437 /* Logging update event. */
1438 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001439 zlog_debug ("RIPng update timer expired!");
paul718e3742002-12-13 20:15:29 +00001440
1441 /* Supply routes to each interface. */
1442 for (node = listhead (iflist); node; nextnode (node))
1443 {
1444 ifp = getdata (node);
1445 ri = ifp->info;
1446
1447 if (if_is_loopback (ifp) || ! if_is_up (ifp))
1448 continue;
1449
1450 if (! ri->running)
1451 continue;
1452
1453 /* When passive interface is specified, suppress announce to the
1454 interface. */
1455 if (ri->passive)
1456 continue;
1457
1458#if RIPNG_ADVANCED
1459 if (ri->ri_send == RIPNG_SEND_OFF)
1460 {
1461 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001462 zlog (NULL, LOG_DEBUG,
paul718e3742002-12-13 20:15:29 +00001463 "[Event] RIPng send to if %d is suppressed by config",
1464 ifp->ifindex);
1465 continue;
1466 }
1467#endif /* RIPNG_ADVANCED */
1468
hassoa94434b2003-05-25 17:10:12 +00001469 ripng_output_process (ifp, NULL, ripng_all_route);
paul718e3742002-12-13 20:15:29 +00001470 }
1471
1472 /* Triggered updates may be suppressed if a regular update is due by
1473 the time the triggered update would be sent. */
1474 if (ripng->t_triggered_interval)
1475 {
1476 thread_cancel (ripng->t_triggered_interval);
1477 ripng->t_triggered_interval = NULL;
1478 }
1479 ripng->trigger = 0;
1480
1481 /* Reset flush event. */
1482 ripng_event (RIPNG_UPDATE_EVENT, 0);
1483
1484 return 0;
1485}
1486
1487/* Triggered update interval timer. */
1488int
1489ripng_triggered_interval (struct thread *t)
1490{
1491 ripng->t_triggered_interval = NULL;
1492
1493 if (ripng->trigger)
1494 {
1495 ripng->trigger = 0;
1496 ripng_triggered_update (t);
1497 }
1498 return 0;
1499}
1500
1501/* Execute triggered update. */
1502int
1503ripng_triggered_update (struct thread *t)
1504{
hasso52dc7ee2004-09-23 19:18:23 +00001505 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001506 struct interface *ifp;
1507 struct ripng_interface *ri;
1508 int interval;
1509
1510 ripng->t_triggered_update = NULL;
1511
1512 /* Cancel interval timer. */
1513 if (ripng->t_triggered_interval)
1514 {
1515 thread_cancel (ripng->t_triggered_interval);
1516 ripng->t_triggered_interval = NULL;
1517 }
1518 ripng->trigger = 0;
1519
1520 /* Logging triggered update. */
1521 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001522 zlog_debug ("RIPng triggered update!");
paul718e3742002-12-13 20:15:29 +00001523
1524 /* Split Horizon processing is done when generating triggered
1525 updates as well as normal updates (see section 2.6). */
1526 for (node = listhead (iflist); node; nextnode (node))
1527 {
1528 ifp = getdata (node);
1529 ri = ifp->info;
1530
1531 if (if_is_loopback (ifp) || ! if_is_up (ifp))
1532 continue;
1533
1534 if (! ri->running)
1535 continue;
1536
1537 /* When passive interface is specified, suppress announce to the
1538 interface. */
1539 if (ri->passive)
1540 continue;
1541
hassoa94434b2003-05-25 17:10:12 +00001542 ripng_output_process (ifp, NULL, ripng_changed_route);
paul718e3742002-12-13 20:15:29 +00001543 }
1544
1545 /* Once all of the triggered updates have been generated, the route
1546 change flags should be cleared. */
1547 ripng_clear_changed_flag ();
1548
1549 /* After a triggered update is sent, a timer should be set for a
1550 random interval between 1 and 5 seconds. If other changes that
1551 would trigger updates occur before the timer expires, a single
1552 update is triggered when the timer expires. */
1553 interval = (random () % 5) + 1;
1554
1555 ripng->t_triggered_interval =
1556 thread_add_timer (master, ripng_triggered_interval, NULL, interval);
1557
1558 return 0;
1559}
1560
1561/* Write routing table entry to the stream and return next index of
1562 the routing table entry in the stream. */
1563int
1564ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
hassoa94434b2003-05-25 17:10:12 +00001565 struct in6_addr *nexthop, u_int16_t tag, u_char metric)
paul718e3742002-12-13 20:15:29 +00001566{
1567 /* RIPng packet header. */
1568 if (num == 0)
1569 {
1570 stream_putc (s, RIPNG_RESPONSE);
1571 stream_putc (s, RIPNG_V1);
1572 stream_putw (s, 0);
1573 }
1574
1575 /* Write routing table entry. */
hassoa94434b2003-05-25 17:10:12 +00001576 if (!nexthop)
hassoc9e52be2004-09-26 16:09:34 +00001577 stream_write (s, (u_char *) &p->prefix, sizeof (struct in6_addr));
hassoa94434b2003-05-25 17:10:12 +00001578 else
hassoc9e52be2004-09-26 16:09:34 +00001579 stream_write (s, (u_char *) nexthop, sizeof (struct in6_addr));
paul718e3742002-12-13 20:15:29 +00001580 stream_putw (s, tag);
hassoa94434b2003-05-25 17:10:12 +00001581 if (p)
1582 stream_putc (s, p->prefixlen);
1583 else
1584 stream_putc (s, 0);
paul718e3742002-12-13 20:15:29 +00001585 stream_putc (s, metric);
1586
1587 return ++num;
1588}
1589
1590/* Send RESPONSE message to specified destination. */
1591void
1592ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,
hassoa94434b2003-05-25 17:10:12 +00001593 int route_type)
paul718e3742002-12-13 20:15:29 +00001594{
1595 int ret;
paul718e3742002-12-13 20:15:29 +00001596 struct route_node *rp;
1597 struct ripng_info *rinfo;
1598 struct ripng_interface *ri;
1599 struct ripng_aggregate *aggregate;
1600 struct prefix_ipv6 *p;
hassoa94434b2003-05-25 17:10:12 +00001601 struct list * ripng_rte_list;
paul718e3742002-12-13 20:15:29 +00001602
hassoa94434b2003-05-25 17:10:12 +00001603 if (IS_RIPNG_DEBUG_EVENT) {
1604 if (to)
ajsc6106812004-12-08 19:51:16 +00001605 zlog_debug ("RIPng update routes to neighbor %s",
hasso59209902005-04-05 14:36:49 +00001606 inet6_ntoa(&to->sin6_addr));
hassoa94434b2003-05-25 17:10:12 +00001607 else
ajsc6106812004-12-08 19:51:16 +00001608 zlog_debug ("RIPng update routes on interface %s", ifp->name);
hassoa94434b2003-05-25 17:10:12 +00001609 }
paul718e3742002-12-13 20:15:29 +00001610
paul718e3742002-12-13 20:15:29 +00001611 /* Get RIPng interface. */
1612 ri = ifp->info;
hassoa94434b2003-05-25 17:10:12 +00001613
1614 ripng_rte_list = ripng_rte_new();
1615
paul718e3742002-12-13 20:15:29 +00001616 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1617 {
1618 if ((rinfo = rp->info) != NULL && rinfo->suppress == 0)
1619 {
hassoa94434b2003-05-25 17:10:12 +00001620 /* If no route-map are applied, the RTE will be these following
1621 * informations.
1622 */
paul718e3742002-12-13 20:15:29 +00001623 p = (struct prefix_ipv6 *) &rp->p;
hassoa94434b2003-05-25 17:10:12 +00001624 rinfo->metric_out = rinfo->metric;
1625 rinfo->tag_out = rinfo->tag;
1626 memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out));
1627 /* In order to avoid some local loops,
1628 * if the RIPng route has a nexthop via this interface, keep the nexthop,
1629 * otherwise set it to 0. The nexthop should not be propagated
1630 * beyond the local broadcast/multicast area in order
1631 * to avoid an IGP multi-level recursive look-up.
1632 */
1633 if (rinfo->ifindex == ifp->ifindex)
1634 rinfo->nexthop_out = rinfo->nexthop;
1635
1636 /* Apply output filters. */
1637 ret = ripng_outgoing_filter (p, ri);
1638 if (ret < 0)
1639 continue;
paul718e3742002-12-13 20:15:29 +00001640
1641 /* Changed route only output. */
1642 if (route_type == ripng_changed_route &&
1643 (! (rinfo->flags & RIPNG_RTF_CHANGED)))
1644 continue;
1645
1646 /* Split horizon. */
hassoa94434b2003-05-25 17:10:12 +00001647 if (ri->split_horizon == RIPNG_SPLIT_HORIZON)
1648 {
1649 /* We perform split horizon for RIPng routes. */
1650 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
1651 rinfo->ifindex == ifp->ifindex)
1652 continue;
1653 }
paul718e3742002-12-13 20:15:29 +00001654
1655 /* Preparation for route-map. */
hassoa94434b2003-05-25 17:10:12 +00001656 rinfo->metric_set = 0;
1657 /* nexthop_out,
1658 * metric_out
1659 * and tag_out are already initialized.
1660 */
paul718e3742002-12-13 20:15:29 +00001661
hassoa94434b2003-05-25 17:10:12 +00001662 /* Interface route-map */
paul718e3742002-12-13 20:15:29 +00001663 if (ri->routemap[RIPNG_FILTER_OUT])
1664 {
1665 int ret;
paul718e3742002-12-13 20:15:29 +00001666
1667 ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
1668 (struct prefix *) p, RMAP_RIPNG,
hassoa94434b2003-05-25 17:10:12 +00001669 rinfo);
paul718e3742002-12-13 20:15:29 +00001670
1671 if (ret == RMAP_DENYMATCH)
1672 {
1673 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +00001674 zlog_debug ("RIPng %s/%d is filtered by route-map out",
hasso59209902005-04-05 14:36:49 +00001675 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +00001676 continue;
paul718e3742002-12-13 20:15:29 +00001677 }
1678
paul718e3742002-12-13 20:15:29 +00001679 }
1680
hassoa94434b2003-05-25 17:10:12 +00001681 /* Redistribute route-map. */
1682 if (ripng->route_map[rinfo->type].name)
paul718e3742002-12-13 20:15:29 +00001683 {
hassoa94434b2003-05-25 17:10:12 +00001684 int ret;
1685
1686 ret = route_map_apply (ripng->route_map[rinfo->type].map,
1687 (struct prefix *) p, RMAP_RIPNG,
hassobb3a0232003-06-02 10:38:15 +00001688 rinfo);
hassoa94434b2003-05-25 17:10:12 +00001689
1690 if (ret == RMAP_DENYMATCH)
paul718e3742002-12-13 20:15:29 +00001691 {
hassoa94434b2003-05-25 17:10:12 +00001692 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +00001693 zlog_debug ("RIPng %s/%d is filtered by route-map",
hasso59209902005-04-05 14:36:49 +00001694 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +00001695 continue;
paul718e3742002-12-13 20:15:29 +00001696 }
hassoa94434b2003-05-25 17:10:12 +00001697 }
paul718e3742002-12-13 20:15:29 +00001698
hassoa94434b2003-05-25 17:10:12 +00001699 /* When the route-map does not set metric. */
1700 if (! rinfo->metric_set)
1701 {
1702 /* If the redistribute metric is set. */
1703 if (ripng->route_map[rinfo->type].metric_config
1704 && rinfo->metric != RIPNG_METRIC_INFINITY)
paul718e3742002-12-13 20:15:29 +00001705 {
hassoa94434b2003-05-25 17:10:12 +00001706 rinfo->metric_out = ripng->route_map[rinfo->type].metric;
1707 }
1708 else
1709 {
1710 /* If the route is not connected or localy generated
1711 one, use default-metric value */
1712 if (rinfo->type != ZEBRA_ROUTE_RIPNG
1713 && rinfo->type != ZEBRA_ROUTE_CONNECT
paul718e3742002-12-13 20:15:29 +00001714 && rinfo->metric != RIPNG_METRIC_INFINITY)
hassoa94434b2003-05-25 17:10:12 +00001715 rinfo->metric_out = ripng->default_metric;
paul718e3742002-12-13 20:15:29 +00001716 }
1717 }
1718
hassoa94434b2003-05-25 17:10:12 +00001719 /* Apply offset-list */
1720 if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
1721 ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out);
paul718e3742002-12-13 20:15:29 +00001722
hassoa94434b2003-05-25 17:10:12 +00001723 if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
1724 rinfo->metric_out = RIPNG_METRIC_INFINITY;
1725
1726 /* Perform split-horizon with poisoned reverse
1727 * for RIPng routes.
1728 **/
1729 if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) {
1730 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
1731 rinfo->ifindex == ifp->ifindex)
1732 rinfo->metric_out = RIPNG_METRIC_INFINITY;
1733 }
1734
1735 /* Add RTE to the list */
1736 ripng_rte_add(ripng_rte_list, p, rinfo, NULL);
paul718e3742002-12-13 20:15:29 +00001737 }
hassoa94434b2003-05-25 17:10:12 +00001738
1739 /* Process the aggregated RTE entry */
paul718e3742002-12-13 20:15:29 +00001740 if ((aggregate = rp->aggregate) != NULL &&
1741 aggregate->count > 0 &&
1742 aggregate->suppress == 0)
1743 {
hassoa94434b2003-05-25 17:10:12 +00001744 /* If no route-map are applied, the RTE will be these following
1745 * informations.
1746 */
paul718e3742002-12-13 20:15:29 +00001747 p = (struct prefix_ipv6 *) &rp->p;
hassoa94434b2003-05-25 17:10:12 +00001748 aggregate->metric_set = 0;
1749 aggregate->metric_out = aggregate->metric;
1750 aggregate->tag_out = aggregate->tag;
1751 memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out));
paul718e3742002-12-13 20:15:29 +00001752
1753 /* Apply output filters.*/
hassoa94434b2003-05-25 17:10:12 +00001754 ret = ripng_outgoing_filter (p, ri);
1755 if (ret < 0)
1756 continue;
paul718e3742002-12-13 20:15:29 +00001757
hassoa94434b2003-05-25 17:10:12 +00001758 /* Interface route-map */
paul718e3742002-12-13 20:15:29 +00001759 if (ri->routemap[RIPNG_FILTER_OUT])
1760 {
1761 int ret;
1762 struct ripng_info newinfo;
1763
hassoa94434b2003-05-25 17:10:12 +00001764 /* let's cast the aggregate structure to ripng_info */
paul718e3742002-12-13 20:15:29 +00001765 memset (&newinfo, 0, sizeof (struct ripng_info));
hassoa94434b2003-05-25 17:10:12 +00001766 /* the nexthop is :: */
1767 newinfo.metric = aggregate->metric;
1768 newinfo.metric_out = aggregate->metric_out;
1769 newinfo.tag = aggregate->tag;
1770 newinfo.tag_out = aggregate->tag_out;
paul718e3742002-12-13 20:15:29 +00001771
1772 ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
1773 (struct prefix *) p, RMAP_RIPNG,
1774 &newinfo);
1775
1776 if (ret == RMAP_DENYMATCH)
1777 {
1778 if (IS_RIPNG_DEBUG_PACKET)
ajsc6106812004-12-08 19:51:16 +00001779 zlog_debug ("RIPng %s/%d is filtered by route-map out",
hasso59209902005-04-05 14:36:49 +00001780 inet6_ntoa (&p->prefix), p->prefixlen);
hassoa94434b2003-05-25 17:10:12 +00001781 continue;
paul718e3742002-12-13 20:15:29 +00001782 }
1783
hassoa94434b2003-05-25 17:10:12 +00001784 aggregate->metric_out = newinfo.metric_out;
1785 aggregate->tag_out = newinfo.tag_out;
1786 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out))
1787 aggregate->nexthop_out = newinfo.nexthop_out;
paul718e3742002-12-13 20:15:29 +00001788 }
1789
hassoa94434b2003-05-25 17:10:12 +00001790 /* There is no redistribute routemap for the aggregated RTE */
1791
paul718e3742002-12-13 20:15:29 +00001792 /* Changed route only output. */
hassoa94434b2003-05-25 17:10:12 +00001793 /* XXX, vincent, in order to increase time convergence,
1794 * it should be announced if a child has changed.
1795 */
paul718e3742002-12-13 20:15:29 +00001796 if (route_type == ripng_changed_route)
1797 continue;
1798
hassoa94434b2003-05-25 17:10:12 +00001799 /* Apply offset-list */
1800 if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
1801 ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out);
paul718e3742002-12-13 20:15:29 +00001802
hassoa94434b2003-05-25 17:10:12 +00001803 if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
1804 aggregate->metric_out = RIPNG_METRIC_INFINITY;
1805
1806 /* Add RTE to the list */
1807 ripng_rte_add(ripng_rte_list, p, NULL, aggregate);
paul718e3742002-12-13 20:15:29 +00001808 }
1809
1810 }
paul718e3742002-12-13 20:15:29 +00001811
hassoa94434b2003-05-25 17:10:12 +00001812 /* Flush the list */
1813 ripng_rte_send(ripng_rte_list, ifp, to);
1814 ripng_rte_free(ripng_rte_list);
paul718e3742002-12-13 20:15:29 +00001815}
1816
1817/* Create new RIPng instance and set it to global variable. */
1818int
1819ripng_create ()
1820{
1821 /* ripng should be NULL. */
1822 assert (ripng == NULL);
1823
1824 /* Allocaste RIPng instance. */
hassoa94434b2003-05-25 17:10:12 +00001825 ripng = XMALLOC (MTYPE_RIPNG, sizeof (struct ripng));
paul718e3742002-12-13 20:15:29 +00001826 memset (ripng, 0, sizeof (struct ripng));
1827
1828 /* Default version and timer values. */
1829 ripng->version = RIPNG_V1;
1830 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
1831 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
1832 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
1833 ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
1834
1835 /* Make buffer. */
1836 ripng->ibuf = stream_new (RIPNG_MAX_PACKET_SIZE * 5);
1837 ripng->obuf = stream_new (RIPNG_MAX_PACKET_SIZE);
1838
1839 /* Initialize RIPng routig table. */
1840 ripng->table = route_table_init ();
1841 ripng->route = route_table_init ();
1842 ripng->aggregate = route_table_init ();
1843
1844 /* Make socket. */
1845 ripng->sock = ripng_make_socket ();
1846 if (ripng->sock < 0)
1847 return ripng->sock;
1848
1849 /* Threads. */
1850 ripng_event (RIPNG_READ, ripng->sock);
1851 ripng_event (RIPNG_UPDATE_EVENT, 1);
1852
1853 return 0;
1854}
1855
hassoa94434b2003-05-25 17:10:12 +00001856/* Send RIPng request to the interface. */
paul718e3742002-12-13 20:15:29 +00001857int
1858ripng_request (struct interface *ifp)
1859{
1860 struct rte *rte;
1861 struct ripng_packet ripng_packet;
1862
hassoa94434b2003-05-25 17:10:12 +00001863 /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1864 if (if_is_loopback(ifp))
1865 return 0;
1866
1867 /* If interface is down, don't send RIP packet. */
1868 if (! if_is_up (ifp))
1869 return 0;
1870
paul718e3742002-12-13 20:15:29 +00001871 if (IS_RIPNG_DEBUG_EVENT)
ajsc6106812004-12-08 19:51:16 +00001872 zlog_debug ("RIPng send request to %s", ifp->name);
paul718e3742002-12-13 20:15:29 +00001873
1874 memset (&ripng_packet, 0, sizeof (ripng_packet));
1875 ripng_packet.command = RIPNG_REQUEST;
1876 ripng_packet.version = RIPNG_V1;
1877 rte = ripng_packet.rte;
1878 rte->metric = RIPNG_METRIC_INFINITY;
1879
1880 return ripng_send_packet ((caddr_t) &ripng_packet, sizeof (ripng_packet),
1881 NULL, ifp);
1882}
1883
paul718e3742002-12-13 20:15:29 +00001884
1885int
1886ripng_update_jitter (int time)
1887{
1888 return ((rand () % (time + 1)) - (time / 2));
1889}
1890
1891void
1892ripng_event (enum ripng_event event, int sock)
1893{
paul718e3742002-12-13 20:15:29 +00001894 int jitter = 0;
1895
1896 switch (event)
1897 {
1898 case RIPNG_READ:
1899 if (!ripng->t_read)
1900 ripng->t_read = thread_add_read (master, ripng_read, NULL, sock);
1901 break;
1902 case RIPNG_UPDATE_EVENT:
1903 if (ripng->t_update)
1904 {
1905 thread_cancel (ripng->t_update);
1906 ripng->t_update = NULL;
1907 }
1908 /* Update timer jitter. */
1909 jitter = ripng_update_jitter (ripng->update_time);
1910
1911 ripng->t_update =
1912 thread_add_timer (master, ripng_update, NULL,
1913 sock ? 2 : ripng->update_time + jitter);
1914 break;
1915 case RIPNG_TRIGGERED_UPDATE:
1916 if (ripng->t_triggered_interval)
1917 ripng->trigger = 1;
1918 else if (! ripng->t_triggered_update)
1919 ripng->t_triggered_update =
1920 thread_add_event (master, ripng_triggered_update, NULL, 0);
1921 break;
1922 default:
1923 break;
1924 }
1925}
1926
hasso7a1d5832004-10-08 06:32:23 +00001927/* Each route type's strings and default preference.
1928 * FIXME: ISIS? What are these distance values? */
paul718e3742002-12-13 20:15:29 +00001929struct
1930{
1931 int key;
hasso7a1d5832004-10-08 06:32:23 +00001932 const char *str;
1933 const char *str_long;
paul718e3742002-12-13 20:15:29 +00001934 int distance;
1935} route_info[] =
1936{
1937 { ZEBRA_ROUTE_SYSTEM, "X", "system", 10},
1938 { ZEBRA_ROUTE_KERNEL, "K", "kernel", 20},
1939 { ZEBRA_ROUTE_CONNECT, "C", "connected", 30},
1940 { ZEBRA_ROUTE_STATIC, "S", "static", 40},
1941 { ZEBRA_ROUTE_RIP, "R", "rip", 50},
1942 { ZEBRA_ROUTE_RIPNG, "R", "ripng", 50},
1943 { ZEBRA_ROUTE_OSPF, "O", "ospf", 60},
1944 { ZEBRA_ROUTE_OSPF6, "O", "ospf6", 60},
1945 { ZEBRA_ROUTE_BGP, "B", "bgp", 70},
1946};
1947
paul718e3742002-12-13 20:15:29 +00001948/* Print out routes update time. */
1949static void
1950ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo)
1951{
1952 struct timeval timer_now;
1953 time_t clock;
1954 struct tm *tm;
1955#define TIME_BUF 25
1956 char timebuf [TIME_BUF];
1957 struct thread *thread;
1958
1959 gettimeofday (&timer_now, NULL);
1960
1961 if ((thread = rinfo->t_timeout) != NULL)
1962 {
1963 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
1964 tm = gmtime (&clock);
1965 strftime (timebuf, TIME_BUF, "%M:%S", tm);
1966 vty_out (vty, "%5s", timebuf);
1967 }
1968 else if ((thread = rinfo->t_garbage_collect) != NULL)
1969 {
1970 clock = thread->u.sands.tv_sec - timer_now.tv_sec;
1971 tm = gmtime (&clock);
1972 strftime (timebuf, TIME_BUF, "%M:%S", tm);
1973 vty_out (vty, "%5s", timebuf);
1974 }
1975}
1976
hassoa94434b2003-05-25 17:10:12 +00001977char *
1978ripng_route_subtype_print (struct ripng_info *rinfo)
1979{
1980 static char str[3];
1981 memset(str, 0, 3);
1982
1983 if (rinfo->suppress)
1984 strcat(str, "S");
1985
1986 switch (rinfo->sub_type)
1987 {
1988 case RIPNG_ROUTE_RTE:
1989 strcat(str, "n");
1990 break;
1991 case RIPNG_ROUTE_STATIC:
1992 strcat(str, "s");
1993 break;
1994 case RIPNG_ROUTE_DEFAULT:
1995 strcat(str, "d");
1996 break;
1997 case RIPNG_ROUTE_REDISTRIBUTE:
1998 strcat(str, "r");
1999 break;
2000 case RIPNG_ROUTE_INTERFACE:
2001 strcat(str, "i");
2002 break;
2003 default:
2004 strcat(str, "?");
2005 break;
2006 }
2007
2008 return str;
2009}
2010
paul718e3742002-12-13 20:15:29 +00002011DEFUN (show_ipv6_ripng,
2012 show_ipv6_ripng_cmd,
2013 "show ipv6 ripng",
2014 SHOW_STR
hasso8d0f15f2004-09-11 16:33:28 +00002015 IPV6_STR
paul718e3742002-12-13 20:15:29 +00002016 "Show RIPng routes\n")
2017{
2018 struct route_node *rp;
2019 struct ripng_info *rinfo;
2020 struct ripng_aggregate *aggregate;
2021 struct prefix_ipv6 *p;
2022 int len;
2023
hassoa94434b2003-05-25 17:10:12 +00002024 if (! ripng)
2025 return CMD_SUCCESS;
2026
paul718e3742002-12-13 20:15:29 +00002027 /* Header of display. */
hassoa94434b2003-05-25 17:10:12 +00002028 vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2029 "Sub-codes:%s"
2030 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2031 " (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2032 " Network Next Hop Via Metric Tag Time%s",
2033 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
paul718e3742002-12-13 20:15:29 +00002034 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
2035
2036 for (rp = route_top (ripng->table); rp; rp = route_next (rp))
2037 {
2038 if ((aggregate = rp->aggregate) != NULL)
2039 {
2040 p = (struct prefix_ipv6 *) &rp->p;
2041
2042#ifdef DEBUG
hassoa94434b2003-05-25 17:10:12 +00002043 len = vty_out (vty, "R(a) %d/%d %s/%d ",
paul718e3742002-12-13 20:15:29 +00002044 aggregate->count, aggregate->suppress,
hasso59209902005-04-05 14:36:49 +00002045 inet6_ntoa (&p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +00002046#else
hassoa94434b2003-05-25 17:10:12 +00002047 len = vty_out (vty, "R(a) %s/%d ",
hasso59209902005-04-05 14:36:49 +00002048 inet6_ntoa (&p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +00002049#endif /* DEBUG */
hassoa94434b2003-05-25 17:10:12 +00002050 vty_out (vty, "%s", VTY_NEWLINE);
2051 vty_out (vty, "%*s", 18, " ");
paul718e3742002-12-13 20:15:29 +00002052
hassoa94434b2003-05-25 17:10:12 +00002053 vty_out (vty, "%*s", 28, " ");
2054 vty_out (vty, "self %2d %3d%s", aggregate->metric,
paul718e3742002-12-13 20:15:29 +00002055 aggregate->tag,
2056 VTY_NEWLINE);
2057 }
2058
2059 if ((rinfo = rp->info) != NULL)
2060 {
2061 p = (struct prefix_ipv6 *) &rp->p;
2062
2063#ifdef DEBUG
hassoa94434b2003-05-25 17:10:12 +00002064 len = vty_out (vty, "%s(%s) 0/%d %s/%d ",
paul718e3742002-12-13 20:15:29 +00002065 route_info[rinfo->type].str,
hassoa94434b2003-05-25 17:10:12 +00002066 ripng_route_subtype_print(rinfo),
paul718e3742002-12-13 20:15:29 +00002067 rinfo->suppress,
hasso59209902005-04-05 14:36:49 +00002068 inet6_ntoa (&p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +00002069#else
hassoa94434b2003-05-25 17:10:12 +00002070 len = vty_out (vty, "%s(%s) %s/%d ",
paul718e3742002-12-13 20:15:29 +00002071 route_info[rinfo->type].str,
hassoa94434b2003-05-25 17:10:12 +00002072 ripng_route_subtype_print(rinfo),
hasso59209902005-04-05 14:36:49 +00002073 inet6_ntoa (&p->prefix), p->prefixlen);
paul718e3742002-12-13 20:15:29 +00002074#endif /* DEBUG */
hassoa94434b2003-05-25 17:10:12 +00002075 vty_out (vty, "%s", VTY_NEWLINE);
2076 vty_out (vty, "%*s", 18, " ");
hasso59209902005-04-05 14:36:49 +00002077 len = vty_out (vty, "%s", inet6_ntoa (&rinfo->nexthop));
paul718e3742002-12-13 20:15:29 +00002078
hassoa94434b2003-05-25 17:10:12 +00002079 len = 28 - len;
2080 if (len > 0)
2081 len = vty_out (vty, "%*s", len, " ");
2082
2083 /* from */
2084 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2085 (rinfo->sub_type == RIPNG_ROUTE_RTE))
2086 {
2087 len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex));
2088 } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
2089 {
2090 len = vty_out (vty, "kill");
2091 } else
2092 len = vty_out (vty, "self");
2093
2094 len = 9 - len;
paul718e3742002-12-13 20:15:29 +00002095 if (len > 0)
2096 vty_out (vty, "%*s", len, " ");
2097
hassoa94434b2003-05-25 17:10:12 +00002098 vty_out (vty, " %2d %3d ",
2099 rinfo->metric, rinfo->tag);
paul718e3742002-12-13 20:15:29 +00002100
hassoa94434b2003-05-25 17:10:12 +00002101 /* time */
2102 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2103 (rinfo->sub_type == RIPNG_ROUTE_RTE))
2104 {
2105 /* RTE from remote RIP routers */
paul718e3742002-12-13 20:15:29 +00002106 ripng_vty_out_uptime (vty, rinfo);
hassoa94434b2003-05-25 17:10:12 +00002107 } else if (rinfo->metric == RIPNG_METRIC_INFINITY)
2108 {
2109 /* poisonous reversed routes (gc) */
2110 ripng_vty_out_uptime (vty, rinfo);
2111 }
paul718e3742002-12-13 20:15:29 +00002112
2113 vty_out (vty, "%s", VTY_NEWLINE);
2114 }
2115 }
2116
2117 return CMD_SUCCESS;
2118}
2119
hassoa94434b2003-05-25 17:10:12 +00002120/* Return next event time. */
2121static int
2122ripng_next_thread_timer (struct thread *thread)
2123{
2124 struct timeval timer_now;
2125
2126 gettimeofday (&timer_now, NULL);
2127
2128 return thread->u.sands.tv_sec - timer_now.tv_sec;
2129}
2130
2131DEFUN (show_ipv6_ripng_status,
2132 show_ipv6_ripng_status_cmd,
2133 "show ipv6 ripng status",
2134 SHOW_STR
hasso8d0f15f2004-09-11 16:33:28 +00002135 IPV6_STR
hassoa94434b2003-05-25 17:10:12 +00002136 "Show RIPng routes\n"
2137 "IPv6 routing protocol process parameters and statistics\n")
2138{
hasso52dc7ee2004-09-23 19:18:23 +00002139 struct listnode *node;
hassoa94434b2003-05-25 17:10:12 +00002140 int ripng_network_write (struct vty *, int);
2141 void ripng_redistribute_write (struct vty *, int);
2142
2143 if (! ripng)
2144 return CMD_SUCCESS;
2145
2146 vty_out (vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE);
2147 vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
2148 ripng->update_time);
2149 vty_out (vty, " next due in %d seconds%s",
2150 ripng_next_thread_timer (ripng->t_update),
2151 VTY_NEWLINE);
2152 vty_out (vty, " Timeout after %ld seconds,", ripng->timeout_time);
2153 vty_out (vty, " garbage collect after %ld seconds%s", ripng->garbage_time,
2154 VTY_NEWLINE);
2155
2156 /* Filtering status show. */
2157 config_show_distribute (vty);
2158
2159 /* Default metric information. */
2160 vty_out (vty, " Default redistribution metric is %d%s",
2161 ripng->default_metric, VTY_NEWLINE);
2162
2163 /* Redistribute information. */
2164 vty_out (vty, " Redistributing:");
2165 ripng_redistribute_write (vty, 0);
2166 vty_out (vty, "%s", VTY_NEWLINE);
2167
2168 vty_out (vty, " Default version control: send version %d,", ripng->version);
2169 vty_out (vty, " receive version %d %s", ripng->version,
2170 VTY_NEWLINE);
2171
2172 vty_out (vty, " Interface Send Recv%s", VTY_NEWLINE);
2173
2174 for (node = listhead (iflist); node; node = nextnode (node))
2175 {
2176 struct ripng_interface *ri;
2177 struct interface *ifp;
2178
2179 ifp = getdata (node);
2180 ri = ifp->info;
2181
2182 if (ri->enable_network || ri->enable_interface)
2183 {
2184
2185 vty_out (vty, " %-17s%-3d %-3d%s", ifp->name,
2186 ripng->version,
2187 ripng->version,
2188 VTY_NEWLINE);
2189 }
2190 }
2191
2192 vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
2193 ripng_network_write (vty, 0);
2194
2195 vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
2196 vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
2197 ripng_peer_display (vty);
2198
2199 return CMD_SUCCESS;
2200}
2201
paul718e3742002-12-13 20:15:29 +00002202DEFUN (router_ripng,
2203 router_ripng_cmd,
2204 "router ripng",
2205 "Enable a routing process\n"
2206 "Make RIPng instance command\n")
2207{
2208 int ret;
2209
2210 vty->node = RIPNG_NODE;
2211
2212 if (!ripng)
2213 {
2214 ret = ripng_create ();
2215
2216 /* Notice to user we couldn't create RIPng. */
2217 if (ret < 0)
2218 {
2219 zlog_warn ("can't create RIPng");
2220 return CMD_WARNING;
2221 }
2222 }
2223
2224 return CMD_SUCCESS;
2225}
2226
hassoa94434b2003-05-25 17:10:12 +00002227DEFUN (no_router_ripng,
2228 no_router_ripng_cmd,
2229 "no router ripng",
2230 NO_STR
2231 "Enable a routing process\n"
2232 "Make RIPng instance command\n")
2233{
2234 if(ripng)
2235 ripng_clean();
2236 return CMD_SUCCESS;
2237}
2238
paul718e3742002-12-13 20:15:29 +00002239DEFUN (ripng_route,
2240 ripng_route_cmd,
2241 "route IPV6ADDR",
2242 "Static route setup\n"
2243 "Set static RIPng route announcement\n")
2244{
2245 int ret;
2246 struct prefix_ipv6 p;
2247 struct route_node *rp;
2248
2249 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2250 if (ret <= 0)
2251 {
2252 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2253 return CMD_WARNING;
2254 }
2255 apply_mask_ipv6 (&p);
2256
2257 rp = route_node_get (ripng->route, (struct prefix *) &p);
2258 if (rp->info)
2259 {
2260 vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2261 route_unlock_node (rp);
2262 return CMD_WARNING;
2263 }
2264 rp->info = (void *)1;
2265
hassoa94434b2003-05-25 17:10:12 +00002266 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL);
paul718e3742002-12-13 20:15:29 +00002267
2268 return CMD_SUCCESS;
2269}
2270
2271DEFUN (no_ripng_route,
2272 no_ripng_route_cmd,
2273 "no route IPV6ADDR",
2274 NO_STR
2275 "Static route setup\n"
2276 "Delete static RIPng route announcement\n")
2277{
2278 int ret;
2279 struct prefix_ipv6 p;
2280 struct route_node *rp;
2281
2282 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2283 if (ret <= 0)
2284 {
2285 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2286 return CMD_WARNING;
2287 }
2288 apply_mask_ipv6 (&p);
2289
2290 rp = route_node_lookup (ripng->route, (struct prefix *) &p);
2291 if (! rp)
2292 {
2293 vty_out (vty, "Can't find static route.%s", VTY_NEWLINE);
2294 return CMD_WARNING;
2295 }
2296
2297 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
2298 route_unlock_node (rp);
2299
2300 rp->info = NULL;
2301 route_unlock_node (rp);
2302
2303 return CMD_SUCCESS;
2304}
2305
2306DEFUN (ripng_aggregate_address,
2307 ripng_aggregate_address_cmd,
2308 "aggregate-address X:X::X:X/M",
2309 "Set aggregate RIPng route announcement\n"
2310 "Aggregate network\n")
2311{
2312 int ret;
2313 struct prefix p;
2314 struct route_node *node;
2315
2316 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2317 if (ret <= 0)
2318 {
2319 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2320 return CMD_WARNING;
2321 }
2322
2323 /* Check aggregate alredy exist or not. */
2324 node = route_node_get (ripng->aggregate, &p);
2325 if (node->info)
2326 {
2327 vty_out (vty, "There is already same aggregate route.%s", VTY_NEWLINE);
2328 route_unlock_node (node);
2329 return CMD_WARNING;
2330 }
2331 node->info = (void *)1;
2332
2333 ripng_aggregate_add (&p);
2334
2335 return CMD_SUCCESS;
2336}
2337
2338DEFUN (no_ripng_aggregate_address,
2339 no_ripng_aggregate_address_cmd,
2340 "no aggregate-address X:X::X:X/M",
2341 NO_STR
2342 "Delete aggregate RIPng route announcement\n"
2343 "Aggregate network")
2344{
2345 int ret;
2346 struct prefix p;
2347 struct route_node *rn;
2348
2349 ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &p);
2350 if (ret <= 0)
2351 {
2352 vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2353 return CMD_WARNING;
2354 }
2355
2356 rn = route_node_lookup (ripng->aggregate, &p);
2357 if (! rn)
2358 {
2359 vty_out (vty, "Can't find aggregate route.%s", VTY_NEWLINE);
2360 return CMD_WARNING;
2361 }
2362 route_unlock_node (rn);
2363 rn->info = NULL;
2364 route_unlock_node (rn);
2365
2366 ripng_aggregate_delete (&p);
2367
2368 return CMD_SUCCESS;
2369}
2370
2371DEFUN (ripng_default_metric,
2372 ripng_default_metric_cmd,
2373 "default-metric <1-16>",
2374 "Set a metric of redistribute routes\n"
2375 "Default metric\n")
2376{
2377 if (ripng)
2378 {
2379 ripng->default_metric = atoi (argv[0]);
2380 }
2381 return CMD_SUCCESS;
2382}
2383
2384DEFUN (no_ripng_default_metric,
2385 no_ripng_default_metric_cmd,
2386 "no default-metric",
2387 NO_STR
2388 "Set a metric of redistribute routes\n"
2389 "Default metric\n")
2390{
2391 if (ripng)
2392 {
2393 ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
2394 }
2395 return CMD_SUCCESS;
2396}
2397
2398ALIAS (no_ripng_default_metric,
2399 no_ripng_default_metric_val_cmd,
2400 "no default-metric <1-16>",
2401 NO_STR
2402 "Set a metric of redistribute routes\n"
2403 "Default metric\n")
2404
2405#if 0
2406/* RIPng update timer setup. */
2407DEFUN (ripng_update_timer,
2408 ripng_update_timer_cmd,
2409 "update-timer SECOND",
2410 "Set RIPng update timer in seconds\n"
2411 "Seconds\n")
2412{
2413 unsigned long update;
2414 char *endptr = NULL;
2415
2416 update = strtoul (argv[0], &endptr, 10);
2417 if (update == ULONG_MAX || *endptr != '\0')
2418 {
2419 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2420 return CMD_WARNING;
2421 }
2422
2423 ripng->update_time = update;
2424
2425 ripng_event (RIPNG_UPDATE_EVENT, 0);
2426 return CMD_SUCCESS;
2427}
2428
2429DEFUN (no_ripng_update_timer,
2430 no_ripng_update_timer_cmd,
2431 "no update-timer SECOND",
2432 NO_STR
2433 "Unset RIPng update timer in seconds\n"
2434 "Seconds\n")
2435{
2436 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2437 ripng_event (RIPNG_UPDATE_EVENT, 0);
2438 return CMD_SUCCESS;
2439}
2440
2441/* RIPng timeout timer setup. */
2442DEFUN (ripng_timeout_timer,
2443 ripng_timeout_timer_cmd,
2444 "timeout-timer SECOND",
2445 "Set RIPng timeout timer in seconds\n"
2446 "Seconds\n")
2447{
2448 unsigned long timeout;
2449 char *endptr = NULL;
2450
2451 timeout = strtoul (argv[0], &endptr, 10);
2452 if (timeout == ULONG_MAX || *endptr != '\0')
2453 {
2454 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2455 return CMD_WARNING;
2456 }
2457
2458 ripng->timeout_time = timeout;
2459
2460 return CMD_SUCCESS;
2461}
2462
2463DEFUN (no_ripng_timeout_timer,
2464 no_ripng_timeout_timer_cmd,
2465 "no timeout-timer SECOND",
2466 NO_STR
2467 "Unset RIPng timeout timer in seconds\n"
2468 "Seconds\n")
2469{
2470 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2471 return CMD_SUCCESS;
2472}
2473
2474/* RIPng garbage timer setup. */
2475DEFUN (ripng_garbage_timer,
2476 ripng_garbage_timer_cmd,
2477 "garbage-timer SECOND",
2478 "Set RIPng garbage timer in seconds\n"
2479 "Seconds\n")
2480{
2481 unsigned long garbage;
2482 char *endptr = NULL;
2483
2484 garbage = strtoul (argv[0], &endptr, 10);
2485 if (garbage == ULONG_MAX || *endptr != '\0')
2486 {
2487 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2488 return CMD_WARNING;
2489 }
2490
2491 ripng->garbage_time = garbage;
2492
2493 return CMD_SUCCESS;
2494}
2495
2496DEFUN (no_ripng_garbage_timer,
2497 no_ripng_garbage_timer_cmd,
2498 "no garbage-timer SECOND",
2499 NO_STR
2500 "Unset RIPng garbage timer in seconds\n"
2501 "Seconds\n")
2502{
2503 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2504 return CMD_SUCCESS;
2505}
2506#endif /* 0 */
2507
2508DEFUN (ripng_timers,
2509 ripng_timers_cmd,
2510 "timers basic <0-65535> <0-65535> <0-65535>",
2511 "RIPng timers setup\n"
2512 "Basic timer\n"
2513 "Routing table update timer value in second. Default is 30.\n"
2514 "Routing information timeout timer. Default is 180.\n"
2515 "Garbage collection timer. Default is 120.\n")
2516{
2517 unsigned long update;
2518 unsigned long timeout;
2519 unsigned long garbage;
2520 char *endptr = NULL;
2521
2522 update = strtoul (argv[0], &endptr, 10);
2523 if (update == ULONG_MAX || *endptr != '\0')
2524 {
2525 vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2526 return CMD_WARNING;
2527 }
2528
2529 timeout = strtoul (argv[1], &endptr, 10);
2530 if (timeout == ULONG_MAX || *endptr != '\0')
2531 {
2532 vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2533 return CMD_WARNING;
2534 }
2535
2536 garbage = strtoul (argv[2], &endptr, 10);
2537 if (garbage == ULONG_MAX || *endptr != '\0')
2538 {
2539 vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2540 return CMD_WARNING;
2541 }
2542
2543 /* Set each timer value. */
2544 ripng->update_time = update;
2545 ripng->timeout_time = timeout;
2546 ripng->garbage_time = garbage;
2547
2548 /* Reset update timer thread. */
2549 ripng_event (RIPNG_UPDATE_EVENT, 0);
2550
2551 return CMD_SUCCESS;
2552}
2553
2554DEFUN (no_ripng_timers,
2555 no_ripng_timers_cmd,
2556 "no timers basic",
2557 NO_STR
2558 "RIPng timers setup\n"
2559 "Basic timer\n")
2560{
2561 /* Set each timer value to the default. */
2562 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2563 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2564 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2565
2566 /* Reset update timer thread. */
2567 ripng_event (RIPNG_UPDATE_EVENT, 0);
2568
2569 return CMD_SUCCESS;
2570}
2571
hassoa94434b2003-05-25 17:10:12 +00002572ALIAS (no_ripng_timers,
2573 no_ripng_timers_val_cmd,
2574 "no timers basic <0-65535> <0-65535> <0-65535>",
2575 NO_STR
2576 "RIPng timers setup\n"
2577 "Basic timer\n"
2578 "Routing table update timer value in second. Default is 30.\n"
2579 "Routing information timeout timer. Default is 180.\n"
2580 "Garbage collection timer. Default is 120.\n")
paul718e3742002-12-13 20:15:29 +00002581
2582DEFUN (show_ipv6_protocols, show_ipv6_protocols_cmd,
2583 "show ipv6 protocols",
2584 SHOW_STR
hasso8d0f15f2004-09-11 16:33:28 +00002585 IPV6_STR
paul718e3742002-12-13 20:15:29 +00002586 "Routing protocol information")
2587{
2588 if (! ripng)
2589 return CMD_SUCCESS;
2590
2591 vty_out (vty, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE);
2592
2593 vty_out (vty, "Sending updates every %ld seconds, next due in %d seconds%s",
2594 ripng->update_time, 0,
2595 VTY_NEWLINE);
2596
2597 vty_out (vty, "Timerout after %ld seconds, garbage correct %ld%s",
2598 ripng->timeout_time,
2599 ripng->garbage_time,
2600 VTY_NEWLINE);
2601
2602 vty_out (vty, "Outgoing update filter list for all interfaces is not set");
2603 vty_out (vty, "Incoming update filter list for all interfaces is not set");
2604
2605 return CMD_SUCCESS;
2606}
2607
2608/* Please be carefull to use this command. */
paula2c62832003-04-23 17:01:31 +00002609DEFUN (ripng_default_information_originate,
2610 ripng_default_information_originate_cmd,
paul718e3742002-12-13 20:15:29 +00002611 "default-information originate",
2612 "Default route information\n"
2613 "Distribute default route\n")
2614{
2615 struct prefix_ipv6 p;
2616
hassoa94434b2003-05-25 17:10:12 +00002617 if (! ripng ->default_information) {
2618 ripng->default_information = 1;
paul718e3742002-12-13 20:15:29 +00002619
hassoa94434b2003-05-25 17:10:12 +00002620 str2prefix_ipv6 ("::/0", &p);
2621 ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL);
2622 }
paul718e3742002-12-13 20:15:29 +00002623
2624 return CMD_SUCCESS;
2625}
2626
paula2c62832003-04-23 17:01:31 +00002627DEFUN (no_ripng_default_information_originate,
2628 no_ripng_default_information_originate_cmd,
paul718e3742002-12-13 20:15:29 +00002629 "no default-information originate",
2630 NO_STR
2631 "Default route information\n"
2632 "Distribute default route\n")
2633{
2634 struct prefix_ipv6 p;
2635
hassoa94434b2003-05-25 17:10:12 +00002636 if (ripng->default_information) {
2637 ripng->default_information = 0;
paul718e3742002-12-13 20:15:29 +00002638
hassoa94434b2003-05-25 17:10:12 +00002639 str2prefix_ipv6 ("::/0", &p);
2640 ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0);
2641 }
paul718e3742002-12-13 20:15:29 +00002642
2643 return CMD_SUCCESS;
2644}
2645
2646/* RIPng configuration write function. */
2647int
2648ripng_config_write (struct vty *vty)
2649{
hassoa94434b2003-05-25 17:10:12 +00002650 int ripng_network_write (struct vty *, int);
2651 void ripng_redistribute_write (struct vty *, int);
paul718e3742002-12-13 20:15:29 +00002652 int write = 0;
2653 struct route_node *rp;
2654
2655 if (ripng)
2656 {
2657
2658 /* RIPng router. */
2659 vty_out (vty, "router ripng%s", VTY_NEWLINE);
2660
2661 if (ripng->default_information)
2662 vty_out (vty, " default-information originate%s", VTY_NEWLINE);
2663
hassoa94434b2003-05-25 17:10:12 +00002664 ripng_network_write (vty, 1);
paul718e3742002-12-13 20:15:29 +00002665
2666 /* RIPng default metric configuration */
2667 if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT)
2668 vty_out (vty, " default-metric %d%s",
2669 ripng->default_metric, VTY_NEWLINE);
2670
hassoa94434b2003-05-25 17:10:12 +00002671 ripng_redistribute_write (vty, 1);
2672
2673 /* RIP offset-list configuration. */
2674 config_write_ripng_offset_list (vty);
paul718e3742002-12-13 20:15:29 +00002675
2676 /* RIPng aggregate routes. */
2677 for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
2678 if (rp->info != NULL)
2679 vty_out (vty, " aggregate-address %s/%d%s",
hasso59209902005-04-05 14:36:49 +00002680 inet6_ntoa (&rp->p.u.prefix6),
paul718e3742002-12-13 20:15:29 +00002681 rp->p.prefixlen,
2682
2683 VTY_NEWLINE);
2684
2685 /* RIPng static routes. */
2686 for (rp = route_top (ripng->route); rp; rp = route_next (rp))
2687 if (rp->info != NULL)
hasso59209902005-04-05 14:36:49 +00002688 vty_out (vty, " route %s/%d%s", inet6_ntoa (&rp->p.u.prefix6),
paul718e3742002-12-13 20:15:29 +00002689 rp->p.prefixlen,
2690 VTY_NEWLINE);
2691
2692 /* RIPng timers configuration. */
2693 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT ||
2694 ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT ||
2695 ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
2696 {
2697 vty_out (vty, " timers basic %ld %ld %ld%s",
2698 ripng->update_time,
2699 ripng->timeout_time,
2700 ripng->garbage_time,
2701 VTY_NEWLINE);
2702 }
2703#if 0
2704 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT)
2705 vty_out (vty, " update-timer %d%s", ripng->update_time,
2706 VTY_NEWLINE);
2707 if (ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT)
2708 vty_out (vty, " timeout-timer %d%s", ripng->timeout_time,
2709 VTY_NEWLINE);
2710 if (ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
2711 vty_out (vty, " garbage-timer %d%s", ripng->garbage_time,
2712 VTY_NEWLINE);
2713#endif /* 0 */
2714
2715 write += config_write_distribute (vty);
2716
2717 write += config_write_if_rmap (vty);
2718
2719 write++;
2720 }
2721 return write;
2722}
2723
2724/* RIPng node structure. */
2725struct cmd_node cmd_ripng_node =
2726{
2727 RIPNG_NODE,
2728 "%s(config-router)# ",
2729 1,
2730};
2731
2732void
2733ripng_distribute_update (struct distribute *dist)
2734{
2735 struct interface *ifp;
2736 struct ripng_interface *ri;
2737 struct access_list *alist;
2738 struct prefix_list *plist;
2739
2740 if (! dist->ifname)
2741 return;
2742
2743 ifp = if_lookup_by_name (dist->ifname);
2744 if (ifp == NULL)
2745 return;
2746
2747 ri = ifp->info;
2748
2749 if (dist->list[DISTRIBUTE_IN])
2750 {
2751 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
2752 if (alist)
2753 ri->list[RIPNG_FILTER_IN] = alist;
2754 else
2755 ri->list[RIPNG_FILTER_IN] = NULL;
2756 }
2757 else
2758 ri->list[RIPNG_FILTER_IN] = NULL;
2759
2760 if (dist->list[DISTRIBUTE_OUT])
2761 {
2762 alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
2763 if (alist)
2764 ri->list[RIPNG_FILTER_OUT] = alist;
2765 else
2766 ri->list[RIPNG_FILTER_OUT] = NULL;
2767 }
2768 else
2769 ri->list[RIPNG_FILTER_OUT] = NULL;
2770
2771 if (dist->prefix[DISTRIBUTE_IN])
2772 {
2773 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
2774 if (plist)
2775 ri->prefix[RIPNG_FILTER_IN] = plist;
2776 else
2777 ri->prefix[RIPNG_FILTER_IN] = NULL;
2778 }
2779 else
2780 ri->prefix[RIPNG_FILTER_IN] = NULL;
2781
2782 if (dist->prefix[DISTRIBUTE_OUT])
2783 {
2784 plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
2785 if (plist)
2786 ri->prefix[RIPNG_FILTER_OUT] = plist;
2787 else
2788 ri->prefix[RIPNG_FILTER_OUT] = NULL;
2789 }
2790 else
2791 ri->prefix[RIPNG_FILTER_OUT] = NULL;
2792}
hassoa94434b2003-05-25 17:10:12 +00002793
paul718e3742002-12-13 20:15:29 +00002794void
2795ripng_distribute_update_interface (struct interface *ifp)
2796{
2797 struct distribute *dist;
2798
2799 dist = distribute_lookup (ifp->name);
2800 if (dist)
2801 ripng_distribute_update (dist);
2802}
2803
2804/* Update all interface's distribute list. */
2805void
hassoc9e52be2004-09-26 16:09:34 +00002806ripng_distribute_update_all (struct prefix_list *notused)
paul718e3742002-12-13 20:15:29 +00002807{
2808 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00002809 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002810
2811 for (node = listhead (iflist); node; nextnode (node))
2812 {
2813 ifp = getdata (node);
2814 ripng_distribute_update_interface (ifp);
2815 }
2816}
hassoc9e52be2004-09-26 16:09:34 +00002817
2818void
2819ripng_distribute_update_all_wrapper (struct access_list *notused)
2820{
2821 ripng_distribute_update_all(NULL);
2822}
hassoa94434b2003-05-25 17:10:12 +00002823
2824/* delete all the added ripng routes. */
2825void
2826ripng_clean()
2827{
2828 int i;
2829 struct route_node *rp;
2830 struct ripng_info *rinfo;
2831
2832 if (ripng) {
2833 /* Clear RIPng routes */
2834 for (rp = route_top (ripng->table); rp; rp = route_next (rp)) {
2835 if ((rinfo = rp->info) != NULL) {
2836 if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2837 (rinfo->sub_type == RIPNG_ROUTE_RTE))
2838 ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p,
2839 &rinfo->nexthop, rinfo->metric);
2840
2841 RIPNG_TIMER_OFF (rinfo->t_timeout);
2842 RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
2843
2844 rp->info = NULL;
2845 route_unlock_node (rp);
2846
2847 ripng_info_free(rinfo);
2848 }
2849 }
2850
2851 /* Cancel the RIPng timers */
2852 RIPNG_TIMER_OFF (ripng->t_update);
2853 RIPNG_TIMER_OFF (ripng->t_triggered_update);
2854 RIPNG_TIMER_OFF (ripng->t_triggered_interval);
2855
2856 /* Cancel the read thread */
2857 if (ripng->t_read) {
2858 thread_cancel (ripng->t_read);
2859 ripng->t_read = NULL;
2860 }
2861
2862 /* Close the RIPng socket */
2863 if (ripng->sock >= 0) {
2864 close(ripng->sock);
2865 ripng->sock = -1;
2866 }
2867
2868 /* Static RIPng route configuration. */
2869 for (rp = route_top (ripng->route); rp; rp = route_next (rp))
2870 if (rp->info) {
2871 rp->info = NULL;
2872 route_unlock_node (rp);
2873 }
2874
2875 /* RIPng aggregated prefixes */
2876 for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
2877 if (rp->info) {
2878 rp->info = NULL;
2879 route_unlock_node (rp);
2880 }
2881
2882 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2883 if (ripng->route_map[i].name)
2884 free (ripng->route_map[i].name);
2885
2886 XFREE (MTYPE_ROUTE_TABLE, ripng->table);
2887 XFREE (MTYPE_ROUTE_TABLE, ripng->route);
2888 XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate);
2889
2890 XFREE (MTYPE_RIPNG, ripng);
2891 ripng = NULL;
2892 } /* if (ripng) */
2893
2894 ripng_clean_network();
2895 ripng_passive_interface_clean ();
2896 ripng_offset_clean ();
2897 ripng_interface_clean ();
2898 ripng_redistribute_clean ();
2899}
2900
2901/* Reset all values to the default settings. */
2902void
2903ripng_reset ()
2904{
2905 /* Call ripd related reset functions. */
2906 ripng_debug_reset ();
2907 ripng_route_map_reset ();
2908
2909 /* Call library reset functions. */
2910 vty_reset ();
2911 access_list_reset ();
2912 prefix_list_reset ();
2913
2914 distribute_list_reset ();
2915
2916 ripng_interface_reset ();
2917
2918 ripng_zclient_reset ();
2919}
paul718e3742002-12-13 20:15:29 +00002920
2921void
2922ripng_if_rmap_update (struct if_rmap *if_rmap)
2923{
2924 struct interface *ifp;
2925 struct ripng_interface *ri;
2926 struct route_map *rmap;
2927
2928 ifp = if_lookup_by_name (if_rmap->ifname);
2929 if (ifp == NULL)
2930 return;
2931
2932 ri = ifp->info;
2933
2934 if (if_rmap->routemap[IF_RMAP_IN])
2935 {
2936 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
2937 if (rmap)
2938 ri->routemap[IF_RMAP_IN] = rmap;
2939 else
2940 ri->routemap[IF_RMAP_IN] = NULL;
2941 }
2942 else
2943 ri->routemap[RIPNG_FILTER_IN] = NULL;
2944
2945 if (if_rmap->routemap[IF_RMAP_OUT])
2946 {
2947 rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
2948 if (rmap)
2949 ri->routemap[IF_RMAP_OUT] = rmap;
2950 else
2951 ri->routemap[IF_RMAP_OUT] = NULL;
2952 }
2953 else
2954 ri->routemap[RIPNG_FILTER_OUT] = NULL;
2955}
2956
2957void
2958ripng_if_rmap_update_interface (struct interface *ifp)
2959{
2960 struct if_rmap *if_rmap;
2961
2962 if_rmap = if_rmap_lookup (ifp->name);
2963 if (if_rmap)
2964 ripng_if_rmap_update (if_rmap);
2965}
2966
2967void
2968ripng_routemap_update_redistribute (void)
2969{
2970 int i;
2971
2972 if (ripng)
2973 {
2974 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2975 {
2976 if (ripng->route_map[i].name)
2977 ripng->route_map[i].map =
2978 route_map_lookup_by_name (ripng->route_map[i].name);
2979 }
2980 }
2981}
2982
2983void
hasso98b718a2004-10-11 12:57:57 +00002984ripng_routemap_update (const char *unused)
paul718e3742002-12-13 20:15:29 +00002985{
2986 struct interface *ifp;
hasso52dc7ee2004-09-23 19:18:23 +00002987 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002988
2989 for (node = listhead (iflist); node; nextnode (node))
2990 {
2991 ifp = getdata (node);
2992 ripng_if_rmap_update_interface (ifp);
2993 }
2994
2995 ripng_routemap_update_redistribute ();
2996}
2997
2998/* Initialize ripng structure and set commands. */
2999void
3000ripng_init ()
3001{
3002 /* Randomize. */
3003 srand (time (NULL));
3004
3005 /* Install RIPNG_NODE. */
3006 install_node (&cmd_ripng_node, ripng_config_write);
3007
3008 /* Install ripng commands. */
3009 install_element (VIEW_NODE, &show_ipv6_ripng_cmd);
hassoa94434b2003-05-25 17:10:12 +00003010 install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd);
paul718e3742002-12-13 20:15:29 +00003011
3012 install_element (ENABLE_NODE, &show_ipv6_ripng_cmd);
hassoa94434b2003-05-25 17:10:12 +00003013 install_element (ENABLE_NODE, &show_ipv6_ripng_status_cmd);
paul718e3742002-12-13 20:15:29 +00003014
3015 install_element (CONFIG_NODE, &router_ripng_cmd);
hassoa94434b2003-05-25 17:10:12 +00003016 install_element (CONFIG_NODE, &no_router_ripng_cmd);
paul718e3742002-12-13 20:15:29 +00003017
3018 install_default (RIPNG_NODE);
3019 install_element (RIPNG_NODE, &ripng_route_cmd);
3020 install_element (RIPNG_NODE, &no_ripng_route_cmd);
3021 install_element (RIPNG_NODE, &ripng_aggregate_address_cmd);
3022 install_element (RIPNG_NODE, &no_ripng_aggregate_address_cmd);
3023
3024 install_element (RIPNG_NODE, &ripng_default_metric_cmd);
3025 install_element (RIPNG_NODE, &no_ripng_default_metric_cmd);
3026 install_element (RIPNG_NODE, &no_ripng_default_metric_val_cmd);
3027
3028 install_element (RIPNG_NODE, &ripng_timers_cmd);
3029 install_element (RIPNG_NODE, &no_ripng_timers_cmd);
hassoa94434b2003-05-25 17:10:12 +00003030 install_element (RIPNG_NODE, &no_ripng_timers_val_cmd);
paul718e3742002-12-13 20:15:29 +00003031#if 0
3032 install_element (RIPNG_NODE, &ripng_update_timer_cmd);
3033 install_element (RIPNG_NODE, &no_ripng_update_timer_cmd);
3034 install_element (RIPNG_NODE, &ripng_timeout_timer_cmd);
3035 install_element (RIPNG_NODE, &no_ripng_timeout_timer_cmd);
3036 install_element (RIPNG_NODE, &ripng_garbage_timer_cmd);
3037 install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd);
3038#endif /* 0 */
3039
paula2c62832003-04-23 17:01:31 +00003040 install_element (RIPNG_NODE, &ripng_default_information_originate_cmd);
3041 install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd);
paul718e3742002-12-13 20:15:29 +00003042
3043 ripng_if_init ();
3044 ripng_debug_init ();
3045
3046 /* Access list install. */
3047 access_list_init ();
hassoc9e52be2004-09-26 16:09:34 +00003048 access_list_add_hook (ripng_distribute_update_all_wrapper);
3049 access_list_delete_hook (ripng_distribute_update_all_wrapper);
paul718e3742002-12-13 20:15:29 +00003050
3051 /* Prefix list initialize.*/
3052 prefix_list_init ();
3053 prefix_list_add_hook (ripng_distribute_update_all);
3054 prefix_list_delete_hook (ripng_distribute_update_all);
3055
3056 /* Distribute list install. */
3057 distribute_list_init (RIPNG_NODE);
3058 distribute_list_add_hook (ripng_distribute_update);
3059 distribute_list_delete_hook (ripng_distribute_update);
3060
3061 /* Route-map for interface. */
3062 ripng_route_map_init ();
hassoa94434b2003-05-25 17:10:12 +00003063 ripng_offset_init ();
3064
paul718e3742002-12-13 20:15:29 +00003065 route_map_add_hook (ripng_routemap_update);
3066 route_map_delete_hook (ripng_routemap_update);
3067
hasso0750d212003-05-24 21:41:49 +00003068 if_rmap_init (RIPNG_NODE);
paul718e3742002-12-13 20:15:29 +00003069 if_rmap_hook_add (ripng_if_rmap_update);
3070 if_rmap_hook_delete (ripng_if_rmap_update);
3071}