2
* Copyright (C) 1998, 1999 Kunihiro Ishiguro
4
* This file is part of GNU Zebra.
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
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.
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
34
#include "distribute.h"
40
#include "ripngd/ripngd.h"
41
#include "ripngd/ripng_route.h"
42
#include "ripngd/ripng_debug.h"
43
#include "ripngd/ripng_nexthop.h"
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. */
48
struct ripng *ripng = NULL;
56
extern struct zebra_privs_t ripngd_privs;
60
ripng_output_process (struct interface *, struct sockaddr_in6 *, int);
63
ripng_triggered_update (struct thread *);
65
/* RIPng next hop specification. */
68
enum ripng_nexthop_type
73
struct in6_addr address;
77
ripng_route_rte (struct ripng_info *rinfo)
79
return (rinfo->type == ZEBRA_ROUTE_RIPNG && rinfo->sub_type == RIPNG_ROUTE_RTE);
82
/* Allocate new ripng information. */
86
struct ripng_info *new;
88
new = XCALLOC (MTYPE_RIPNG_ROUTE, sizeof (struct ripng_info));
92
/* Free ripng information. */
94
ripng_info_free (struct ripng_info *rinfo)
96
XFREE (MTYPE_RIPNG_ROUTE, rinfo);
99
/* Create ripng socket. */
101
ripng_make_socket (void)
105
struct sockaddr_in6 ripaddr;
107
sock = socket (AF_INET6, SOCK_DGRAM, 0);
110
zlog (NULL, LOG_ERR, "Can't make ripng socket");
114
ret = setsockopt_so_recvbuf (sock, 8096);
117
ret = setsockopt_ipv6_pktinfo (sock, 1);
120
ret = setsockopt_ipv6_multicast_hops (sock, 255);
123
ret = setsockopt_ipv6_multicast_loop (sock, 0);
126
ret = setsockopt_ipv6_hoplimit (sock, 1);
130
memset (&ripaddr, 0, sizeof (ripaddr));
131
ripaddr.sin6_family = AF_INET6;
133
ripaddr.sin6_len = sizeof (struct sockaddr_in6);
134
#endif /* SIN6_LEN */
135
ripaddr.sin6_port = htons (RIPNG_PORT_DEFAULT);
137
if (ripngd_privs.change (ZPRIVS_RAISE))
138
zlog_err ("ripng_make_socket: could not raise privs");
140
ret = bind (sock, (struct sockaddr *) &ripaddr, sizeof (ripaddr));
143
zlog (NULL, LOG_ERR, "Can't bind ripng socket: %s.", safe_strerror (errno));
144
if (ripngd_privs.change (ZPRIVS_LOWER))
145
zlog_err ("ripng_make_socket: could not lower privs");
148
if (ripngd_privs.change (ZPRIVS_LOWER))
149
zlog_err ("ripng_make_socket: could not lower privs");
153
/* Send RIPng packet. */
155
ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to,
156
struct interface *ifp)
161
struct cmsghdr *cmsgptr;
163
struct in6_pktinfo *pkt;
164
struct sockaddr_in6 addr;
166
if (IS_RIPNG_DEBUG_SEND) {
168
zlog_debug ("send to %s", inet6_ntoa (to->sin6_addr));
169
zlog_debug (" send interface %s", ifp->name);
170
zlog_debug (" send packet size %d", bufsize);
173
memset (&addr, 0, sizeof (struct sockaddr_in6));
174
addr.sin6_family = AF_INET6;
176
addr.sin6_len = sizeof (struct sockaddr_in6);
177
#endif /* SIN6_LEN */
178
addr.sin6_flowinfo = htonl (RIPNG_PRIORITY_DEFAULT);
180
/* When destination is specified. */
183
addr.sin6_addr = to->sin6_addr;
184
addr.sin6_port = to->sin6_port;
188
inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr);
189
addr.sin6_port = htons (RIPNG_PORT_DEFAULT);
192
msg.msg_name = (void *) &addr;
193
msg.msg_namelen = sizeof (struct sockaddr_in6);
196
msg.msg_control = (void *) adata;
197
msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
200
iov.iov_len = bufsize;
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;
207
pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
208
memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
209
pkt->ipi6_ifindex = ifp->ifindex;
211
ret = sendmsg (ripng->sock, &msg, 0);
215
zlog_err ("RIPng send fail on %s to %s: %s", ifp->name,
216
inet6_ntoa (to->sin6_addr), safe_strerror (errno));
218
zlog_err ("RIPng send fail on %s: %s", ifp->name, safe_strerror (errno));
224
/* Receive UDP RIPng packet from socket. */
226
ripng_recv_packet (int sock, u_char *buf, int bufsize,
227
struct sockaddr_in6 *from, unsigned int *ifindex,
233
struct cmsghdr *cmsgptr;
236
/* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
237
point I can't determine size of cmsghdr */
240
/* Fill in message and iovec. */
241
msg.msg_name = (void *) from;
242
msg.msg_namelen = sizeof (struct sockaddr_in6);
245
msg.msg_control = (void *) adata;
246
msg.msg_controllen = sizeof adata;
248
iov.iov_len = bufsize;
250
/* If recvmsg fail return minus value. */
251
ret = recvmsg (sock, &msg, 0);
255
for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
256
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
258
/* I want interface index which this packet comes from. */
259
if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
260
cmsgptr->cmsg_type == IPV6_PKTINFO)
262
struct in6_pktinfo *ptr;
264
ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
265
*ifindex = ptr->ipi6_ifindex;
266
dst = ptr->ipi6_addr;
269
zlog_warn ("Interface index returned by IPV6_PKTINFO is zero");
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));
278
/* Hoplimit check shold be done when destination address is
279
multicast address. */
280
if (! IN6_IS_ADDR_MULTICAST (&dst))
286
/* Dump rip packet */
288
ripng_packet_dump (struct ripng_packet *packet, int size, const char *sndrcv)
292
const char *command_str;
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";
300
command_str = "unknown";
302
/* Dump packet header. */
303
zlog_debug ("%s %s version %d packet size %d",
304
sndrcv, command_str, packet->version, size);
306
/* Dump each routing table entry. */
309
for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
311
if (rte->metric == RIPNG_METRIC_NEXTHOP)
312
zlog_debug (" nexthop %s/%d", inet6_ntoa (rte->addr), rte->prefixlen);
314
zlog_debug (" %s/%d metric %d tag %d",
315
inet6_ntoa (rte->addr), rte->prefixlen,
316
rte->metric, ntohs (rte->tag));
320
/* RIPng next hop address RTE (Route Table Entry). */
322
ripng_nexthop_rte (struct rte *rte,
323
struct sockaddr_in6 *from,
324
struct ripng_nexthop *nexthop)
326
char buf[INET6_BUFSIZ];
328
/* Logging before checking RTE. */
329
if (IS_RIPNG_DEBUG_RECV)
330
zlog_debug ("RIPng nexthop RTE address %s tag %d prefixlen %d",
331
inet6_ntoa (rte->addr), ntohs (rte->tag), rte->prefixlen);
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",
338
ntohs (rte->tag), inet6_ntoa (from->sin6_addr));
340
if (rte->prefixlen != 0)
341
zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s",
342
rte->prefixlen, inet6_ntoa (from->sin6_addr));
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))
350
nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
351
memset (&nexthop->address, 0, sizeof (struct in6_addr));
355
if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
357
nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
358
IPV6_ADDR_COPY (&nexthop->address, &rte->addr);
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",
370
inet6_ntoa (rte->addr),
371
inet_ntop (AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ));
373
nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
374
memset (&nexthop->address, 0, sizeof (struct in6_addr));
379
/* If ifp has same link-local address then return 1. */
381
ripng_lladdr_check (struct interface *ifp, struct in6_addr *addr)
383
struct listnode *node;
384
struct connected *connected;
387
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
389
p = connected->address;
391
if (p->family == AF_INET6 &&
392
IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6) &&
393
IN6_ARE_ADDR_EQUAL (&p->u.prefix6, addr))
399
/* RIPng route garbage collect timer. */
401
ripng_garbage_collect (struct thread *t)
403
struct ripng_info *rinfo;
404
struct route_node *rp;
406
rinfo = THREAD_ARG (t);
407
rinfo->t_garbage_collect = NULL;
409
/* Off timeout timer. */
410
RIPNG_TIMER_OFF (rinfo->t_timeout);
412
/* Get route_node pointer. */
415
/* Unlock route_node. */
417
route_unlock_node (rp);
419
/* Free RIPng routing information. */
420
ripng_info_free (rinfo);
425
/* Timeout RIPng routes. */
427
ripng_timeout (struct thread *t)
429
struct ripng_info *rinfo;
430
struct route_node *rp;
432
rinfo = THREAD_ARG (t);
433
rinfo->t_timeout = NULL;
435
/* Get route_node pointer. */
438
/* - The garbage-collection timer is set for 120 seconds. */
439
RIPNG_TIMER_ON (rinfo->t_garbage_collect, ripng_garbage_collect,
440
ripng->garbage_time);
442
/* Delete this route from the kernel. */
443
ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
445
/* - The metric for the route is set to 16 (infinity). This causes
446
the route to be removed from service. */
447
rinfo->metric = RIPNG_METRIC_INFINITY;
448
rinfo->flags &= ~RIPNG_RTF_FIB;
450
/* Aggregate count decrement. */
451
ripng_aggregate_decrement (rp, rinfo);
453
/* - The route change flag is to indicate that this entry has been
455
rinfo->flags |= RIPNG_RTF_CHANGED;
457
/* - The output process is signalled to trigger a response. */
458
ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
464
ripng_timeout_update (struct ripng_info *rinfo)
466
if (rinfo->metric != RIPNG_METRIC_INFINITY)
468
RIPNG_TIMER_OFF (rinfo->t_timeout);
469
RIPNG_TIMER_ON (rinfo->t_timeout, ripng_timeout, ripng->timeout_time);
474
ripng_incoming_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
476
struct distribute *dist;
477
struct access_list *alist;
478
struct prefix_list *plist;
480
/* Input distribute-list filtering. */
481
if (ri->list[RIPNG_FILTER_IN])
483
if (access_list_apply (ri->list[RIPNG_FILTER_IN],
484
(struct prefix *) p) == FILTER_DENY)
486
if (IS_RIPNG_DEBUG_PACKET)
487
zlog_debug ("%s/%d filtered by distribute in",
488
inet6_ntoa (p->prefix), p->prefixlen);
492
if (ri->prefix[RIPNG_FILTER_IN])
494
if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN],
495
(struct prefix *) p) == PREFIX_DENY)
497
if (IS_RIPNG_DEBUG_PACKET)
498
zlog_debug ("%s/%d filtered by prefix-list in",
499
inet6_ntoa (p->prefix), p->prefixlen);
504
/* All interface filter check. */
505
dist = distribute_lookup (NULL);
508
if (dist->list[DISTRIBUTE_IN])
510
alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
514
if (access_list_apply (alist,
515
(struct prefix *) p) == FILTER_DENY)
517
if (IS_RIPNG_DEBUG_PACKET)
518
zlog_debug ("%s/%d filtered by distribute in",
519
inet6_ntoa (p->prefix), p->prefixlen);
524
if (dist->prefix[DISTRIBUTE_IN])
526
plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
530
if (prefix_list_apply (plist,
531
(struct prefix *) p) == PREFIX_DENY)
533
if (IS_RIPNG_DEBUG_PACKET)
534
zlog_debug ("%s/%d filtered by prefix-list in",
535
inet6_ntoa (p->prefix), p->prefixlen);
545
ripng_outgoing_filter (struct prefix_ipv6 *p, struct ripng_interface *ri)
547
struct distribute *dist;
548
struct access_list *alist;
549
struct prefix_list *plist;
551
if (ri->list[RIPNG_FILTER_OUT])
553
if (access_list_apply (ri->list[RIPNG_FILTER_OUT],
554
(struct prefix *) p) == FILTER_DENY)
556
if (IS_RIPNG_DEBUG_PACKET)
557
zlog_debug ("%s/%d is filtered by distribute out",
558
inet6_ntoa (p->prefix), p->prefixlen);
562
if (ri->prefix[RIPNG_FILTER_OUT])
564
if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT],
565
(struct prefix *) p) == PREFIX_DENY)
567
if (IS_RIPNG_DEBUG_PACKET)
568
zlog_debug ("%s/%d is filtered by prefix-list out",
569
inet6_ntoa (p->prefix), p->prefixlen);
574
/* All interface filter check. */
575
dist = distribute_lookup (NULL);
578
if (dist->list[DISTRIBUTE_OUT])
580
alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
584
if (access_list_apply (alist,
585
(struct prefix *) p) == FILTER_DENY)
587
if (IS_RIPNG_DEBUG_PACKET)
588
zlog_debug ("%s/%d filtered by distribute out",
589
inet6_ntoa (p->prefix), p->prefixlen);
594
if (dist->prefix[DISTRIBUTE_OUT])
596
plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
600
if (prefix_list_apply (plist,
601
(struct prefix *) p) == PREFIX_DENY)
603
if (IS_RIPNG_DEBUG_PACKET)
604
zlog_debug ("%s/%d filtered by prefix-list out",
605
inet6_ntoa (p->prefix), p->prefixlen);
614
/* Process RIPng route according to RFC2080. */
616
ripng_route_process (struct rte *rte, struct sockaddr_in6 *from,
617
struct ripng_nexthop *ripng_nexthop,
618
struct interface *ifp)
621
struct prefix_ipv6 p;
622
struct route_node *rp;
623
struct ripng_info *rinfo;
624
struct ripng_interface *ri;
625
struct in6_addr *nexthop;
629
/* Make prefix structure. */
630
memset (&p, 0, sizeof (struct prefix_ipv6));
632
/* p.prefix = rte->addr; */
633
IPV6_ADDR_COPY (&p.prefix, &rte->addr);
634
p.prefixlen = rte->prefixlen;
636
/* Make sure mask is applied. */
637
/* XXX We have to check the prefix is valid or not before call
639
apply_mask_ipv6 (&p);
641
/* Apply input filters. */
644
ret = ripng_incoming_filter (&p, ri);
649
if (ri->routemap[RIPNG_FILTER_IN])
652
struct ripng_info newinfo;
654
memset (&newinfo, 0, sizeof (struct ripng_info));
655
newinfo.type = ZEBRA_ROUTE_RIPNG;
656
newinfo.sub_type = RIPNG_ROUTE_RTE;
657
if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
658
newinfo.nexthop = ripng_nexthop->address;
660
newinfo.nexthop = from->sin6_addr;
661
newinfo.from = from->sin6_addr;
662
newinfo.ifindex = ifp->ifindex;
663
newinfo.metric = rte->metric;
664
newinfo.metric_out = rte->metric; /* XXX */
665
newinfo.tag = ntohs(rte->tag); /* XXX */
667
ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN],
668
(struct prefix *)&p, RMAP_RIPNG, &newinfo);
670
if (ret == RMAP_DENYMATCH)
672
if (IS_RIPNG_DEBUG_PACKET)
673
zlog_debug ("RIPng %s/%d is filtered by route-map in",
674
inet6_ntoa (p.prefix), p.prefixlen);
678
/* Get back the object */
679
if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) {
680
if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) {
681
/* the nexthop get changed by the routemap */
682
if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop))
683
ripng_nexthop->address = newinfo.nexthop;
685
ripng_nexthop->address = in6addr_any;
688
if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) {
689
/* the nexthop get changed by the routemap */
690
if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) {
691
ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
692
ripng_nexthop->address = newinfo.nexthop;
696
rte->tag = htons(newinfo.tag_out); /* XXX */
697
rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
700
/* Once the entry has been validated, update the metric by
701
* adding the cost of the network on wich the message
702
* arrived. If the result is greater than infinity, use infinity
703
* (RFC2453 Sec. 3.9.2)
706
/* Zebra ripngd can handle offset-list in. */
707
ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric);
709
/* If offset-list does not modify the metric use interface's
712
rte->metric += ifp->metric;
714
if (rte->metric > RIPNG_METRIC_INFINITY)
715
rte->metric = RIPNG_METRIC_INFINITY;
717
/* Set nexthop pointer. */
718
if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
719
nexthop = &ripng_nexthop->address;
721
nexthop = &from->sin6_addr;
723
/* Lookup RIPng routing table. */
724
rp = route_node_get (ripng->table, (struct prefix *) &p);
730
/* Redistributed route check. */
731
if (rinfo->type != ZEBRA_ROUTE_RIPNG
732
&& rinfo->metric != RIPNG_METRIC_INFINITY)
735
/* Local static route. */
736
if (rinfo->type == ZEBRA_ROUTE_RIPNG
737
&& ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
738
(rinfo->sub_type == RIPNG_ROUTE_DEFAULT))
739
&& rinfo->metric != RIPNG_METRIC_INFINITY)
743
if (rp->info == NULL)
745
/* Now, check to see whether there is already an explicit route
746
for the destination prefix. If there is no such route, add
747
this route to the routing table, unless the metric is
748
infinity (there is no point in adding a route which
750
if (rte->metric != RIPNG_METRIC_INFINITY)
752
rinfo = ripng_info_new ();
754
/* - Setting the destination prefix and length to those in
759
/* - Setting the metric to the newly calculated metric (as
761
rinfo->metric = rte->metric;
762
rinfo->tag = ntohs (rte->tag);
764
/* - Set the next hop address to be the address of the router
765
from which the datagram came or the next hop address
766
specified by a next hop RTE. */
767
IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
768
IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
769
rinfo->ifindex = ifp->ifindex;
771
/* - Initialize the timeout for the route. If the
772
garbage-collection timer is running for this route, stop it. */
773
ripng_timeout_update (rinfo);
775
/* - Set the route change flag. */
776
rinfo->flags |= RIPNG_RTF_CHANGED;
778
/* - Signal the output process to trigger an update (see section
780
ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
782
/* Finally, route goes into the kernel. */
783
rinfo->type = ZEBRA_ROUTE_RIPNG;
784
rinfo->sub_type = RIPNG_ROUTE_RTE;
786
ripng_zebra_ipv6_add (&p, &rinfo->nexthop, rinfo->ifindex);
787
rinfo->flags |= RIPNG_RTF_FIB;
789
/* Aggregate check. */
790
ripng_aggregate_increment (rp, rinfo);
797
/* If there is an existing route, compare the next hop address
798
to the address of the router from which the datagram came.
799
If this datagram is from the same router as the existing
800
route, reinitialize the timeout. */
801
same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr)
802
&& (rinfo->ifindex == ifp->ifindex));
805
ripng_timeout_update (rinfo);
807
/* Next, compare the metrics. If the datagram is from the same
808
router as the existing route, and the new metric is different
809
than the old one; or, if the new metric is lower than the old
810
one; do the following actions: */
811
if ((same && rinfo->metric != rte->metric) ||
812
rte->metric < rinfo->metric)
814
/* - Adopt the route from the datagram. That is, put the
815
new metric in, and adjust the next hop address (if
817
oldmetric = rinfo->metric;
818
rinfo->metric = rte->metric;
819
rinfo->tag = ntohs (rte->tag);
820
IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);
821
rinfo->ifindex = ifp->ifindex;
823
/* Should a new route to this network be established
824
while the garbage-collection timer is running, the
825
new route will replace the one that is about to be
826
deleted. In this case the garbage-collection timer
829
if (oldmetric == RIPNG_METRIC_INFINITY &&
830
rinfo->metric < RIPNG_METRIC_INFINITY)
832
rinfo->type = ZEBRA_ROUTE_RIPNG;
833
rinfo->sub_type = RIPNG_ROUTE_RTE;
835
RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
837
if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
838
IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
840
ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);
841
rinfo->flags |= RIPNG_RTF_FIB;
843
/* The aggregation counter needs to be updated because
844
the prefixes, which are into the gc, have been
845
removed from the aggregator (see ripng_timout). */
846
ripng_aggregate_increment (rp, rinfo);
849
/* Update nexthop and/or metric value. */
850
if (oldmetric != RIPNG_METRIC_INFINITY)
852
ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
853
ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);
854
rinfo->flags |= RIPNG_RTF_FIB;
856
if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop))
857
IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);
860
/* - Set the route change flag and signal the output process
861
to trigger an update. */
862
rinfo->flags |= RIPNG_RTF_CHANGED;
863
ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
865
/* - If the new metric is infinity, start the deletion
866
process (described above); */
867
if (rinfo->metric == RIPNG_METRIC_INFINITY)
869
/* If the new metric is infinity, the deletion process
870
begins for the route, which is no longer used for
871
routing packets. Note that the deletion process is
872
started only when the metric is first set to
873
infinity. If the metric was already infinity, then a
874
new deletion process is not started. */
875
if (oldmetric != RIPNG_METRIC_INFINITY)
877
/* - The garbage-collection timer is set for 120 seconds. */
878
RIPNG_TIMER_ON (rinfo->t_garbage_collect,
879
ripng_garbage_collect, ripng->garbage_time);
880
RIPNG_TIMER_OFF (rinfo->t_timeout);
882
/* - The metric for the route is set to 16
883
(infinity). This causes the route to be removed
885
ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);
886
rinfo->flags &= ~RIPNG_RTF_FIB;
888
/* Aggregate count decrement. */
889
ripng_aggregate_decrement (rp, rinfo);
891
/* - The route change flag is to indicate that this
892
entry has been changed. */
893
/* - The output process is signalled to trigger a
895
; /* Above processes are already done previously. */
900
/* otherwise, re-initialize the timeout. */
901
ripng_timeout_update (rinfo);
904
/* Unlock tempolary lock of the route. */
905
route_unlock_node (rp);
909
/* Add redistributed route to RIPng table. */
911
ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p,
912
unsigned int ifindex, struct in6_addr *nexthop)
914
struct route_node *rp;
915
struct ripng_info *rinfo;
917
/* Redistribute route */
918
if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
920
if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
922
#if defined (MUSICA) || defined (LINUX)
923
/* XXX As long as the RIPng redistribution is applied to all the connected
924
* routes, one needs to filter the ::/96 prefixes.
925
* However it could be a wanted case, it will be removed soon.
927
if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
928
(IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
930
#endif /* MUSICA or LINUX */
932
rp = route_node_get (ripng->table, (struct prefix *) p);
937
if (rinfo->type == ZEBRA_ROUTE_CONNECT
938
&& rinfo->sub_type == RIPNG_ROUTE_INTERFACE
939
&& rinfo->metric != RIPNG_METRIC_INFINITY) {
940
route_unlock_node (rp);
944
/* Manually configured RIPng route check.
945
* They have the precedence on all the other entries.
947
if (rinfo->type == ZEBRA_ROUTE_RIPNG
948
&& ((rinfo->sub_type == RIPNG_ROUTE_STATIC) ||
949
(rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) {
950
if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) &&
951
(sub_type != RIPNG_ROUTE_DEFAULT))) {
952
route_unlock_node (rp);
957
RIPNG_TIMER_OFF (rinfo->t_timeout);
958
RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
960
/* Tells the other daemons about the deletion of
963
if (ripng_route_rte (rinfo))
964
ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop,
968
ripng_info_free (rinfo);
970
route_unlock_node (rp);
974
rinfo = ripng_info_new ();
977
rinfo->sub_type = sub_type;
978
rinfo->ifindex = ifindex;
982
if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop))
983
rinfo->nexthop = *nexthop;
985
rinfo->flags |= RIPNG_RTF_FIB;
988
/* Aggregate check. */
989
ripng_aggregate_increment (rp, rinfo);
991
rinfo->flags |= RIPNG_RTF_CHANGED;
993
if (IS_RIPNG_DEBUG_EVENT) {
995
zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
996
inet6_ntoa(p->prefix), p->prefixlen,
997
ifindex2ifname(ifindex));
999
zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1000
inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop),
1001
ifindex2ifname(ifindex));
1004
ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
1007
/* Delete redistributed route to RIPng table. */
1009
ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p,
1010
unsigned int ifindex)
1012
struct route_node *rp;
1013
struct ripng_info *rinfo;
1015
if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))
1017
if (IN6_IS_ADDR_LOOPBACK (&p->prefix))
1019
#if defined (MUSICA) || defined (LINUX)
1020
/* XXX As long as the RIPng redistribution is applied to all the connected
1021
* routes, one needs to filter the ::/96 prefixes.
1022
* However it could be a wanted case, it will be removed soon.
1024
if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
1025
(IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
1027
#endif /* MUSICA or LINUX */
1029
rp = route_node_lookup (ripng->table, (struct prefix *) p);
1036
&& rinfo->type == type
1037
&& rinfo->sub_type == sub_type
1038
&& rinfo->ifindex == ifindex)
1040
/* Perform poisoned reverse. */
1041
rinfo->metric = RIPNG_METRIC_INFINITY;
1042
RIPNG_TIMER_ON (rinfo->t_garbage_collect,
1043
ripng_garbage_collect, ripng->garbage_time);
1044
RIPNG_TIMER_OFF (rinfo->t_timeout);
1046
/* Aggregate count decrement. */
1047
ripng_aggregate_decrement (rp, rinfo);
1049
rinfo->flags |= RIPNG_RTF_CHANGED;
1051
if (IS_RIPNG_DEBUG_EVENT)
1052
zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]",
1053
inet6_ntoa(p->prefix), p->prefixlen,
1054
ifindex2ifname(ifindex));
1056
ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
1061
/* Withdraw redistributed route. */
1063
ripng_redistribute_withdraw (int type)
1065
struct route_node *rp;
1066
struct ripng_info *rinfo;
1071
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1072
if ((rinfo = rp->info) != NULL)
1074
if ((rinfo->type == type)
1075
&& (rinfo->sub_type != RIPNG_ROUTE_INTERFACE))
1077
/* Perform poisoned reverse. */
1078
rinfo->metric = RIPNG_METRIC_INFINITY;
1079
RIPNG_TIMER_ON (rinfo->t_garbage_collect,
1080
ripng_garbage_collect, ripng->garbage_time);
1081
RIPNG_TIMER_OFF (rinfo->t_timeout);
1083
/* Aggregate count decrement. */
1084
ripng_aggregate_decrement (rp, rinfo);
1086
rinfo->flags |= RIPNG_RTF_CHANGED;
1088
if (IS_RIPNG_DEBUG_EVENT) {
1089
struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p;
1091
zlog_debug ("Poisone %s/%d on the interface %s [withdraw]",
1092
inet6_ntoa(p->prefix), p->prefixlen,
1093
ifindex2ifname(rinfo->ifindex));
1096
ripng_event (RIPNG_TRIGGERED_UPDATE, 0);
1101
/* RIP routing information. */
1103
ripng_response_process (struct ripng_packet *packet, int size,
1104
struct sockaddr_in6 *from, struct interface *ifp,
1109
struct ripng_nexthop nexthop;
1111
/* RFC2080 2.4.2 Response Messages:
1112
The Response must be ignored if it is not from the RIPng port. */
1113
if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT)
1115
zlog_warn ("RIPng packet comes from non RIPng port %d from %s",
1116
ntohs (from->sin6_port), inet6_ntoa (from->sin6_addr));
1117
ripng_peer_bad_packet (from);
1121
/* The datagram's IPv6 source address should be checked to see
1122
whether the datagram is from a valid neighbor; the source of the
1123
datagram must be a link-local address. */
1124
if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr))
1126
zlog_warn ("RIPng packet comes from non link local address %s",
1127
inet6_ntoa (from->sin6_addr));
1128
ripng_peer_bad_packet (from);
1132
/* It is also worth checking to see whether the response is from one
1133
of the router's own addresses. Interfaces on broadcast networks
1134
may receive copies of their own multicasts immediately. If a
1135
router processes its own output as new input, confusion is likely,
1136
and such datagrams must be ignored. */
1137
if (ripng_lladdr_check (ifp, &from->sin6_addr))
1139
zlog_warn ("RIPng packet comes from my own link local address %s",
1140
inet6_ntoa (from->sin6_addr));
1141
ripng_peer_bad_packet (from);
1145
/* As an additional check, periodic advertisements must have their
1146
hop counts set to 255, and inbound, multicast packets sent from the
1147
RIPng port (i.e. periodic advertisement or triggered update
1148
packets) must be examined to ensure that the hop count is 255. */
1149
if (hoplimit >= 0 && hoplimit != 255)
1151
zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",
1152
hoplimit, inet6_ntoa (from->sin6_addr));
1153
ripng_peer_bad_packet (from);
1157
/* Update RIPng peer. */
1158
ripng_peer_update (from, packet->version);
1160
/* Reset nexthop. */
1161
memset (&nexthop, 0, sizeof (struct ripng_nexthop));
1162
nexthop.flag = RIPNG_NEXTHOP_UNSPEC;
1164
/* Set RTE pointer. */
1167
for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++)
1169
/* First of all, we have to check this RTE is next hop RTE or
1170
not. Next hop RTE is completely different with normal RTE so
1171
we need special treatment. */
1172
if (rte->metric == RIPNG_METRIC_NEXTHOP)
1174
ripng_nexthop_rte (rte, from, &nexthop);
1178
/* RTE information validation. */
1180
/* - is the destination prefix valid (e.g., not a multicast
1181
prefix and not a link-local address) A link-local address
1182
should never be present in an RTE. */
1183
if (IN6_IS_ADDR_MULTICAST (&rte->addr))
1185
zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",
1186
inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
1187
ripng_peer_bad_route (from);
1190
if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))
1192
zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",
1193
inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
1194
ripng_peer_bad_route (from);
1197
if (IN6_IS_ADDR_LOOPBACK (&rte->addr))
1199
zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",
1200
inet6_ntoa (rte->addr), rte->prefixlen, rte->metric);
1201
ripng_peer_bad_route (from);
1205
/* - is the prefix length valid (i.e., between 0 and 128,
1207
if (rte->prefixlen > 128)
1209
zlog_warn ("Invalid prefix length %s/%d from %s%%%s",
1210
inet6_ntoa (rte->addr), rte->prefixlen,
1211
inet6_ntoa (from->sin6_addr), ifp->name);
1212
ripng_peer_bad_route (from);
1216
/* - is the metric valid (i.e., between 1 and 16, inclusive) */
1217
if (! (rte->metric >= 1 && rte->metric <= 16))
1219
zlog_warn ("Invalid metric %d from %s%%%s", rte->metric,
1220
inet6_ntoa (from->sin6_addr), ifp->name);
1221
ripng_peer_bad_route (from);
1225
/* Vincent: XXX Should we compute the direclty reachable nexthop
1226
* for our RIPng network ?
1229
/* Routing table updates. */
1230
ripng_route_process (rte, from, &nexthop, ifp);
1234
/* Response to request message. */
1236
ripng_request_process (struct ripng_packet *packet,int size,
1237
struct sockaddr_in6 *from, struct interface *ifp)
1241
struct prefix_ipv6 p;
1242
struct route_node *rp;
1243
struct ripng_info *rinfo;
1244
struct ripng_interface *ri;
1246
/* Does not reponse to the requests on the loopback interfaces */
1247
if (if_is_loopback (ifp))
1250
/* Check RIPng process is enabled on this interface. */
1255
/* When passive interface is specified, suppress responses */
1259
/* RIPng peer update. */
1260
ripng_peer_update (from, packet->version);
1262
lim = ((caddr_t) packet) + size;
1265
/* The Request is processed entry by entry. If there are no
1266
entries, no response is given. */
1267
if (lim == (caddr_t) rte)
1270
/* There is one special case. If there is exactly one entry in the
1271
request, and it has a destination prefix of zero, a prefix length
1272
of zero, and a metric of infinity (i.e., 16), then this is a
1273
request to send the entire routing table. In that case, a call
1274
is made to the output process to send the routing table to the
1275
requesting address/port. */
1276
if (lim == ((caddr_t) (rte + 1)) &&
1277
IN6_IS_ADDR_UNSPECIFIED (&rte->addr) &&
1278
rte->prefixlen == 0 &&
1279
rte->metric == RIPNG_METRIC_INFINITY)
1281
/* All route with split horizon */
1282
ripng_output_process (ifp, from, ripng_all_route);
1286
/* Except for this special case, processing is quite simple.
1287
Examine the list of RTEs in the Request one by one. For each
1288
entry, look up the destination in the router's routing
1289
database and, if there is a route, put that route's metric in
1290
the metric field of the RTE. If there is no explicit route
1291
to the specified destination, put infinity in the metric
1292
field. Once all the entries have been filled in, change the
1293
command from Request to Response and send the datagram back
1294
to the requestor. */
1295
memset (&p, 0, sizeof (struct prefix_ipv6));
1296
p.family = AF_INET6;
1298
for (; ((caddr_t) rte) < lim; rte++)
1300
p.prefix = rte->addr;
1301
p.prefixlen = rte->prefixlen;
1302
apply_mask_ipv6 (&p);
1304
rp = route_node_lookup (ripng->table, (struct prefix *) &p);
1309
rte->metric = rinfo->metric;
1310
route_unlock_node (rp);
1313
rte->metric = RIPNG_METRIC_INFINITY;
1315
packet->command = RIPNG_RESPONSE;
1317
ripng_send_packet ((caddr_t) packet, size, from, ifp);
1321
/* First entry point of reading RIPng packet. */
1323
ripng_read (struct thread *thread)
1327
struct sockaddr_in6 from;
1328
struct ripng_packet *packet;
1329
unsigned int ifindex;
1330
struct interface *ifp;
1333
/* Check ripng is active and alive. */
1334
assert (ripng != NULL);
1335
assert (ripng->sock >= 0);
1337
/* Fetch thread data and set read pointer to empty for event
1338
managing. `sock' sould be same as ripng->sock. */
1339
sock = THREAD_FD (thread);
1340
ripng->t_read = NULL;
1342
/* Add myself to the next event. */
1343
ripng_event (RIPNG_READ, sock);
1345
/* Read RIPng packet. */
1346
len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf),
1347
STREAM_SIZE (ripng->ibuf), &from, &ifindex,
1351
zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno));
1355
/* Check RTE boundary. RTE size (Packet length - RIPng header size
1356
(4)) must be multiple size of one RTE size (20). */
1357
if (((len - 4) % 20) != 0)
1359
zlog_warn ("RIPng invalid packet size %d from %s", len,
1360
inet6_ntoa (from.sin6_addr));
1361
ripng_peer_bad_packet (&from);
1365
packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf);
1366
ifp = if_lookup_by_index (ifindex);
1368
/* RIPng packet received. */
1369
if (IS_RIPNG_DEBUG_EVENT)
1370
zlog_debug ("RIPng packet received from %s port %d on %s",
1371
inet6_ntoa (from.sin6_addr), ntohs (from.sin6_port),
1372
ifp ? ifp->name : "unknown");
1374
/* Logging before packet checking. */
1375
if (IS_RIPNG_DEBUG_RECV)
1376
ripng_packet_dump (packet, len, "RECV");
1378
/* Packet comes from unknown interface. */
1381
zlog_warn ("RIPng packet comes from unknown interface %d", ifindex);
1385
/* Packet version mismatch checking. */
1386
if (packet->version != ripng->version)
1388
zlog_warn ("RIPng packet version %d doesn't fit to my version %d",
1389
packet->version, ripng->version);
1390
ripng_peer_bad_packet (&from);
1394
/* Process RIPng packet. */
1395
switch (packet->command)
1398
ripng_request_process (packet, len, &from, ifp);
1400
case RIPNG_RESPONSE:
1401
ripng_response_process (packet, len, &from, ifp, hoplimit);
1404
zlog_warn ("Invalid RIPng command %d", packet->command);
1405
ripng_peer_bad_packet (&from);
1411
/* Walk down the RIPng routing table then clear changed flag. */
1413
ripng_clear_changed_flag ()
1415
struct route_node *rp;
1416
struct ripng_info *rinfo;
1418
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1419
if ((rinfo = rp->info) != NULL)
1420
if (rinfo->flags & RIPNG_RTF_CHANGED)
1421
rinfo->flags &= ~RIPNG_RTF_CHANGED;
1424
/* Regular update of RIPng route. Send all routing formation to RIPng
1425
enabled interface. */
1427
ripng_update (struct thread *t)
1429
struct listnode *node;
1430
struct interface *ifp;
1431
struct ripng_interface *ri;
1433
/* Clear update timer thread. */
1434
ripng->t_update = NULL;
1436
/* Logging update event. */
1437
if (IS_RIPNG_DEBUG_EVENT)
1438
zlog_debug ("RIPng update timer expired!");
1440
/* Supply routes to each interface. */
1441
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
1445
if (if_is_loopback (ifp) || ! if_is_up (ifp))
1451
/* When passive interface is specified, suppress announce to the
1457
if (ri->ri_send == RIPNG_SEND_OFF)
1459
if (IS_RIPNG_DEBUG_EVENT)
1460
zlog (NULL, LOG_DEBUG,
1461
"[Event] RIPng send to if %d is suppressed by config",
1465
#endif /* RIPNG_ADVANCED */
1467
ripng_output_process (ifp, NULL, ripng_all_route);
1470
/* Triggered updates may be suppressed if a regular update is due by
1471
the time the triggered update would be sent. */
1472
if (ripng->t_triggered_interval)
1474
thread_cancel (ripng->t_triggered_interval);
1475
ripng->t_triggered_interval = NULL;
1479
/* Reset flush event. */
1480
ripng_event (RIPNG_UPDATE_EVENT, 0);
1485
/* Triggered update interval timer. */
1487
ripng_triggered_interval (struct thread *t)
1489
ripng->t_triggered_interval = NULL;
1494
ripng_triggered_update (t);
1499
/* Execute triggered update. */
1501
ripng_triggered_update (struct thread *t)
1503
struct listnode *node;
1504
struct interface *ifp;
1505
struct ripng_interface *ri;
1508
ripng->t_triggered_update = NULL;
1510
/* Cancel interval timer. */
1511
if (ripng->t_triggered_interval)
1513
thread_cancel (ripng->t_triggered_interval);
1514
ripng->t_triggered_interval = NULL;
1518
/* Logging triggered update. */
1519
if (IS_RIPNG_DEBUG_EVENT)
1520
zlog_debug ("RIPng triggered update!");
1522
/* Split Horizon processing is done when generating triggered
1523
updates as well as normal updates (see section 2.6). */
1524
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
1528
if (if_is_loopback (ifp) || ! if_is_up (ifp))
1534
/* When passive interface is specified, suppress announce to the
1539
ripng_output_process (ifp, NULL, ripng_changed_route);
1542
/* Once all of the triggered updates have been generated, the route
1543
change flags should be cleared. */
1544
ripng_clear_changed_flag ();
1546
/* After a triggered update is sent, a timer should be set for a
1547
random interval between 1 and 5 seconds. If other changes that
1548
would trigger updates occur before the timer expires, a single
1549
update is triggered when the timer expires. */
1550
interval = (random () % 5) + 1;
1552
ripng->t_triggered_interval =
1553
thread_add_timer (master, ripng_triggered_interval, NULL, interval);
1558
/* Write routing table entry to the stream and return next index of
1559
the routing table entry in the stream. */
1561
ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,
1562
struct in6_addr *nexthop, u_int16_t tag, u_char metric)
1564
/* RIPng packet header. */
1567
stream_putc (s, RIPNG_RESPONSE);
1568
stream_putc (s, RIPNG_V1);
1572
/* Write routing table entry. */
1574
stream_write (s, (u_char *) &p->prefix, sizeof (struct in6_addr));
1576
stream_write (s, (u_char *) nexthop, sizeof (struct in6_addr));
1577
stream_putw (s, tag);
1579
stream_putc (s, p->prefixlen);
1582
stream_putc (s, metric);
1587
/* Send RESPONSE message to specified destination. */
1589
ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,
1593
struct route_node *rp;
1594
struct ripng_info *rinfo;
1595
struct ripng_interface *ri;
1596
struct ripng_aggregate *aggregate;
1597
struct prefix_ipv6 *p;
1598
struct list * ripng_rte_list;
1600
if (IS_RIPNG_DEBUG_EVENT) {
1602
zlog_debug ("RIPng update routes to neighbor %s",
1603
inet6_ntoa(to->sin6_addr));
1605
zlog_debug ("RIPng update routes on interface %s", ifp->name);
1608
/* Get RIPng interface. */
1611
ripng_rte_list = ripng_rte_new();
1613
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
1615
if ((rinfo = rp->info) != NULL && rinfo->suppress == 0)
1617
/* If no route-map are applied, the RTE will be these following
1620
p = (struct prefix_ipv6 *) &rp->p;
1621
rinfo->metric_out = rinfo->metric;
1622
rinfo->tag_out = rinfo->tag;
1623
memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out));
1624
/* In order to avoid some local loops,
1625
* if the RIPng route has a nexthop via this interface, keep the nexthop,
1626
* otherwise set it to 0. The nexthop should not be propagated
1627
* beyond the local broadcast/multicast area in order
1628
* to avoid an IGP multi-level recursive look-up.
1630
if (rinfo->ifindex == ifp->ifindex)
1631
rinfo->nexthop_out = rinfo->nexthop;
1633
/* Apply output filters. */
1634
ret = ripng_outgoing_filter (p, ri);
1638
/* Changed route only output. */
1639
if (route_type == ripng_changed_route &&
1640
(! (rinfo->flags & RIPNG_RTF_CHANGED)))
1643
/* Split horizon. */
1644
if (ri->split_horizon == RIPNG_SPLIT_HORIZON)
1646
/* We perform split horizon for RIPng routes. */
1647
if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
1648
rinfo->ifindex == ifp->ifindex)
1652
/* Preparation for route-map. */
1653
rinfo->metric_set = 0;
1656
* and tag_out are already initialized.
1659
/* Interface route-map */
1660
if (ri->routemap[RIPNG_FILTER_OUT])
1664
ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
1665
(struct prefix *) p, RMAP_RIPNG,
1668
if (ret == RMAP_DENYMATCH)
1670
if (IS_RIPNG_DEBUG_PACKET)
1671
zlog_debug ("RIPng %s/%d is filtered by route-map out",
1672
inet6_ntoa (p->prefix), p->prefixlen);
1678
/* Redistribute route-map. */
1679
if (ripng->route_map[rinfo->type].name)
1683
ret = route_map_apply (ripng->route_map[rinfo->type].map,
1684
(struct prefix *) p, RMAP_RIPNG,
1687
if (ret == RMAP_DENYMATCH)
1689
if (IS_RIPNG_DEBUG_PACKET)
1690
zlog_debug ("RIPng %s/%d is filtered by route-map",
1691
inet6_ntoa (p->prefix), p->prefixlen);
1696
/* When the route-map does not set metric. */
1697
if (! rinfo->metric_set)
1699
/* If the redistribute metric is set. */
1700
if (ripng->route_map[rinfo->type].metric_config
1701
&& rinfo->metric != RIPNG_METRIC_INFINITY)
1703
rinfo->metric_out = ripng->route_map[rinfo->type].metric;
1707
/* If the route is not connected or localy generated
1708
one, use default-metric value */
1709
if (rinfo->type != ZEBRA_ROUTE_RIPNG
1710
&& rinfo->type != ZEBRA_ROUTE_CONNECT
1711
&& rinfo->metric != RIPNG_METRIC_INFINITY)
1712
rinfo->metric_out = ripng->default_metric;
1716
/* Apply offset-list */
1717
if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
1718
ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out);
1720
if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
1721
rinfo->metric_out = RIPNG_METRIC_INFINITY;
1723
/* Perform split-horizon with poisoned reverse
1726
if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) {
1727
if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
1728
rinfo->ifindex == ifp->ifindex)
1729
rinfo->metric_out = RIPNG_METRIC_INFINITY;
1732
/* Add RTE to the list */
1733
ripng_rte_add(ripng_rte_list, p, rinfo, NULL);
1736
/* Process the aggregated RTE entry */
1737
if ((aggregate = rp->aggregate) != NULL &&
1738
aggregate->count > 0 &&
1739
aggregate->suppress == 0)
1741
/* If no route-map are applied, the RTE will be these following
1744
p = (struct prefix_ipv6 *) &rp->p;
1745
aggregate->metric_set = 0;
1746
aggregate->metric_out = aggregate->metric;
1747
aggregate->tag_out = aggregate->tag;
1748
memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out));
1750
/* Apply output filters.*/
1751
ret = ripng_outgoing_filter (p, ri);
1755
/* Interface route-map */
1756
if (ri->routemap[RIPNG_FILTER_OUT])
1759
struct ripng_info newinfo;
1761
/* let's cast the aggregate structure to ripng_info */
1762
memset (&newinfo, 0, sizeof (struct ripng_info));
1763
/* the nexthop is :: */
1764
newinfo.metric = aggregate->metric;
1765
newinfo.metric_out = aggregate->metric_out;
1766
newinfo.tag = aggregate->tag;
1767
newinfo.tag_out = aggregate->tag_out;
1769
ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT],
1770
(struct prefix *) p, RMAP_RIPNG,
1773
if (ret == RMAP_DENYMATCH)
1775
if (IS_RIPNG_DEBUG_PACKET)
1776
zlog_debug ("RIPng %s/%d is filtered by route-map out",
1777
inet6_ntoa (p->prefix), p->prefixlen);
1781
aggregate->metric_out = newinfo.metric_out;
1782
aggregate->tag_out = newinfo.tag_out;
1783
if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out))
1784
aggregate->nexthop_out = newinfo.nexthop_out;
1787
/* There is no redistribute routemap for the aggregated RTE */
1789
/* Changed route only output. */
1790
/* XXX, vincent, in order to increase time convergence,
1791
* it should be announced if a child has changed.
1793
if (route_type == ripng_changed_route)
1796
/* Apply offset-list */
1797
if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
1798
ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out);
1800
if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
1801
aggregate->metric_out = RIPNG_METRIC_INFINITY;
1803
/* Add RTE to the list */
1804
ripng_rte_add(ripng_rte_list, p, NULL, aggregate);
1809
/* Flush the list */
1810
ripng_rte_send(ripng_rte_list, ifp, to);
1811
ripng_rte_free(ripng_rte_list);
1814
/* Create new RIPng instance and set it to global variable. */
1818
/* ripng should be NULL. */
1819
assert (ripng == NULL);
1821
/* Allocaste RIPng instance. */
1822
ripng = XMALLOC (MTYPE_RIPNG, sizeof (struct ripng));
1823
memset (ripng, 0, sizeof (struct ripng));
1825
/* Default version and timer values. */
1826
ripng->version = RIPNG_V1;
1827
ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
1828
ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
1829
ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
1830
ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
1833
ripng->ibuf = stream_new (RIPNG_MAX_PACKET_SIZE * 5);
1834
ripng->obuf = stream_new (RIPNG_MAX_PACKET_SIZE);
1836
/* Initialize RIPng routig table. */
1837
ripng->table = route_table_init ();
1838
ripng->route = route_table_init ();
1839
ripng->aggregate = route_table_init ();
1842
ripng->sock = ripng_make_socket ();
1843
if (ripng->sock < 0)
1847
ripng_event (RIPNG_READ, ripng->sock);
1848
ripng_event (RIPNG_UPDATE_EVENT, 1);
1853
/* Send RIPng request to the interface. */
1855
ripng_request (struct interface *ifp)
1858
struct ripng_packet ripng_packet;
1860
/* In default ripd doesn't send RIP_REQUEST to the loopback interface. */
1861
if (if_is_loopback(ifp))
1864
/* If interface is down, don't send RIP packet. */
1865
if (! if_is_up (ifp))
1868
if (IS_RIPNG_DEBUG_EVENT)
1869
zlog_debug ("RIPng send request to %s", ifp->name);
1871
memset (&ripng_packet, 0, sizeof (ripng_packet));
1872
ripng_packet.command = RIPNG_REQUEST;
1873
ripng_packet.version = RIPNG_V1;
1874
rte = ripng_packet.rte;
1875
rte->metric = RIPNG_METRIC_INFINITY;
1877
return ripng_send_packet ((caddr_t) &ripng_packet, sizeof (ripng_packet),
1883
ripng_update_jitter (int time)
1885
return ((rand () % (time + 1)) - (time / 2));
1889
ripng_event (enum ripng_event event, int sock)
1897
ripng->t_read = thread_add_read (master, ripng_read, NULL, sock);
1899
case RIPNG_UPDATE_EVENT:
1900
if (ripng->t_update)
1902
thread_cancel (ripng->t_update);
1903
ripng->t_update = NULL;
1905
/* Update timer jitter. */
1906
jitter = ripng_update_jitter (ripng->update_time);
1909
thread_add_timer (master, ripng_update, NULL,
1910
sock ? 2 : ripng->update_time + jitter);
1912
case RIPNG_TRIGGERED_UPDATE:
1913
if (ripng->t_triggered_interval)
1915
else if (! ripng->t_triggered_update)
1916
ripng->t_triggered_update =
1917
thread_add_event (master, ripng_triggered_update, NULL, 0);
1924
/* Each route type's strings and default preference.
1925
* FIXME: ISIS? What are these distance values? */
1930
const char *str_long;
1934
{ ZEBRA_ROUTE_SYSTEM, "X", "system", 10},
1935
{ ZEBRA_ROUTE_KERNEL, "K", "kernel", 20},
1936
{ ZEBRA_ROUTE_CONNECT, "C", "connected", 30},
1937
{ ZEBRA_ROUTE_STATIC, "S", "static", 40},
1938
{ ZEBRA_ROUTE_RIP, "R", "rip", 50},
1939
{ ZEBRA_ROUTE_RIPNG, "R", "ripng", 50},
1940
{ ZEBRA_ROUTE_OSPF, "O", "ospf", 60},
1941
{ ZEBRA_ROUTE_OSPF6, "O", "ospf6", 60},
1942
{ ZEBRA_ROUTE_BGP, "B", "bgp", 70},
1945
/* Print out routes update time. */
1947
ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo)
1949
struct timeval timer_now;
1953
char timebuf [TIME_BUF];
1954
struct thread *thread;
1956
gettimeofday (&timer_now, NULL);
1958
if ((thread = rinfo->t_timeout) != NULL)
1960
clock = thread->u.sands.tv_sec - timer_now.tv_sec;
1961
tm = gmtime (&clock);
1962
strftime (timebuf, TIME_BUF, "%M:%S", tm);
1963
vty_out (vty, "%5s", timebuf);
1965
else if ((thread = rinfo->t_garbage_collect) != NULL)
1967
clock = thread->u.sands.tv_sec - timer_now.tv_sec;
1968
tm = gmtime (&clock);
1969
strftime (timebuf, TIME_BUF, "%M:%S", tm);
1970
vty_out (vty, "%5s", timebuf);
1975
ripng_route_subtype_print (struct ripng_info *rinfo)
1980
if (rinfo->suppress)
1983
switch (rinfo->sub_type)
1985
case RIPNG_ROUTE_RTE:
1988
case RIPNG_ROUTE_STATIC:
1991
case RIPNG_ROUTE_DEFAULT:
1994
case RIPNG_ROUTE_REDISTRIBUTE:
1997
case RIPNG_ROUTE_INTERFACE:
2008
DEFUN (show_ipv6_ripng,
2009
show_ipv6_ripng_cmd,
2013
"Show RIPng routes\n")
2015
struct route_node *rp;
2016
struct ripng_info *rinfo;
2017
struct ripng_aggregate *aggregate;
2018
struct prefix_ipv6 *p;
2024
/* Header of display. */
2025
vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s"
2027
" (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
2028
" (i) - interface, (a/S) - aggregated/Suppressed%s%s"
2029
" Network Next Hop Via Metric Tag Time%s",
2030
VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
2031
VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
2033
for (rp = route_top (ripng->table); rp; rp = route_next (rp))
2035
if ((aggregate = rp->aggregate) != NULL)
2037
p = (struct prefix_ipv6 *) &rp->p;
2040
len = vty_out (vty, "R(a) %d/%d %s/%d ",
2041
aggregate->count, aggregate->suppress,
2042
inet6_ntoa (p->prefix), p->prefixlen);
2044
len = vty_out (vty, "R(a) %s/%d ",
2045
inet6_ntoa (p->prefix), p->prefixlen);
2047
vty_out (vty, "%s", VTY_NEWLINE);
2048
vty_out (vty, "%*s", 18, " ");
2050
vty_out (vty, "%*s", 28, " ");
2051
vty_out (vty, "self %2d %3d%s", aggregate->metric,
2056
if ((rinfo = rp->info) != NULL)
2058
p = (struct prefix_ipv6 *) &rp->p;
2061
len = vty_out (vty, "%s(%s) 0/%d %s/%d ",
2062
route_info[rinfo->type].str,
2063
ripng_route_subtype_print(rinfo),
2065
inet6_ntoa (p->prefix), p->prefixlen);
2067
len = vty_out (vty, "%s(%s) %s/%d ",
2068
route_info[rinfo->type].str,
2069
ripng_route_subtype_print(rinfo),
2070
inet6_ntoa (p->prefix), p->prefixlen);
2072
vty_out (vty, "%s", VTY_NEWLINE);
2073
vty_out (vty, "%*s", 18, " ");
2074
len = vty_out (vty, "%s", inet6_ntoa (rinfo->nexthop));
2078
len = vty_out (vty, "%*s", len, " ");
2081
if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2082
(rinfo->sub_type == RIPNG_ROUTE_RTE))
2084
len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex));
2085
} else if (rinfo->metric == RIPNG_METRIC_INFINITY)
2087
len = vty_out (vty, "kill");
2089
len = vty_out (vty, "self");
2093
vty_out (vty, "%*s", len, " ");
2095
vty_out (vty, " %2d %3d ",
2096
rinfo->metric, rinfo->tag);
2099
if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2100
(rinfo->sub_type == RIPNG_ROUTE_RTE))
2102
/* RTE from remote RIP routers */
2103
ripng_vty_out_uptime (vty, rinfo);
2104
} else if (rinfo->metric == RIPNG_METRIC_INFINITY)
2106
/* poisonous reversed routes (gc) */
2107
ripng_vty_out_uptime (vty, rinfo);
2110
vty_out (vty, "%s", VTY_NEWLINE);
2117
/* Return next event time. */
2119
ripng_next_thread_timer (struct thread *thread)
2121
struct timeval timer_now;
2123
gettimeofday (&timer_now, NULL);
2125
return thread->u.sands.tv_sec - timer_now.tv_sec;
2128
DEFUN (show_ipv6_ripng_status,
2129
show_ipv6_ripng_status_cmd,
2130
"show ipv6 ripng status",
2133
"Show RIPng routes\n"
2134
"IPv6 routing protocol process parameters and statistics\n")
2136
struct listnode *node;
2137
struct interface *ifp;
2138
int ripng_network_write (struct vty *, int);
2139
void ripng_redistribute_write (struct vty *, int);
2144
vty_out (vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE);
2145
vty_out (vty, " Sending updates every %ld seconds with +/-50%%,",
2146
ripng->update_time);
2147
vty_out (vty, " next due in %d seconds%s",
2148
ripng_next_thread_timer (ripng->t_update),
2150
vty_out (vty, " Timeout after %ld seconds,", ripng->timeout_time);
2151
vty_out (vty, " garbage collect after %ld seconds%s", ripng->garbage_time,
2154
/* Filtering status show. */
2155
config_show_distribute (vty);
2157
/* Default metric information. */
2158
vty_out (vty, " Default redistribution metric is %d%s",
2159
ripng->default_metric, VTY_NEWLINE);
2161
/* Redistribute information. */
2162
vty_out (vty, " Redistributing:");
2163
ripng_redistribute_write (vty, 0);
2164
vty_out (vty, "%s", VTY_NEWLINE);
2166
vty_out (vty, " Default version control: send version %d,", ripng->version);
2167
vty_out (vty, " receive version %d %s", ripng->version,
2170
vty_out (vty, " Interface Send Recv%s", VTY_NEWLINE);
2172
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2174
struct ripng_interface *ri;
2178
if (ri->enable_network || ri->enable_interface)
2181
vty_out (vty, " %-17s%-3d %-3d%s", ifp->name,
2188
vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE);
2189
ripng_network_write (vty, 0);
2191
vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE);
2192
vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE);
2193
ripng_peer_display (vty);
2198
DEFUN (router_ripng,
2201
"Enable a routing process\n"
2202
"Make RIPng instance command\n")
2206
vty->node = RIPNG_NODE;
2210
ret = ripng_create ();
2212
/* Notice to user we couldn't create RIPng. */
2215
zlog_warn ("can't create RIPng");
2223
DEFUN (no_router_ripng,
2224
no_router_ripng_cmd,
2227
"Enable a routing process\n"
2228
"Make RIPng instance command\n")
2238
"Static route setup\n"
2239
"Set static RIPng route announcement\n")
2242
struct prefix_ipv6 p;
2243
struct route_node *rp;
2245
ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2248
vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2251
apply_mask_ipv6 (&p);
2253
rp = route_node_get (ripng->route, (struct prefix *) &p);
2256
vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);
2257
route_unlock_node (rp);
2260
rp->info = (void *)1;
2262
ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL);
2267
DEFUN (no_ripng_route,
2269
"no route IPV6ADDR",
2271
"Static route setup\n"
2272
"Delete static RIPng route announcement\n")
2275
struct prefix_ipv6 p;
2276
struct route_node *rp;
2278
ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2281
vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2284
apply_mask_ipv6 (&p);
2286
rp = route_node_lookup (ripng->route, (struct prefix *) &p);
2289
vty_out (vty, "Can't find static route.%s", VTY_NEWLINE);
2293
ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0);
2294
route_unlock_node (rp);
2297
route_unlock_node (rp);
2302
DEFUN (ripng_aggregate_address,
2303
ripng_aggregate_address_cmd,
2304
"aggregate-address X:X::X:X/M",
2305
"Set aggregate RIPng route announcement\n"
2306
"Aggregate network\n")
2310
struct route_node *node;
2312
ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *)&p);
2315
vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2319
/* Check aggregate alredy exist or not. */
2320
node = route_node_get (ripng->aggregate, &p);
2323
vty_out (vty, "There is already same aggregate route.%s", VTY_NEWLINE);
2324
route_unlock_node (node);
2327
node->info = (void *)1;
2329
ripng_aggregate_add (&p);
2334
DEFUN (no_ripng_aggregate_address,
2335
no_ripng_aggregate_address_cmd,
2336
"no aggregate-address X:X::X:X/M",
2338
"Delete aggregate RIPng route announcement\n"
2339
"Aggregate network")
2343
struct route_node *rn;
2345
ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &p);
2348
vty_out (vty, "Malformed address%s", VTY_NEWLINE);
2352
rn = route_node_lookup (ripng->aggregate, &p);
2355
vty_out (vty, "Can't find aggregate route.%s", VTY_NEWLINE);
2358
route_unlock_node (rn);
2360
route_unlock_node (rn);
2362
ripng_aggregate_delete (&p);
2367
DEFUN (ripng_default_metric,
2368
ripng_default_metric_cmd,
2369
"default-metric <1-16>",
2370
"Set a metric of redistribute routes\n"
2375
ripng->default_metric = atoi (argv[0]);
2380
DEFUN (no_ripng_default_metric,
2381
no_ripng_default_metric_cmd,
2382
"no default-metric",
2384
"Set a metric of redistribute routes\n"
2389
ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT;
2394
ALIAS (no_ripng_default_metric,
2395
no_ripng_default_metric_val_cmd,
2396
"no default-metric <1-16>",
2398
"Set a metric of redistribute routes\n"
2402
/* RIPng update timer setup. */
2403
DEFUN (ripng_update_timer,
2404
ripng_update_timer_cmd,
2405
"update-timer SECOND",
2406
"Set RIPng update timer in seconds\n"
2409
unsigned long update;
2410
char *endptr = NULL;
2412
update = strtoul (argv[0], &endptr, 10);
2413
if (update == ULONG_MAX || *endptr != '\0')
2415
vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2419
ripng->update_time = update;
2421
ripng_event (RIPNG_UPDATE_EVENT, 0);
2425
DEFUN (no_ripng_update_timer,
2426
no_ripng_update_timer_cmd,
2427
"no update-timer SECOND",
2429
"Unset RIPng update timer in seconds\n"
2432
ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2433
ripng_event (RIPNG_UPDATE_EVENT, 0);
2437
/* RIPng timeout timer setup. */
2438
DEFUN (ripng_timeout_timer,
2439
ripng_timeout_timer_cmd,
2440
"timeout-timer SECOND",
2441
"Set RIPng timeout timer in seconds\n"
2444
unsigned long timeout;
2445
char *endptr = NULL;
2447
timeout = strtoul (argv[0], &endptr, 10);
2448
if (timeout == ULONG_MAX || *endptr != '\0')
2450
vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2454
ripng->timeout_time = timeout;
2459
DEFUN (no_ripng_timeout_timer,
2460
no_ripng_timeout_timer_cmd,
2461
"no timeout-timer SECOND",
2463
"Unset RIPng timeout timer in seconds\n"
2466
ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2470
/* RIPng garbage timer setup. */
2471
DEFUN (ripng_garbage_timer,
2472
ripng_garbage_timer_cmd,
2473
"garbage-timer SECOND",
2474
"Set RIPng garbage timer in seconds\n"
2477
unsigned long garbage;
2478
char *endptr = NULL;
2480
garbage = strtoul (argv[0], &endptr, 10);
2481
if (garbage == ULONG_MAX || *endptr != '\0')
2483
vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2487
ripng->garbage_time = garbage;
2492
DEFUN (no_ripng_garbage_timer,
2493
no_ripng_garbage_timer_cmd,
2494
"no garbage-timer SECOND",
2496
"Unset RIPng garbage timer in seconds\n"
2499
ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2504
DEFUN (ripng_timers,
2506
"timers basic <0-65535> <0-65535> <0-65535>",
2507
"RIPng timers setup\n"
2509
"Routing table update timer value in second. Default is 30.\n"
2510
"Routing information timeout timer. Default is 180.\n"
2511
"Garbage collection timer. Default is 120.\n")
2513
unsigned long update;
2514
unsigned long timeout;
2515
unsigned long garbage;
2516
char *endptr = NULL;
2518
update = strtoul (argv[0], &endptr, 10);
2519
if (update == ULONG_MAX || *endptr != '\0')
2521
vty_out (vty, "update timer value error%s", VTY_NEWLINE);
2525
timeout = strtoul (argv[1], &endptr, 10);
2526
if (timeout == ULONG_MAX || *endptr != '\0')
2528
vty_out (vty, "timeout timer value error%s", VTY_NEWLINE);
2532
garbage = strtoul (argv[2], &endptr, 10);
2533
if (garbage == ULONG_MAX || *endptr != '\0')
2535
vty_out (vty, "garbage timer value error%s", VTY_NEWLINE);
2539
/* Set each timer value. */
2540
ripng->update_time = update;
2541
ripng->timeout_time = timeout;
2542
ripng->garbage_time = garbage;
2544
/* Reset update timer thread. */
2545
ripng_event (RIPNG_UPDATE_EVENT, 0);
2550
DEFUN (no_ripng_timers,
2551
no_ripng_timers_cmd,
2554
"RIPng timers setup\n"
2557
/* Set each timer value to the default. */
2558
ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2559
ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2560
ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2562
/* Reset update timer thread. */
2563
ripng_event (RIPNG_UPDATE_EVENT, 0);
2568
ALIAS (no_ripng_timers,
2569
no_ripng_timers_val_cmd,
2570
"no timers basic <0-65535> <0-65535> <0-65535>",
2572
"RIPng timers setup\n"
2574
"Routing table update timer value in second. Default is 30.\n"
2575
"Routing information timeout timer. Default is 180.\n"
2576
"Garbage collection timer. Default is 120.\n")
2578
DEFUN (show_ipv6_protocols, show_ipv6_protocols_cmd,
2579
"show ipv6 protocols",
2582
"Routing protocol information")
2587
vty_out (vty, "Routing Protocol is \"ripng\"%s", VTY_NEWLINE);
2589
vty_out (vty, "Sending updates every %ld seconds, next due in %d seconds%s",
2590
ripng->update_time, 0,
2593
vty_out (vty, "Timerout after %ld seconds, garbage correct %ld%s",
2594
ripng->timeout_time,
2595
ripng->garbage_time,
2598
vty_out (vty, "Outgoing update filter list for all interfaces is not set");
2599
vty_out (vty, "Incoming update filter list for all interfaces is not set");
2604
/* Please be carefull to use this command. */
2605
DEFUN (ripng_default_information_originate,
2606
ripng_default_information_originate_cmd,
2607
"default-information originate",
2608
"Default route information\n"
2609
"Distribute default route\n")
2611
struct prefix_ipv6 p;
2613
if (! ripng ->default_information) {
2614
ripng->default_information = 1;
2616
str2prefix_ipv6 ("::/0", &p);
2617
ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL);
2623
DEFUN (no_ripng_default_information_originate,
2624
no_ripng_default_information_originate_cmd,
2625
"no default-information originate",
2627
"Default route information\n"
2628
"Distribute default route\n")
2630
struct prefix_ipv6 p;
2632
if (ripng->default_information) {
2633
ripng->default_information = 0;
2635
str2prefix_ipv6 ("::/0", &p);
2636
ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0);
2642
/* RIPng configuration write function. */
2644
ripng_config_write (struct vty *vty)
2646
int ripng_network_write (struct vty *, int);
2647
void ripng_redistribute_write (struct vty *, int);
2649
struct route_node *rp;
2655
vty_out (vty, "router ripng%s", VTY_NEWLINE);
2657
if (ripng->default_information)
2658
vty_out (vty, " default-information originate%s", VTY_NEWLINE);
2660
ripng_network_write (vty, 1);
2662
/* RIPng default metric configuration */
2663
if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT)
2664
vty_out (vty, " default-metric %d%s",
2665
ripng->default_metric, VTY_NEWLINE);
2667
ripng_redistribute_write (vty, 1);
2669
/* RIP offset-list configuration. */
2670
config_write_ripng_offset_list (vty);
2672
/* RIPng aggregate routes. */
2673
for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
2674
if (rp->info != NULL)
2675
vty_out (vty, " aggregate-address %s/%d%s",
2676
inet6_ntoa (rp->p.u.prefix6),
2681
/* RIPng static routes. */
2682
for (rp = route_top (ripng->route); rp; rp = route_next (rp))
2683
if (rp->info != NULL)
2684
vty_out (vty, " route %s/%d%s", inet6_ntoa (rp->p.u.prefix6),
2688
/* RIPng timers configuration. */
2689
if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT ||
2690
ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT ||
2691
ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
2693
vty_out (vty, " timers basic %ld %ld %ld%s",
2695
ripng->timeout_time,
2696
ripng->garbage_time,
2700
if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT)
2701
vty_out (vty, " update-timer %d%s", ripng->update_time,
2703
if (ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT)
2704
vty_out (vty, " timeout-timer %d%s", ripng->timeout_time,
2706
if (ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT)
2707
vty_out (vty, " garbage-timer %d%s", ripng->garbage_time,
2711
write += config_write_distribute (vty);
2713
write += config_write_if_rmap (vty);
2720
/* RIPng node structure. */
2721
struct cmd_node cmd_ripng_node =
2724
"%s(config-router)# ",
2729
ripng_distribute_update (struct distribute *dist)
2731
struct interface *ifp;
2732
struct ripng_interface *ri;
2733
struct access_list *alist;
2734
struct prefix_list *plist;
2739
ifp = if_lookup_by_name (dist->ifname);
2745
if (dist->list[DISTRIBUTE_IN])
2747
alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_IN]);
2749
ri->list[RIPNG_FILTER_IN] = alist;
2751
ri->list[RIPNG_FILTER_IN] = NULL;
2754
ri->list[RIPNG_FILTER_IN] = NULL;
2756
if (dist->list[DISTRIBUTE_OUT])
2758
alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_OUT]);
2760
ri->list[RIPNG_FILTER_OUT] = alist;
2762
ri->list[RIPNG_FILTER_OUT] = NULL;
2765
ri->list[RIPNG_FILTER_OUT] = NULL;
2767
if (dist->prefix[DISTRIBUTE_IN])
2769
plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_IN]);
2771
ri->prefix[RIPNG_FILTER_IN] = plist;
2773
ri->prefix[RIPNG_FILTER_IN] = NULL;
2776
ri->prefix[RIPNG_FILTER_IN] = NULL;
2778
if (dist->prefix[DISTRIBUTE_OUT])
2780
plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_OUT]);
2782
ri->prefix[RIPNG_FILTER_OUT] = plist;
2784
ri->prefix[RIPNG_FILTER_OUT] = NULL;
2787
ri->prefix[RIPNG_FILTER_OUT] = NULL;
2791
ripng_distribute_update_interface (struct interface *ifp)
2793
struct distribute *dist;
2795
dist = distribute_lookup (ifp->name);
2797
ripng_distribute_update (dist);
2800
/* Update all interface's distribute list. */
2802
ripng_distribute_update_all (struct prefix_list *notused)
2804
struct interface *ifp;
2805
struct listnode *node;
2807
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2808
ripng_distribute_update_interface (ifp);
2812
ripng_distribute_update_all_wrapper (struct access_list *notused)
2814
ripng_distribute_update_all(NULL);
2817
/* delete all the added ripng routes. */
2822
struct route_node *rp;
2823
struct ripng_info *rinfo;
2826
/* Clear RIPng routes */
2827
for (rp = route_top (ripng->table); rp; rp = route_next (rp)) {
2828
if ((rinfo = rp->info) != NULL) {
2829
if ((rinfo->type == ZEBRA_ROUTE_RIPNG) &&
2830
(rinfo->sub_type == RIPNG_ROUTE_RTE))
2831
ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p,
2832
&rinfo->nexthop, rinfo->metric);
2834
RIPNG_TIMER_OFF (rinfo->t_timeout);
2835
RIPNG_TIMER_OFF (rinfo->t_garbage_collect);
2838
route_unlock_node (rp);
2840
ripng_info_free(rinfo);
2844
/* Cancel the RIPng timers */
2845
RIPNG_TIMER_OFF (ripng->t_update);
2846
RIPNG_TIMER_OFF (ripng->t_triggered_update);
2847
RIPNG_TIMER_OFF (ripng->t_triggered_interval);
2849
/* Cancel the read thread */
2850
if (ripng->t_read) {
2851
thread_cancel (ripng->t_read);
2852
ripng->t_read = NULL;
2855
/* Close the RIPng socket */
2856
if (ripng->sock >= 0) {
2861
/* Static RIPng route configuration. */
2862
for (rp = route_top (ripng->route); rp; rp = route_next (rp))
2865
route_unlock_node (rp);
2868
/* RIPng aggregated prefixes */
2869
for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp))
2872
route_unlock_node (rp);
2875
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2876
if (ripng->route_map[i].name)
2877
free (ripng->route_map[i].name);
2879
XFREE (MTYPE_ROUTE_TABLE, ripng->table);
2880
XFREE (MTYPE_ROUTE_TABLE, ripng->route);
2881
XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate);
2883
XFREE (MTYPE_RIPNG, ripng);
2887
ripng_clean_network();
2888
ripng_passive_interface_clean ();
2889
ripng_offset_clean ();
2890
ripng_interface_clean ();
2891
ripng_redistribute_clean ();
2894
/* Reset all values to the default settings. */
2898
/* Call ripd related reset functions. */
2899
ripng_debug_reset ();
2900
ripng_route_map_reset ();
2902
/* Call library reset functions. */
2904
access_list_reset ();
2905
prefix_list_reset ();
2907
distribute_list_reset ();
2909
ripng_interface_reset ();
2911
ripng_zclient_reset ();
2915
ripng_if_rmap_update (struct if_rmap *if_rmap)
2917
struct interface *ifp;
2918
struct ripng_interface *ri;
2919
struct route_map *rmap;
2921
ifp = if_lookup_by_name (if_rmap->ifname);
2927
if (if_rmap->routemap[IF_RMAP_IN])
2929
rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
2931
ri->routemap[IF_RMAP_IN] = rmap;
2933
ri->routemap[IF_RMAP_IN] = NULL;
2936
ri->routemap[RIPNG_FILTER_IN] = NULL;
2938
if (if_rmap->routemap[IF_RMAP_OUT])
2940
rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
2942
ri->routemap[IF_RMAP_OUT] = rmap;
2944
ri->routemap[IF_RMAP_OUT] = NULL;
2947
ri->routemap[RIPNG_FILTER_OUT] = NULL;
2951
ripng_if_rmap_update_interface (struct interface *ifp)
2953
struct if_rmap *if_rmap;
2955
if_rmap = if_rmap_lookup (ifp->name);
2957
ripng_if_rmap_update (if_rmap);
2961
ripng_routemap_update_redistribute (void)
2967
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2969
if (ripng->route_map[i].name)
2970
ripng->route_map[i].map =
2971
route_map_lookup_by_name (ripng->route_map[i].name);
2977
ripng_routemap_update (const char *unused)
2979
struct interface *ifp;
2980
struct listnode *node;
2982
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
2983
ripng_if_rmap_update_interface (ifp);
2985
ripng_routemap_update_redistribute ();
2988
/* Initialize ripng structure and set commands. */
2993
srand (time (NULL));
2995
/* Install RIPNG_NODE. */
2996
install_node (&cmd_ripng_node, ripng_config_write);
2998
/* Install ripng commands. */
2999
install_element (VIEW_NODE, &show_ipv6_ripng_cmd);
3000
install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd);
3002
install_element (ENABLE_NODE, &show_ipv6_ripng_cmd);
3003
install_element (ENABLE_NODE, &show_ipv6_ripng_status_cmd);
3005
install_element (CONFIG_NODE, &router_ripng_cmd);
3006
install_element (CONFIG_NODE, &no_router_ripng_cmd);
3008
install_default (RIPNG_NODE);
3009
install_element (RIPNG_NODE, &ripng_route_cmd);
3010
install_element (RIPNG_NODE, &no_ripng_route_cmd);
3011
install_element (RIPNG_NODE, &ripng_aggregate_address_cmd);
3012
install_element (RIPNG_NODE, &no_ripng_aggregate_address_cmd);
3014
install_element (RIPNG_NODE, &ripng_default_metric_cmd);
3015
install_element (RIPNG_NODE, &no_ripng_default_metric_cmd);
3016
install_element (RIPNG_NODE, &no_ripng_default_metric_val_cmd);
3018
install_element (RIPNG_NODE, &ripng_timers_cmd);
3019
install_element (RIPNG_NODE, &no_ripng_timers_cmd);
3020
install_element (RIPNG_NODE, &no_ripng_timers_val_cmd);
3022
install_element (RIPNG_NODE, &ripng_update_timer_cmd);
3023
install_element (RIPNG_NODE, &no_ripng_update_timer_cmd);
3024
install_element (RIPNG_NODE, &ripng_timeout_timer_cmd);
3025
install_element (RIPNG_NODE, &no_ripng_timeout_timer_cmd);
3026
install_element (RIPNG_NODE, &ripng_garbage_timer_cmd);
3027
install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd);
3030
install_element (RIPNG_NODE, &ripng_default_information_originate_cmd);
3031
install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd);
3034
ripng_debug_init ();
3036
/* Access list install. */
3037
access_list_init ();
3038
access_list_add_hook (ripng_distribute_update_all_wrapper);
3039
access_list_delete_hook (ripng_distribute_update_all_wrapper);
3041
/* Prefix list initialize.*/
3042
prefix_list_init ();
3043
prefix_list_add_hook (ripng_distribute_update_all);
3044
prefix_list_delete_hook (ripng_distribute_update_all);
3046
/* Distribute list install. */
3047
distribute_list_init (RIPNG_NODE);
3048
distribute_list_add_hook (ripng_distribute_update);
3049
distribute_list_delete_hook (ripng_distribute_update);
3051
/* Route-map for interface. */
3052
ripng_route_map_init ();
3053
ripng_offset_init ();
3055
route_map_add_hook (ripng_routemap_update);
3056
route_map_delete_hook (ripng_routemap_update);
3058
if_rmap_init (RIPNG_NODE);
3059
if_rmap_hook_add (ripng_if_rmap_update);
3060
if_rmap_hook_delete (ripng_if_rmap_update);