]> git.proxmox.com Git - mirror_frr.git/blob - ripngd/ripngd.c
ripngd: add VRF support
[mirror_frr.git] / ripngd / ripngd.c
1 /* 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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "prefix.h"
24 #include "filter.h"
25 #include "log.h"
26 #include "thread.h"
27 #include "memory.h"
28 #include "if.h"
29 #include "stream.h"
30 #include "agg_table.h"
31 #include "command.h"
32 #include "sockopt.h"
33 #include "distribute.h"
34 #include "plist.h"
35 #include "routemap.h"
36 #include "if_rmap.h"
37 #include "privs.h"
38 #include "lib_errors.h"
39 #include "northbound_cli.h"
40
41 #include "ripngd/ripngd.h"
42 #include "ripngd/ripng_route.h"
43 #include "ripngd/ripng_debug.h"
44 #include "ripngd/ripng_nexthop.h"
45
46 enum { ripng_all_route,
47 ripng_changed_route,
48 };
49
50 static void ripng_distribute_update(struct distribute_ctx *ctx,
51 struct distribute *dist);
52
53 /* Prototypes. */
54 void ripng_output_process(struct interface *, struct sockaddr_in6 *, int);
55 static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf,
56 int sock);
57 static void ripng_instance_disable(struct ripng *ripng);
58
59 int ripng_triggered_update(struct thread *);
60
61 /* Generate rb-tree of RIPng instances. */
62 static inline int ripng_instance_compare(const struct ripng *a,
63 const struct ripng *b)
64 {
65 return strcmp(a->vrf_name, b->vrf_name);
66 }
67 RB_GENERATE(ripng_instance_head, ripng, entry, ripng_instance_compare)
68
69 struct ripng_instance_head ripng_instances = RB_INITIALIZER(&ripng_instances);
70
71 /* RIPng next hop specification. */
72 struct ripng_nexthop {
73 enum ripng_nexthop_type {
74 RIPNG_NEXTHOP_UNSPEC,
75 RIPNG_NEXTHOP_ADDRESS
76 } flag;
77 struct in6_addr address;
78 };
79
80 int ripng_route_rte(struct ripng_info *rinfo)
81 {
82 return (rinfo->type == ZEBRA_ROUTE_RIPNG
83 && rinfo->sub_type == RIPNG_ROUTE_RTE);
84 }
85
86 /* Allocate new ripng information. */
87 struct ripng_info *ripng_info_new()
88 {
89 struct ripng_info *new;
90
91 new = XCALLOC(MTYPE_RIPNG_ROUTE, sizeof(struct ripng_info));
92 return new;
93 }
94
95 /* Free ripng information. */
96 void ripng_info_free(struct ripng_info *rinfo)
97 {
98 XFREE(MTYPE_RIPNG_ROUTE, rinfo);
99 }
100
101 struct ripng *ripng_info_get_instance(const struct ripng_info *rinfo)
102 {
103 return agg_get_table_info(agg_get_table(rinfo->rp));
104 }
105
106 /* Create ripng socket. */
107 int ripng_make_socket(struct vrf *vrf)
108 {
109 int ret;
110 int sock;
111 struct sockaddr_in6 ripaddr;
112 const char *vrf_dev = NULL;
113
114 /* Make datagram socket. */
115 if (vrf->vrf_id != VRF_DEFAULT)
116 vrf_dev = vrf->name;
117 frr_elevate_privs(&ripngd_privs)
118 {
119 sock = vrf_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
120 vrf->vrf_id, vrf_dev);
121 if (sock < 0) {
122 flog_err_sys(EC_LIB_SOCKET,
123 "Cannot create UDP socket: %s",
124 safe_strerror(errno));
125 return -1;
126 }
127 }
128
129 sockopt_reuseaddr(sock);
130 sockopt_reuseport(sock);
131 setsockopt_so_recvbuf(sock, 8096);
132 ret = setsockopt_ipv6_pktinfo(sock, 1);
133 if (ret < 0)
134 goto error;
135 #ifdef IPTOS_PREC_INTERNETCONTROL
136 ret = setsockopt_ipv6_tclass(sock, IPTOS_PREC_INTERNETCONTROL);
137 if (ret < 0)
138 goto error;
139 #endif
140 ret = setsockopt_ipv6_multicast_hops(sock, 255);
141 if (ret < 0)
142 goto error;
143 ret = setsockopt_ipv6_multicast_loop(sock, 0);
144 if (ret < 0)
145 goto error;
146 ret = setsockopt_ipv6_hoplimit(sock, 1);
147 if (ret < 0)
148 goto error;
149
150 memset(&ripaddr, 0, sizeof(ripaddr));
151 ripaddr.sin6_family = AF_INET6;
152 #ifdef SIN6_LEN
153 ripaddr.sin6_len = sizeof(struct sockaddr_in6);
154 #endif /* SIN6_LEN */
155 ripaddr.sin6_port = htons(RIPNG_PORT_DEFAULT);
156
157 frr_elevate_privs(&ripngd_privs) {
158 ret = bind(sock, (struct sockaddr *)&ripaddr, sizeof(ripaddr));
159 if (ret < 0) {
160 zlog_err("Can't bind ripng socket: %s.",
161 safe_strerror(errno));
162 goto error;
163 }
164 }
165 return sock;
166
167 error:
168 close(sock);
169 return ret;
170 }
171
172 /* Send RIPng packet. */
173 int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to,
174 struct interface *ifp)
175 {
176 struct ripng_interface *ri = ifp->info;
177 struct ripng *ripng = ri->ripng;
178 int ret;
179 struct msghdr msg;
180 struct iovec iov;
181 struct cmsghdr *cmsgptr;
182 char adata[256] = {};
183 struct in6_pktinfo *pkt;
184 struct sockaddr_in6 addr;
185
186 if (IS_RIPNG_DEBUG_SEND) {
187 if (to)
188 zlog_debug("send to %s", inet6_ntoa(to->sin6_addr));
189 zlog_debug(" send interface %s", ifp->name);
190 zlog_debug(" send packet size %d", bufsize);
191 }
192
193 memset(&addr, 0, sizeof(struct sockaddr_in6));
194 addr.sin6_family = AF_INET6;
195 #ifdef SIN6_LEN
196 addr.sin6_len = sizeof(struct sockaddr_in6);
197 #endif /* SIN6_LEN */
198 addr.sin6_flowinfo = htonl(RIPNG_PRIORITY_DEFAULT);
199
200 /* When destination is specified. */
201 if (to != NULL) {
202 addr.sin6_addr = to->sin6_addr;
203 addr.sin6_port = to->sin6_port;
204 } else {
205 inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr);
206 addr.sin6_port = htons(RIPNG_PORT_DEFAULT);
207 }
208
209 memset(&msg, 0, sizeof(msg));
210 msg.msg_name = (void *)&addr;
211 msg.msg_namelen = sizeof(struct sockaddr_in6);
212 msg.msg_iov = &iov;
213 msg.msg_iovlen = 1;
214 msg.msg_control = (void *)adata;
215 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
216
217 iov.iov_base = buf;
218 iov.iov_len = bufsize;
219
220 cmsgptr = (struct cmsghdr *)adata;
221 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
222 cmsgptr->cmsg_level = IPPROTO_IPV6;
223 cmsgptr->cmsg_type = IPV6_PKTINFO;
224
225 pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
226 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
227 pkt->ipi6_ifindex = ifp->ifindex;
228
229 ret = sendmsg(ripng->sock, &msg, 0);
230
231 if (ret < 0) {
232 if (to)
233 flog_err_sys(EC_LIB_SOCKET,
234 "RIPng send fail on %s to %s: %s",
235 ifp->name, inet6_ntoa(to->sin6_addr),
236 safe_strerror(errno));
237 else
238 flog_err_sys(EC_LIB_SOCKET, "RIPng send fail on %s: %s",
239 ifp->name, safe_strerror(errno));
240 }
241
242 return ret;
243 }
244
245 /* Receive UDP RIPng packet from socket. */
246 static int ripng_recv_packet(int sock, uint8_t *buf, int bufsize,
247 struct sockaddr_in6 *from, ifindex_t *ifindex,
248 int *hoplimit)
249 {
250 int ret;
251 struct msghdr msg;
252 struct iovec iov;
253 struct cmsghdr *cmsgptr;
254 struct in6_addr dst = {.s6_addr = {0}};
255
256 memset(&dst, 0, sizeof(struct in6_addr));
257
258 /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this
259 point I can't determine size of cmsghdr */
260 char adata[1024];
261
262 /* Fill in message and iovec. */
263 memset(&msg, 0, sizeof(msg));
264 msg.msg_name = (void *)from;
265 msg.msg_namelen = sizeof(struct sockaddr_in6);
266 msg.msg_iov = &iov;
267 msg.msg_iovlen = 1;
268 msg.msg_control = (void *)adata;
269 msg.msg_controllen = sizeof adata;
270 iov.iov_base = buf;
271 iov.iov_len = bufsize;
272
273 /* If recvmsg fail return minus value. */
274 ret = recvmsg(sock, &msg, 0);
275 if (ret < 0)
276 return ret;
277
278 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
279 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
280 /* I want interface index which this packet comes from. */
281 if (cmsgptr->cmsg_level == IPPROTO_IPV6
282 && cmsgptr->cmsg_type == IPV6_PKTINFO) {
283 struct in6_pktinfo *ptr;
284
285 ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
286 *ifindex = ptr->ipi6_ifindex;
287 dst = ptr->ipi6_addr;
288
289 if (*ifindex == 0)
290 zlog_warn(
291 "Interface index returned by IPV6_PKTINFO is zero");
292 }
293
294 /* Incoming packet's multicast hop limit. */
295 if (cmsgptr->cmsg_level == IPPROTO_IPV6
296 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) {
297 int *phoplimit = (int *)CMSG_DATA(cmsgptr);
298 *hoplimit = *phoplimit;
299 }
300 }
301
302 /* Hoplimit check shold be done when destination address is
303 multicast address. */
304 if (!IN6_IS_ADDR_MULTICAST(&dst))
305 *hoplimit = -1;
306
307 return ret;
308 }
309
310 /* Dump rip packet */
311 void ripng_packet_dump(struct ripng_packet *packet, int size,
312 const char *sndrcv)
313 {
314 caddr_t lim;
315 struct rte *rte;
316 const char *command_str;
317
318 /* Set command string. */
319 if (packet->command == RIPNG_REQUEST)
320 command_str = "request";
321 else if (packet->command == RIPNG_RESPONSE)
322 command_str = "response";
323 else
324 command_str = "unknown";
325
326 /* Dump packet header. */
327 zlog_debug("%s %s version %d packet size %d", sndrcv, command_str,
328 packet->version, size);
329
330 /* Dump each routing table entry. */
331 rte = packet->rte;
332
333 for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) {
334 if (rte->metric == RIPNG_METRIC_NEXTHOP)
335 zlog_debug(" nexthop %s/%d", inet6_ntoa(rte->addr),
336 rte->prefixlen);
337 else
338 zlog_debug(" %s/%d metric %d tag %" ROUTE_TAG_PRI,
339 inet6_ntoa(rte->addr), rte->prefixlen,
340 rte->metric, (route_tag_t)ntohs(rte->tag));
341 }
342 }
343
344 /* RIPng next hop address RTE (Route Table Entry). */
345 static void ripng_nexthop_rte(struct rte *rte, struct sockaddr_in6 *from,
346 struct ripng_nexthop *nexthop)
347 {
348 char buf[INET6_BUFSIZ];
349
350 /* Logging before checking RTE. */
351 if (IS_RIPNG_DEBUG_RECV)
352 zlog_debug("RIPng nexthop RTE address %s tag %" ROUTE_TAG_PRI
353 " prefixlen %d",
354 inet6_ntoa(rte->addr), (route_tag_t)ntohs(rte->tag),
355 rte->prefixlen);
356
357 /* RFC2080 2.1.1 Next Hop:
358 The route tag and prefix length in the next hop RTE must be
359 set to zero on sending and ignored on receiption. */
360 if (ntohs(rte->tag) != 0)
361 zlog_warn(
362 "RIPng nexthop RTE with non zero tag value %" ROUTE_TAG_PRI
363 " from %s",
364 (route_tag_t)ntohs(rte->tag),
365 inet6_ntoa(from->sin6_addr));
366
367 if (rte->prefixlen != 0)
368 zlog_warn(
369 "RIPng nexthop RTE with non zero prefixlen value %d from %s",
370 rte->prefixlen, inet6_ntoa(from->sin6_addr));
371
372 /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a
373 next hop RTE indicates that the next hop address should be the
374 originator of the RIPng advertisement. An address specified as a
375 next hop must be a link-local address. */
376 if (IN6_IS_ADDR_UNSPECIFIED(&rte->addr)) {
377 nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
378 memset(&nexthop->address, 0, sizeof(struct in6_addr));
379 return;
380 }
381
382 if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) {
383 nexthop->flag = RIPNG_NEXTHOP_ADDRESS;
384 IPV6_ADDR_COPY(&nexthop->address, &rte->addr);
385 return;
386 }
387
388 /* The purpose of the next hop RTE is to eliminate packets being
389 routed through extra hops in the system. It is particularly useful
390 when RIPng is not being run on all of the routers on a network.
391 Note that next hop RTE is "advisory". That is, if the provided
392 information is ignored, a possibly sub-optimal, but absolutely
393 valid, route may be taken. If the received next hop address is not
394 a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
395 zlog_warn("RIPng nexthop RTE with non link-local address %s from %s",
396 inet6_ntoa(rte->addr),
397 inet_ntop(AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ));
398
399 nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
400 memset(&nexthop->address, 0, sizeof(struct in6_addr));
401
402 return;
403 }
404
405 /* If ifp has same link-local address then return 1. */
406 static int ripng_lladdr_check(struct interface *ifp, struct in6_addr *addr)
407 {
408 struct listnode *node;
409 struct connected *connected;
410 struct prefix *p;
411
412 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
413 p = connected->address;
414
415 if (p->family == AF_INET6
416 && IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6)
417 && IN6_ARE_ADDR_EQUAL(&p->u.prefix6, addr))
418 return 1;
419 }
420 return 0;
421 }
422
423 /* RIPng route garbage collect timer. */
424 static int ripng_garbage_collect(struct thread *t)
425 {
426 struct ripng_info *rinfo;
427 struct agg_node *rp;
428
429 rinfo = THREAD_ARG(t);
430 rinfo->t_garbage_collect = NULL;
431
432 /* Off timeout timer. */
433 RIPNG_TIMER_OFF(rinfo->t_timeout);
434
435 /* Get route_node pointer. */
436 rp = rinfo->rp;
437
438 /* Unlock route_node. */
439 listnode_delete(rp->info, rinfo);
440 if (list_isempty((struct list *)rp->info)) {
441 list_delete((struct list **)&rp->info);
442 agg_unlock_node(rp);
443 }
444
445 /* Free RIPng routing information. */
446 ripng_info_free(rinfo);
447
448 return 0;
449 }
450
451 static void ripng_timeout_update(struct ripng *ripng, struct ripng_info *rinfo);
452
453 /* Add new route to the ECMP list.
454 * RETURN: the new entry added in the list, or NULL if it is not the first
455 * entry and ECMP is not allowed.
456 */
457 struct ripng_info *ripng_ecmp_add(struct ripng *ripng,
458 struct ripng_info *rinfo_new)
459 {
460 struct agg_node *rp = rinfo_new->rp;
461 struct ripng_info *rinfo = NULL;
462 struct list *list = NULL;
463
464 if (rp->info == NULL)
465 rp->info = list_new();
466 list = (struct list *)rp->info;
467
468 /* If ECMP is not allowed and some entry already exists in the list,
469 * do nothing. */
470 if (listcount(list) && !ripng->ecmp)
471 return NULL;
472
473 rinfo = ripng_info_new();
474 memcpy(rinfo, rinfo_new, sizeof(struct ripng_info));
475 listnode_add(list, rinfo);
476
477 if (ripng_route_rte(rinfo)) {
478 ripng_timeout_update(ripng, rinfo);
479 ripng_zebra_ipv6_add(ripng, rp);
480 }
481
482 ripng_aggregate_increment(rp, rinfo);
483
484 /* Set the route change flag on the first entry. */
485 rinfo = listgetdata(listhead(list));
486 SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
487
488 /* Signal the output process to trigger an update. */
489 ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
490
491 return rinfo;
492 }
493
494 /* Replace the ECMP list with the new route.
495 * RETURN: the new entry added in the list
496 */
497 struct ripng_info *ripng_ecmp_replace(struct ripng *ripng,
498 struct ripng_info *rinfo_new)
499 {
500 struct agg_node *rp = rinfo_new->rp;
501 struct list *list = (struct list *)rp->info;
502 struct ripng_info *rinfo = NULL, *tmp_rinfo = NULL;
503 struct listnode *node = NULL, *nextnode = NULL;
504
505 if (list == NULL || listcount(list) == 0)
506 return ripng_ecmp_add(ripng, rinfo_new);
507
508 /* Get the first entry */
509 rinfo = listgetdata(listhead(list));
510
511 /* Learnt route replaced by a local one. Delete it from zebra. */
512 if (ripng_route_rte(rinfo) && !ripng_route_rte(rinfo_new))
513 if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
514 ripng_zebra_ipv6_delete(ripng, rp);
515
516 if (rinfo->metric != RIPNG_METRIC_INFINITY)
517 ripng_aggregate_decrement_list(rp, list);
518
519 /* Re-use the first entry, and delete the others. */
520 for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo))
521 if (tmp_rinfo != rinfo) {
522 RIPNG_TIMER_OFF(tmp_rinfo->t_timeout);
523 RIPNG_TIMER_OFF(tmp_rinfo->t_garbage_collect);
524 list_delete_node(list, node);
525 ripng_info_free(tmp_rinfo);
526 }
527
528 RIPNG_TIMER_OFF(rinfo->t_timeout);
529 RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
530 memcpy(rinfo, rinfo_new, sizeof(struct ripng_info));
531
532 if (ripng_route_rte(rinfo)) {
533 ripng_timeout_update(ripng, rinfo);
534 /* The ADD message implies an update. */
535 ripng_zebra_ipv6_add(ripng, rp);
536 }
537
538 ripng_aggregate_increment(rp, rinfo);
539
540 /* Set the route change flag. */
541 SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
542
543 /* Signal the output process to trigger an update. */
544 ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
545
546 return rinfo;
547 }
548
549 /* Delete one route from the ECMP list.
550 * RETURN:
551 * null - the entry is freed, and other entries exist in the list
552 * the entry - the entry is the last one in the list; its metric is set
553 * to INFINITY, and the garbage collector is started for it
554 */
555 struct ripng_info *ripng_ecmp_delete(struct ripng *ripng,
556 struct ripng_info *rinfo)
557 {
558 struct agg_node *rp = rinfo->rp;
559 struct list *list = (struct list *)rp->info;
560
561 RIPNG_TIMER_OFF(rinfo->t_timeout);
562
563 if (rinfo->metric != RIPNG_METRIC_INFINITY)
564 ripng_aggregate_decrement(rp, rinfo);
565
566 if (listcount(list) > 1) {
567 /* Some other ECMP entries still exist. Just delete this entry.
568 */
569 RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
570 listnode_delete(list, rinfo);
571 if (ripng_route_rte(rinfo)
572 && CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
573 /* The ADD message implies the update. */
574 ripng_zebra_ipv6_add(ripng, rp);
575 ripng_info_free(rinfo);
576 rinfo = NULL;
577 } else {
578 assert(rinfo == listgetdata(listhead(list)));
579
580 /* This is the only entry left in the list. We must keep it in
581 * the list for garbage collection time, with INFINITY metric.
582 */
583
584 rinfo->metric = RIPNG_METRIC_INFINITY;
585 RIPNG_TIMER_ON(rinfo->t_garbage_collect, ripng_garbage_collect,
586 ripng->garbage_time);
587
588 if (ripng_route_rte(rinfo)
589 && CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB))
590 ripng_zebra_ipv6_delete(ripng, rp);
591 }
592
593 /* Set the route change flag on the first entry. */
594 rinfo = listgetdata(listhead(list));
595 SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
596
597 /* Signal the output process to trigger an update. */
598 ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
599
600 return rinfo;
601 }
602
603 /* Timeout RIPng routes. */
604 static int ripng_timeout(struct thread *t)
605 {
606 struct ripng_info *rinfo = THREAD_ARG(t);
607 struct ripng *ripng = ripng_info_get_instance(rinfo);
608
609 ripng_ecmp_delete(ripng, rinfo);
610
611 return 0;
612 }
613
614 static void ripng_timeout_update(struct ripng *ripng, struct ripng_info *rinfo)
615 {
616 if (rinfo->metric != RIPNG_METRIC_INFINITY) {
617 RIPNG_TIMER_OFF(rinfo->t_timeout);
618 thread_add_timer(master, ripng_timeout, rinfo,
619 ripng->timeout_time, &rinfo->t_timeout);
620 }
621 }
622
623 static int ripng_filter(int ripng_distribute, struct prefix_ipv6 *p,
624 struct ripng_interface *ri)
625 {
626 struct distribute *dist;
627 struct access_list *alist;
628 struct prefix_list *plist;
629 int distribute = ripng_distribute == RIPNG_FILTER_OUT
630 ? DISTRIBUTE_V6_OUT
631 : DISTRIBUTE_V6_IN;
632 const char *inout = ripng_distribute == RIPNG_FILTER_OUT ? "out" : "in";
633
634 /* Input distribute-list filtering. */
635 if (ri->list[ripng_distribute]) {
636 if (access_list_apply(ri->list[ripng_distribute],
637 (struct prefix *)p)
638 == FILTER_DENY) {
639 if (IS_RIPNG_DEBUG_PACKET)
640 zlog_debug("%s/%d filtered by distribute %s",
641 inet6_ntoa(p->prefix), p->prefixlen,
642 inout);
643 return -1;
644 }
645 }
646 if (ri->prefix[ripng_distribute]) {
647 if (prefix_list_apply(ri->prefix[ripng_distribute],
648 (struct prefix *)p)
649 == PREFIX_DENY) {
650 if (IS_RIPNG_DEBUG_PACKET)
651 zlog_debug("%s/%d filtered by prefix-list %s",
652 inet6_ntoa(p->prefix), p->prefixlen,
653 inout);
654 return -1;
655 }
656 }
657
658 /* All interface filter check. */
659 dist = distribute_lookup(ri->ripng->distribute_ctx, NULL);
660 if (dist) {
661 if (dist->list[distribute]) {
662 alist = access_list_lookup(AFI_IP6,
663 dist->list[distribute]);
664
665 if (alist) {
666 if (access_list_apply(alist, (struct prefix *)p)
667 == FILTER_DENY) {
668 if (IS_RIPNG_DEBUG_PACKET)
669 zlog_debug(
670 "%s/%d filtered by distribute %s",
671 inet6_ntoa(p->prefix),
672 p->prefixlen, inout);
673 return -1;
674 }
675 }
676 }
677 if (dist->prefix[distribute]) {
678 plist = prefix_list_lookup(AFI_IP6,
679 dist->prefix[distribute]);
680
681 if (plist) {
682 if (prefix_list_apply(plist, (struct prefix *)p)
683 == PREFIX_DENY) {
684 if (IS_RIPNG_DEBUG_PACKET)
685 zlog_debug(
686 "%s/%d filtered by prefix-list %s",
687 inet6_ntoa(p->prefix),
688 p->prefixlen, inout);
689 return -1;
690 }
691 }
692 }
693 }
694 return 0;
695 }
696
697 /* Process RIPng route according to RFC2080. */
698 static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
699 struct ripng_nexthop *ripng_nexthop,
700 struct interface *ifp)
701 {
702 int ret;
703 struct prefix_ipv6 p;
704 struct agg_node *rp;
705 struct ripng_info *rinfo = NULL, newinfo;
706 struct ripng_interface *ri;
707 struct ripng *ripng;
708 struct in6_addr *nexthop;
709 int same = 0;
710 struct list *list = NULL;
711 struct listnode *node = NULL;
712
713 /* Make prefix structure. */
714 memset(&p, 0, sizeof(struct prefix_ipv6));
715 p.family = AF_INET6;
716 /* p.prefix = rte->addr; */
717 IPV6_ADDR_COPY(&p.prefix, &rte->addr);
718 p.prefixlen = rte->prefixlen;
719
720 /* Make sure mask is applied. */
721 /* XXX We have to check the prefix is valid or not before call
722 apply_mask_ipv6. */
723 apply_mask_ipv6(&p);
724
725 ri = ifp->info;
726 ripng = ri->ripng;
727
728 /* Apply input filters. */
729 ret = ripng_filter(RIPNG_FILTER_IN, &p, ri);
730 if (ret < 0)
731 return;
732
733 memset(&newinfo, 0, sizeof(newinfo));
734 newinfo.type = ZEBRA_ROUTE_RIPNG;
735 newinfo.sub_type = RIPNG_ROUTE_RTE;
736 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
737 newinfo.nexthop = ripng_nexthop->address;
738 else
739 newinfo.nexthop = from->sin6_addr;
740 newinfo.from = from->sin6_addr;
741 newinfo.ifindex = ifp->ifindex;
742 newinfo.metric = rte->metric;
743 newinfo.metric_out = rte->metric; /* XXX */
744 newinfo.tag = ntohs(rte->tag); /* XXX */
745
746 /* Modify entry. */
747 if (ri->routemap[RIPNG_FILTER_IN]) {
748 ret = route_map_apply(ri->routemap[RIPNG_FILTER_IN],
749 (struct prefix *)&p, RMAP_RIPNG,
750 &newinfo);
751
752 if (ret == RMAP_DENYMATCH) {
753 if (IS_RIPNG_DEBUG_PACKET)
754 zlog_debug(
755 "RIPng %s/%d is filtered by route-map in",
756 inet6_ntoa(p.prefix), p.prefixlen);
757 return;
758 }
759
760 /* Get back the object */
761 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) {
762 if (!IPV6_ADDR_SAME(&newinfo.nexthop,
763 &ripng_nexthop->address)) {
764 /* the nexthop get changed by the routemap */
765 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop))
766 ripng_nexthop->address =
767 newinfo.nexthop;
768 else
769 ripng_nexthop->address = in6addr_any;
770 }
771 } else {
772 if (!IPV6_ADDR_SAME(&newinfo.nexthop,
773 &from->sin6_addr)) {
774 /* the nexthop get changed by the routemap */
775 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) {
776 ripng_nexthop->flag =
777 RIPNG_NEXTHOP_ADDRESS;
778 ripng_nexthop->address =
779 newinfo.nexthop;
780 }
781 }
782 }
783 rte->tag = htons(newinfo.tag_out); /* XXX */
784 rte->metric =
785 newinfo.metric_out; /* XXX: the routemap uses the
786 metric_out field */
787 }
788
789 /* Once the entry has been validated, update the metric by
790 * adding the cost of the network on wich the message
791 * arrived. If the result is greater than infinity, use infinity
792 * (RFC2453 Sec. 3.9.2)
793 **/
794
795 /* Zebra ripngd can handle offset-list in. */
796 ret = ripng_offset_list_apply_in(ripng, &p, ifp, &rte->metric);
797
798 /* If offset-list does not modify the metric use interface's
799 * one. */
800 if (!ret)
801 rte->metric += ifp->metric ? ifp->metric : 1;
802
803 if (rte->metric > RIPNG_METRIC_INFINITY)
804 rte->metric = RIPNG_METRIC_INFINITY;
805
806 /* Set nexthop pointer. */
807 if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)
808 nexthop = &ripng_nexthop->address;
809 else
810 nexthop = &from->sin6_addr;
811
812 /* Lookup RIPng routing table. */
813 rp = agg_node_get(ripng->table, (struct prefix *)&p);
814
815 newinfo.rp = rp;
816 newinfo.nexthop = *nexthop;
817 newinfo.metric = rte->metric;
818 newinfo.tag = ntohs(rte->tag);
819
820 /* Check to see whether there is already RIPng route on the table. */
821 if ((list = rp->info) != NULL)
822 for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) {
823 /* Need to compare with redistributed entry or local
824 * entry */
825 if (!ripng_route_rte(rinfo))
826 break;
827
828 if (IPV6_ADDR_SAME(&rinfo->from, &from->sin6_addr)
829 && IPV6_ADDR_SAME(&rinfo->nexthop, nexthop))
830 break;
831
832 if (!listnextnode(node)) {
833 /* Not found in the list */
834
835 if (rte->metric > rinfo->metric) {
836 /* New route has a greater metric.
837 * Discard it. */
838 agg_unlock_node(rp);
839 return;
840 }
841
842 if (rte->metric < rinfo->metric)
843 /* New route has a smaller metric.
844 * Replace the ECMP list
845 * with the new one in below. */
846 break;
847
848 /* Metrics are same. Unless ECMP is disabled,
849 * keep "rinfo" null and
850 * the new route is added in the ECMP list in
851 * below. */
852 if (!ripng->ecmp)
853 break;
854 }
855 }
856
857 if (rinfo) {
858 /* Redistributed route check. */
859 if (rinfo->type != ZEBRA_ROUTE_RIPNG
860 && rinfo->metric != RIPNG_METRIC_INFINITY) {
861 agg_unlock_node(rp);
862 return;
863 }
864
865 /* Local static route. */
866 if (rinfo->type == ZEBRA_ROUTE_RIPNG
867 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC)
868 || (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))
869 && rinfo->metric != RIPNG_METRIC_INFINITY) {
870 agg_unlock_node(rp);
871 return;
872 }
873 }
874
875 if (!rinfo) {
876 /* Now, check to see whether there is already an explicit route
877 for the destination prefix. If there is no such route, add
878 this route to the routing table, unless the metric is
879 infinity (there is no point in adding a route which
880 unusable). */
881 if (rte->metric != RIPNG_METRIC_INFINITY)
882 ripng_ecmp_add(ripng, &newinfo);
883 else
884 agg_unlock_node(rp);
885 } else {
886 /* If there is an existing route, compare the next hop address
887 to the address of the router from which the datagram came.
888 If this datagram is from the same router as the existing
889 route, reinitialize the timeout. */
890 same = (IN6_ARE_ADDR_EQUAL(&rinfo->from, &from->sin6_addr)
891 && (rinfo->ifindex == ifp->ifindex));
892
893 /*
894 * RFC 2080 - Section 2.4.2:
895 * "If the new metric is the same as the old one, examine the
896 * timeout
897 * for the existing route. If it is at least halfway to the
898 * expiration
899 * point, switch to the new route. This heuristic is optional,
900 * but
901 * highly recommended".
902 */
903 if (!ripng->ecmp && !same && rinfo->metric == rte->metric
904 && rinfo->t_timeout
905 && (thread_timer_remain_second(rinfo->t_timeout)
906 < (ripng->timeout_time / 2))) {
907 ripng_ecmp_replace(ripng, &newinfo);
908 }
909 /* Next, compare the metrics. If the datagram is from the same
910 router as the existing route, and the new metric is different
911 than the old one; or, if the new metric is lower than the old
912 one; do the following actions: */
913 else if ((same && rinfo->metric != rte->metric)
914 || rte->metric < rinfo->metric) {
915 if (listcount(list) == 1) {
916 if (newinfo.metric != RIPNG_METRIC_INFINITY)
917 ripng_ecmp_replace(ripng, &newinfo);
918 else
919 ripng_ecmp_delete(ripng, rinfo);
920 } else {
921 if (newinfo.metric < rinfo->metric)
922 ripng_ecmp_replace(ripng, &newinfo);
923 else /* newinfo.metric > rinfo->metric */
924 ripng_ecmp_delete(ripng, rinfo);
925 }
926 } else /* same & no change */
927 ripng_timeout_update(ripng, rinfo);
928
929 /* Unlock tempolary lock of the route. */
930 agg_unlock_node(rp);
931 }
932 }
933
934 /* Add redistributed route to RIPng table. */
935 void ripng_redistribute_add(struct ripng *ripng, int type, int sub_type,
936 struct prefix_ipv6 *p, ifindex_t ifindex,
937 struct in6_addr *nexthop, route_tag_t tag)
938 {
939 struct agg_node *rp;
940 struct ripng_info *rinfo = NULL, newinfo;
941 struct list *list = NULL;
942
943 /* Redistribute route */
944 if (IN6_IS_ADDR_LINKLOCAL(&p->prefix))
945 return;
946 if (IN6_IS_ADDR_LOOPBACK(&p->prefix))
947 return;
948
949 rp = agg_node_get(ripng->table, (struct prefix *)p);
950
951 memset(&newinfo, 0, sizeof(struct ripng_info));
952 newinfo.type = type;
953 newinfo.sub_type = sub_type;
954 newinfo.ifindex = ifindex;
955 newinfo.metric = 1;
956 if (tag <= UINT16_MAX) /* RIPng only supports 16 bit tags */
957 newinfo.tag = tag;
958 newinfo.rp = rp;
959 if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop))
960 newinfo.nexthop = *nexthop;
961
962 if ((list = rp->info) != NULL && listcount(list) != 0) {
963 rinfo = listgetdata(listhead(list));
964
965 if (rinfo->type == ZEBRA_ROUTE_CONNECT
966 && rinfo->sub_type == RIPNG_ROUTE_INTERFACE
967 && rinfo->metric != RIPNG_METRIC_INFINITY) {
968 agg_unlock_node(rp);
969 return;
970 }
971
972 /* Manually configured RIPng route check.
973 * They have the precedence on all the other entries.
974 **/
975 if (rinfo->type == ZEBRA_ROUTE_RIPNG
976 && ((rinfo->sub_type == RIPNG_ROUTE_STATIC)
977 || (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))) {
978 if (type != ZEBRA_ROUTE_RIPNG
979 || ((sub_type != RIPNG_ROUTE_STATIC)
980 && (sub_type != RIPNG_ROUTE_DEFAULT))) {
981 agg_unlock_node(rp);
982 return;
983 }
984 }
985
986 ripng_ecmp_replace(ripng, &newinfo);
987 agg_unlock_node(rp);
988 } else
989 ripng_ecmp_add(ripng, &newinfo);
990
991 if (IS_RIPNG_DEBUG_EVENT) {
992 if (!nexthop)
993 zlog_debug(
994 "Redistribute new prefix %s/%d on the interface %s",
995 inet6_ntoa(p->prefix), p->prefixlen,
996 ifindex2ifname(ifindex, ripng->vrf->vrf_id));
997 else
998 zlog_debug(
999 "Redistribute new prefix %s/%d with nexthop %s on the interface %s",
1000 inet6_ntoa(p->prefix), p->prefixlen,
1001 inet6_ntoa(*nexthop),
1002 ifindex2ifname(ifindex, ripng->vrf->vrf_id));
1003 }
1004
1005 ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
1006 }
1007
1008 /* Delete redistributed route to RIPng table. */
1009 void ripng_redistribute_delete(struct ripng *ripng, int type, int sub_type,
1010 struct prefix_ipv6 *p, ifindex_t ifindex)
1011 {
1012 struct agg_node *rp;
1013 struct ripng_info *rinfo;
1014
1015 if (IN6_IS_ADDR_LINKLOCAL(&p->prefix))
1016 return;
1017 if (IN6_IS_ADDR_LOOPBACK(&p->prefix))
1018 return;
1019
1020 rp = agg_node_lookup(ripng->table, (struct prefix *)p);
1021
1022 if (rp) {
1023 struct list *list = rp->info;
1024
1025 if (list != NULL && listcount(list) != 0) {
1026 rinfo = listgetdata(listhead(list));
1027 if (rinfo != NULL && rinfo->type == type
1028 && rinfo->sub_type == sub_type
1029 && rinfo->ifindex == ifindex) {
1030 /* Perform poisoned reverse. */
1031 rinfo->metric = RIPNG_METRIC_INFINITY;
1032 RIPNG_TIMER_ON(rinfo->t_garbage_collect,
1033 ripng_garbage_collect,
1034 ripng->garbage_time);
1035 RIPNG_TIMER_OFF(rinfo->t_timeout);
1036
1037 /* Aggregate count decrement. */
1038 ripng_aggregate_decrement(rp, rinfo);
1039
1040 rinfo->flags |= RIPNG_RTF_CHANGED;
1041
1042 if (IS_RIPNG_DEBUG_EVENT)
1043 zlog_debug(
1044 "Poisone %s/%d on the interface %s with an "
1045 "infinity metric [delete]",
1046 inet6_ntoa(p->prefix),
1047 p->prefixlen,
1048 ifindex2ifname(
1049 ifindex,
1050 ripng->vrf->vrf_id));
1051
1052 ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
1053 }
1054 }
1055 agg_unlock_node(rp);
1056 }
1057 }
1058
1059 /* Withdraw redistributed route. */
1060 void ripng_redistribute_withdraw(struct ripng *ripng, int type)
1061 {
1062 struct agg_node *rp;
1063 struct ripng_info *rinfo = NULL;
1064 struct list *list = NULL;
1065
1066 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp))
1067 if ((list = rp->info) != NULL) {
1068 rinfo = listgetdata(listhead(list));
1069 if ((rinfo->type == type)
1070 && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE)) {
1071 /* Perform poisoned reverse. */
1072 rinfo->metric = RIPNG_METRIC_INFINITY;
1073 RIPNG_TIMER_ON(rinfo->t_garbage_collect,
1074 ripng_garbage_collect,
1075 ripng->garbage_time);
1076 RIPNG_TIMER_OFF(rinfo->t_timeout);
1077
1078 /* Aggregate count decrement. */
1079 ripng_aggregate_decrement(rp, rinfo);
1080
1081 rinfo->flags |= RIPNG_RTF_CHANGED;
1082
1083 if (IS_RIPNG_DEBUG_EVENT) {
1084 struct prefix_ipv6 *p =
1085 (struct prefix_ipv6 *)&rp->p;
1086
1087 zlog_debug(
1088 "Poisone %s/%d on the interface %s [withdraw]",
1089 inet6_ntoa(p->prefix),
1090 p->prefixlen,
1091 ifindex2ifname(
1092 rinfo->ifindex,
1093 ripng->vrf->vrf_id));
1094 }
1095
1096 ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
1097 }
1098 }
1099 }
1100
1101 /* RIP routing information. */
1102 static void ripng_response_process(struct ripng_packet *packet, int size,
1103 struct sockaddr_in6 *from,
1104 struct interface *ifp, int hoplimit)
1105 {
1106 struct ripng_interface *ri = ifp->info;
1107 struct ripng *ripng = ri->ripng;
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 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(ripng, from);
1118 return;
1119 }
1120
1121 /* The datagram's IPv6 source address should be checked to see
1122 whether the datagram is from a valid neighbor; the source of the
1123 datagram must be a link-local address. */
1124 if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) {
1125 zlog_warn("RIPng packet comes from non link local address %s",
1126 inet6_ntoa(from->sin6_addr));
1127 ripng_peer_bad_packet(ripng, from);
1128 return;
1129 }
1130
1131 /* It is also worth checking to see whether the response is from one
1132 of the router's own addresses. Interfaces on broadcast networks
1133 may receive copies of their own multicasts immediately. If a
1134 router processes its own output as new input, confusion is likely,
1135 and such datagrams must be ignored. */
1136 if (ripng_lladdr_check(ifp, &from->sin6_addr)) {
1137 zlog_warn(
1138 "RIPng packet comes from my own link local address %s",
1139 inet6_ntoa(from->sin6_addr));
1140 ripng_peer_bad_packet(ripng, from);
1141 return;
1142 }
1143
1144 /* As an additional check, periodic advertisements must have their
1145 hop counts set to 255, and inbound, multicast packets sent from the
1146 RIPng port (i.e. periodic advertisement or triggered update
1147 packets) must be examined to ensure that the hop count is 255. */
1148 if (hoplimit >= 0 && hoplimit != 255) {
1149 zlog_warn(
1150 "RIPng packet comes with non 255 hop count %d from %s",
1151 hoplimit, inet6_ntoa(from->sin6_addr));
1152 ripng_peer_bad_packet(ripng, from);
1153 return;
1154 }
1155
1156 /* Update RIPng peer. */
1157 ripng_peer_update(ripng, from, packet->version);
1158
1159 /* Reset nexthop. */
1160 memset(&nexthop, 0, sizeof(struct ripng_nexthop));
1161 nexthop.flag = RIPNG_NEXTHOP_UNSPEC;
1162
1163 /* Set RTE pointer. */
1164 rte = packet->rte;
1165
1166 for (lim = ((caddr_t)packet) + size; (caddr_t)rte < lim; rte++) {
1167 /* First of all, we have to check this RTE is next hop RTE or
1168 not. Next hop RTE is completely different with normal RTE so
1169 we need special treatment. */
1170 if (rte->metric == RIPNG_METRIC_NEXTHOP) {
1171 ripng_nexthop_rte(rte, from, &nexthop);
1172 continue;
1173 }
1174
1175 /* RTE information validation. */
1176
1177 /* - is the destination prefix valid (e.g., not a multicast
1178 prefix and not a link-local address) A link-local address
1179 should never be present in an RTE. */
1180 if (IN6_IS_ADDR_MULTICAST(&rte->addr)) {
1181 zlog_warn(
1182 "Destination prefix is a multicast address %s/%d [%d]",
1183 inet6_ntoa(rte->addr), rte->prefixlen,
1184 rte->metric);
1185 ripng_peer_bad_route(ripng, from);
1186 continue;
1187 }
1188 if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) {
1189 zlog_warn(
1190 "Destination prefix is a link-local address %s/%d [%d]",
1191 inet6_ntoa(rte->addr), rte->prefixlen,
1192 rte->metric);
1193 ripng_peer_bad_route(ripng, from);
1194 continue;
1195 }
1196 if (IN6_IS_ADDR_LOOPBACK(&rte->addr)) {
1197 zlog_warn(
1198 "Destination prefix is a loopback address %s/%d [%d]",
1199 inet6_ntoa(rte->addr), rte->prefixlen,
1200 rte->metric);
1201 ripng_peer_bad_route(ripng, from);
1202 continue;
1203 }
1204
1205 /* - is the prefix length valid (i.e., between 0 and 128,
1206 inclusive) */
1207 if (rte->prefixlen > 128) {
1208 zlog_warn("Invalid prefix length %s/%d from %s%%%s",
1209 inet6_ntoa(rte->addr), rte->prefixlen,
1210 inet6_ntoa(from->sin6_addr), ifp->name);
1211 ripng_peer_bad_route(ripng, from);
1212 continue;
1213 }
1214
1215 /* - is the metric valid (i.e., between 1 and 16, inclusive) */
1216 if (!(rte->metric >= 1 && rte->metric <= 16)) {
1217 zlog_warn("Invalid metric %d from %s%%%s", rte->metric,
1218 inet6_ntoa(from->sin6_addr), ifp->name);
1219 ripng_peer_bad_route(ripng, from);
1220 continue;
1221 }
1222
1223 /* Vincent: XXX Should we compute the direclty reachable nexthop
1224 * for our RIPng network ?
1225 **/
1226
1227 /* Routing table updates. */
1228 ripng_route_process(rte, from, &nexthop, ifp);
1229 }
1230 }
1231
1232 /* Response to request message. */
1233 static void ripng_request_process(struct ripng_packet *packet, int size,
1234 struct sockaddr_in6 *from,
1235 struct interface *ifp)
1236 {
1237 struct ripng *ripng;
1238 caddr_t lim;
1239 struct rte *rte;
1240 struct prefix_ipv6 p;
1241 struct agg_node *rp;
1242 struct ripng_info *rinfo;
1243 struct ripng_interface *ri;
1244
1245 /* Does not reponse to the requests on the loopback interfaces */
1246 if (if_is_loopback(ifp))
1247 return;
1248
1249 /* Check RIPng process is enabled on this interface. */
1250 ri = ifp->info;
1251 if (!ri->running)
1252 return;
1253 ripng = ri->ripng;
1254
1255 /* When passive interface is specified, suppress responses */
1256 if (ri->passive)
1257 return;
1258
1259 /* RIPng peer update. */
1260 ripng_peer_update(ripng, from, packet->version);
1261
1262 lim = ((caddr_t)packet) + size;
1263 rte = packet->rte;
1264
1265 /* The Request is processed entry by entry. If there are no
1266 entries, no response is given. */
1267 if (lim == (caddr_t)rte)
1268 return;
1269
1270 /* There is one special case. If there is exactly one entry in the
1271 request, and it has a destination prefix of zero, a prefix length
1272 of zero, and a metric of infinity (i.e., 16), then this is a
1273 request to send the entire routing table. In that case, a call
1274 is made to the output process to send the routing table to the
1275 requesting address/port. */
1276 if (lim == ((caddr_t)(rte + 1)) && IN6_IS_ADDR_UNSPECIFIED(&rte->addr)
1277 && rte->prefixlen == 0 && rte->metric == RIPNG_METRIC_INFINITY) {
1278 /* All route with split horizon */
1279 ripng_output_process(ifp, from, ripng_all_route);
1280 } else {
1281 /* Except for this special case, processing is quite simple.
1282 Examine the list of RTEs in the Request one by one. For each
1283 entry, look up the destination in the router's routing
1284 database and, if there is a route, put that route's metric in
1285 the metric field of the RTE. If there is no explicit route
1286 to the specified destination, put infinity in the metric
1287 field. Once all the entries have been filled in, change the
1288 command from Request to Response and send the datagram back
1289 to the requestor. */
1290 memset(&p, 0, sizeof(struct prefix_ipv6));
1291 p.family = AF_INET6;
1292
1293 for (; ((caddr_t)rte) < lim; rte++) {
1294 p.prefix = rte->addr;
1295 p.prefixlen = rte->prefixlen;
1296 apply_mask_ipv6(&p);
1297
1298 rp = agg_node_lookup(ripng->table, (struct prefix *)&p);
1299
1300 if (rp) {
1301 rinfo = listgetdata(
1302 listhead((struct list *)rp->info));
1303 rte->metric = rinfo->metric;
1304 agg_unlock_node(rp);
1305 } else
1306 rte->metric = RIPNG_METRIC_INFINITY;
1307 }
1308 packet->command = RIPNG_RESPONSE;
1309
1310 ripng_send_packet((caddr_t)packet, size, from, ifp);
1311 }
1312 }
1313
1314 /* First entry point of reading RIPng packet. */
1315 static int ripng_read(struct thread *thread)
1316 {
1317 struct ripng *ripng = THREAD_ARG(thread);
1318 int len;
1319 int sock;
1320 struct sockaddr_in6 from;
1321 struct ripng_packet *packet;
1322 ifindex_t ifindex = 0;
1323 struct interface *ifp;
1324 int hoplimit = -1;
1325
1326 /* Check ripng is active and alive. */
1327 assert(ripng != NULL);
1328 assert(ripng->sock >= 0);
1329
1330 /* Fetch thread data and set read pointer to empty for event
1331 managing. `sock' sould be same as ripng->sock. */
1332 sock = THREAD_FD(thread);
1333 ripng->t_read = NULL;
1334
1335 /* Add myself to the next event. */
1336 ripng_event(ripng, RIPNG_READ, sock);
1337
1338 /* Read RIPng packet. */
1339 len = ripng_recv_packet(sock, STREAM_DATA(ripng->ibuf),
1340 STREAM_SIZE(ripng->ibuf), &from, &ifindex,
1341 &hoplimit);
1342 if (len < 0) {
1343 zlog_warn("RIPng recvfrom failed (VRF %s): %s.",
1344 ripng->vrf_name, safe_strerror(errno));
1345 return len;
1346 }
1347
1348 /* Check RTE boundary. RTE size (Packet length - RIPng header size
1349 (4)) must be multiple size of one RTE size (20). */
1350 if (((len - 4) % 20) != 0) {
1351 zlog_warn("RIPng invalid packet size %d from %s (VRF %s)", len,
1352 inet6_ntoa(from.sin6_addr), ripng->vrf_name);
1353 ripng_peer_bad_packet(ripng, &from);
1354 return 0;
1355 }
1356
1357 packet = (struct ripng_packet *)STREAM_DATA(ripng->ibuf);
1358 ifp = if_lookup_by_index(ifindex, ripng->vrf->vrf_id);
1359
1360 /* RIPng packet received. */
1361 if (IS_RIPNG_DEBUG_EVENT)
1362 zlog_debug(
1363 "RIPng packet received from %s port %d on %s (VRF %s)",
1364 inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port),
1365 ifp ? ifp->name : "unknown", ripng->vrf_name);
1366
1367 /* Logging before packet checking. */
1368 if (IS_RIPNG_DEBUG_RECV)
1369 ripng_packet_dump(packet, len, "RECV");
1370
1371 /* Packet comes from unknown interface. */
1372 if (ifp == NULL) {
1373 zlog_warn(
1374 "RIPng packet comes from unknown interface %d (VRF %s)",
1375 ifindex, ripng->vrf_name);
1376 return 0;
1377 }
1378
1379 /* Packet version mismatch checking. */
1380 if (packet->version != ripng->version) {
1381 zlog_warn(
1382 "RIPng packet version %d doesn't fit to my version %d (VRF %s)",
1383 packet->version, ripng->version, ripng->vrf_name);
1384 ripng_peer_bad_packet(ripng, &from);
1385 return 0;
1386 }
1387
1388 /* Process RIPng packet. */
1389 switch (packet->command) {
1390 case RIPNG_REQUEST:
1391 ripng_request_process(packet, len, &from, ifp);
1392 break;
1393 case RIPNG_RESPONSE:
1394 ripng_response_process(packet, len, &from, ifp, hoplimit);
1395 break;
1396 default:
1397 zlog_warn("Invalid RIPng command %d (VRF %s)", packet->command,
1398 ripng->vrf_name);
1399 ripng_peer_bad_packet(ripng, &from);
1400 break;
1401 }
1402 return 0;
1403 }
1404
1405 /* Walk down the RIPng routing table then clear changed flag. */
1406 static void ripng_clear_changed_flag(struct ripng *ripng)
1407 {
1408 struct agg_node *rp;
1409 struct ripng_info *rinfo = NULL;
1410 struct list *list = NULL;
1411 struct listnode *listnode = NULL;
1412
1413 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp))
1414 if ((list = rp->info) != NULL)
1415 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
1416 UNSET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
1417 /* This flag can be set only on the first entry.
1418 */
1419 break;
1420 }
1421 }
1422
1423 /* Regular update of RIPng route. Send all routing formation to RIPng
1424 enabled interface. */
1425 static int ripng_update(struct thread *t)
1426 {
1427 struct ripng *ripng = THREAD_ARG(t);
1428 struct interface *ifp;
1429 struct ripng_interface *ri;
1430
1431 /* Clear update timer thread. */
1432 ripng->t_update = NULL;
1433
1434 /* Logging update event. */
1435 if (IS_RIPNG_DEBUG_EVENT)
1436 zlog_debug("RIPng update timer expired!");
1437
1438 /* Supply routes to each interface. */
1439 FOR_ALL_INTERFACES (ripng->vrf, ifp) {
1440 ri = ifp->info;
1441
1442 if (if_is_loopback(ifp) || !if_is_up(ifp))
1443 continue;
1444
1445 if (!ri->running)
1446 continue;
1447
1448 /* When passive interface is specified, suppress announce to the
1449 interface. */
1450 if (ri->passive)
1451 continue;
1452
1453 #if RIPNG_ADVANCED
1454 if (ri->ri_send == RIPNG_SEND_OFF) {
1455 if (IS_RIPNG_DEBUG_EVENT)
1456 zlog_debug(
1457 "[Event] RIPng send to if %d is suppressed by config",
1458 ifp->ifindex);
1459 continue;
1460 }
1461 #endif /* RIPNG_ADVANCED */
1462
1463 ripng_output_process(ifp, NULL, ripng_all_route);
1464 }
1465
1466 /* Triggered updates may be suppressed if a regular update is due by
1467 the time the triggered update would be sent. */
1468 if (ripng->t_triggered_interval) {
1469 thread_cancel(ripng->t_triggered_interval);
1470 ripng->t_triggered_interval = NULL;
1471 }
1472 ripng->trigger = 0;
1473
1474 /* Reset flush event. */
1475 ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
1476
1477 return 0;
1478 }
1479
1480 /* Triggered update interval timer. */
1481 static int ripng_triggered_interval(struct thread *t)
1482 {
1483 struct ripng *ripng = THREAD_ARG(t);
1484
1485 ripng->t_triggered_interval = NULL;
1486
1487 if (ripng->trigger) {
1488 ripng->trigger = 0;
1489 ripng_triggered_update(t);
1490 }
1491 return 0;
1492 }
1493
1494 /* Execute triggered update. */
1495 int ripng_triggered_update(struct thread *t)
1496 {
1497 struct ripng *ripng = THREAD_ARG(t);
1498 struct interface *ifp;
1499 struct ripng_interface *ri;
1500 int interval;
1501
1502 ripng->t_triggered_update = NULL;
1503
1504 /* Cancel interval timer. */
1505 if (ripng->t_triggered_interval) {
1506 thread_cancel(ripng->t_triggered_interval);
1507 ripng->t_triggered_interval = NULL;
1508 }
1509 ripng->trigger = 0;
1510
1511 /* Logging triggered update. */
1512 if (IS_RIPNG_DEBUG_EVENT)
1513 zlog_debug("RIPng triggered update!");
1514
1515 /* Split Horizon processing is done when generating triggered
1516 updates as well as normal updates (see section 2.6). */
1517 FOR_ALL_INTERFACES (ripng->vrf, ifp) {
1518 ri = ifp->info;
1519
1520 if (if_is_loopback(ifp) || !if_is_up(ifp))
1521 continue;
1522
1523 if (!ri->running)
1524 continue;
1525
1526 /* When passive interface is specified, suppress announce to the
1527 interface. */
1528 if (ri->passive)
1529 continue;
1530
1531 ripng_output_process(ifp, NULL, ripng_changed_route);
1532 }
1533
1534 /* Once all of the triggered updates have been generated, the route
1535 change flags should be cleared. */
1536 ripng_clear_changed_flag(ripng);
1537
1538 /* After a triggered update is sent, a timer should be set for a
1539 random interval between 1 and 5 seconds. If other changes that
1540 would trigger updates occur before the timer expires, a single
1541 update is triggered when the timer expires. */
1542 interval = (random() % 5) + 1;
1543
1544 ripng->t_triggered_interval = NULL;
1545 thread_add_timer(master, ripng_triggered_interval, ripng, interval,
1546 &ripng->t_triggered_interval);
1547
1548 return 0;
1549 }
1550
1551 /* Write routing table entry to the stream and return next index of
1552 the routing table entry in the stream. */
1553 int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p,
1554 struct in6_addr *nexthop, uint16_t tag, uint8_t metric)
1555 {
1556 /* RIPng packet header. */
1557 if (num == 0) {
1558 stream_putc(s, RIPNG_RESPONSE);
1559 stream_putc(s, RIPNG_V1);
1560 stream_putw(s, 0);
1561 }
1562
1563 /* Write routing table entry. */
1564 if (!nexthop) {
1565 assert(p);
1566 stream_write(s, (uint8_t *)&p->prefix, sizeof(struct in6_addr));
1567 } else
1568 stream_write(s, (uint8_t *)nexthop, sizeof(struct in6_addr));
1569 stream_putw(s, tag);
1570 if (p)
1571 stream_putc(s, p->prefixlen);
1572 else
1573 stream_putc(s, 0);
1574 stream_putc(s, metric);
1575
1576 return ++num;
1577 }
1578
1579 /* Send RESPONSE message to specified destination. */
1580 void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
1581 int route_type)
1582 {
1583 struct ripng *ripng;
1584 int ret;
1585 struct agg_node *rp;
1586 struct ripng_info *rinfo;
1587 struct ripng_interface *ri;
1588 struct ripng_aggregate *aggregate;
1589 struct prefix_ipv6 *p;
1590 struct list *ripng_rte_list;
1591 struct list *list = NULL;
1592 struct listnode *listnode = NULL;
1593
1594 if (IS_RIPNG_DEBUG_EVENT) {
1595 if (to)
1596 zlog_debug("RIPng update routes to neighbor %s",
1597 inet6_ntoa(to->sin6_addr));
1598 else
1599 zlog_debug("RIPng update routes on interface %s",
1600 ifp->name);
1601 }
1602
1603 /* Get RIPng interface and instance. */
1604 ri = ifp->info;
1605 ripng = ri->ripng;
1606
1607 ripng_rte_list = ripng_rte_new();
1608
1609 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
1610 if ((list = rp->info) != NULL
1611 && (rinfo = listgetdata(listhead(list))) != NULL
1612 && rinfo->suppress == 0) {
1613 /* If no route-map are applied, the RTE will be these
1614 * following
1615 * information.
1616 */
1617 p = (struct prefix_ipv6 *)&rp->p;
1618 rinfo->metric_out = rinfo->metric;
1619 rinfo->tag_out = rinfo->tag;
1620 memset(&rinfo->nexthop_out, 0,
1621 sizeof(rinfo->nexthop_out));
1622 /* In order to avoid some local loops,
1623 * if the RIPng route has a nexthop via this interface,
1624 * keep the nexthop,
1625 * otherwise set it to 0. The nexthop should not be
1626 * propagated
1627 * beyond the local broadcast/multicast area in order
1628 * to avoid an IGP multi-level recursive look-up.
1629 */
1630 if (rinfo->ifindex == ifp->ifindex)
1631 rinfo->nexthop_out = rinfo->nexthop;
1632
1633 /* Apply output filters. */
1634 ret = ripng_filter(RIPNG_FILTER_OUT, p, ri);
1635 if (ret < 0)
1636 continue;
1637
1638 /* Changed route only output. */
1639 if (route_type == ripng_changed_route
1640 && (!(rinfo->flags & RIPNG_RTF_CHANGED)))
1641 continue;
1642
1643 /* Split horizon. */
1644 if (ri->split_horizon == RIPNG_SPLIT_HORIZON) {
1645 /* We perform split horizon for RIPng routes. */
1646 int suppress = 0;
1647 struct ripng_info *tmp_rinfo = NULL;
1648
1649 for (ALL_LIST_ELEMENTS_RO(list, listnode,
1650 tmp_rinfo))
1651 if (tmp_rinfo->type == ZEBRA_ROUTE_RIPNG
1652 && tmp_rinfo->ifindex
1653 == ifp->ifindex) {
1654 suppress = 1;
1655 break;
1656 }
1657 if (suppress)
1658 continue;
1659 }
1660
1661 /* Preparation for route-map. */
1662 rinfo->metric_set = 0;
1663 /* nexthop_out,
1664 * metric_out
1665 * and tag_out are already initialized.
1666 */
1667
1668 /* Interface route-map */
1669 if (ri->routemap[RIPNG_FILTER_OUT]) {
1670 ret = route_map_apply(
1671 ri->routemap[RIPNG_FILTER_OUT],
1672 (struct prefix *)p, RMAP_RIPNG, rinfo);
1673
1674 if (ret == RMAP_DENYMATCH) {
1675 if (IS_RIPNG_DEBUG_PACKET)
1676 zlog_debug(
1677 "RIPng %s/%d is filtered by route-map out",
1678 inet6_ntoa(p->prefix),
1679 p->prefixlen);
1680 continue;
1681 }
1682 }
1683
1684 /* Redistribute route-map. */
1685 if (ripng->route_map[rinfo->type].name) {
1686 ret = route_map_apply(
1687 ripng->route_map[rinfo->type].map,
1688 (struct prefix *)p, RMAP_RIPNG, rinfo);
1689
1690 if (ret == RMAP_DENYMATCH) {
1691 if (IS_RIPNG_DEBUG_PACKET)
1692 zlog_debug(
1693 "RIPng %s/%d is filtered by route-map",
1694 inet6_ntoa(p->prefix),
1695 p->prefixlen);
1696 continue;
1697 }
1698 }
1699
1700 /* When the route-map does not set metric. */
1701 if (!rinfo->metric_set) {
1702 /* If the redistribute metric is set. */
1703 if (ripng->route_map[rinfo->type].metric_config
1704 && rinfo->metric != RIPNG_METRIC_INFINITY) {
1705 rinfo->metric_out =
1706 ripng->route_map[rinfo->type]
1707 .metric;
1708 } else {
1709 /* If the route is not connected or
1710 localy generated
1711 one, use default-metric value */
1712 if (rinfo->type != ZEBRA_ROUTE_RIPNG
1713 && rinfo->type
1714 != ZEBRA_ROUTE_CONNECT
1715 && rinfo->metric
1716 != RIPNG_METRIC_INFINITY)
1717 rinfo->metric_out =
1718 ripng->default_metric;
1719 }
1720 }
1721
1722 /* Apply offset-list */
1723 if (rinfo->metric_out != RIPNG_METRIC_INFINITY)
1724 ripng_offset_list_apply_out(ripng, p, ifp,
1725 &rinfo->metric_out);
1726
1727 if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
1728 rinfo->metric_out = RIPNG_METRIC_INFINITY;
1729
1730 /* Perform split-horizon with poisoned reverse
1731 * for RIPng routes.
1732 **/
1733 if (ri->split_horizon
1734 == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) {
1735 struct ripng_info *tmp_rinfo = NULL;
1736
1737 for (ALL_LIST_ELEMENTS_RO(list, listnode,
1738 tmp_rinfo))
1739 if ((tmp_rinfo->type
1740 == ZEBRA_ROUTE_RIPNG)
1741 && tmp_rinfo->ifindex
1742 == ifp->ifindex)
1743 rinfo->metric_out =
1744 RIPNG_METRIC_INFINITY;
1745 }
1746
1747 /* Add RTE to the list */
1748 ripng_rte_add(ripng_rte_list, p, rinfo, NULL);
1749 }
1750
1751 /* Process the aggregated RTE entry */
1752 if ((aggregate = rp->aggregate) != NULL && aggregate->count > 0
1753 && aggregate->suppress == 0) {
1754 /* If no route-map are applied, the RTE will be these
1755 * following
1756 * information.
1757 */
1758 p = (struct prefix_ipv6 *)&rp->p;
1759 aggregate->metric_set = 0;
1760 aggregate->metric_out = aggregate->metric;
1761 aggregate->tag_out = aggregate->tag;
1762 memset(&aggregate->nexthop_out, 0,
1763 sizeof(aggregate->nexthop_out));
1764
1765 /* Apply output filters.*/
1766 ret = ripng_filter(RIPNG_FILTER_OUT, p, ri);
1767 if (ret < 0)
1768 continue;
1769
1770 /* Interface route-map */
1771 if (ri->routemap[RIPNG_FILTER_OUT]) {
1772 struct ripng_info newinfo;
1773
1774 /* let's cast the aggregate structure to
1775 * ripng_info */
1776 memset(&newinfo, 0, sizeof(struct ripng_info));
1777 /* the nexthop is :: */
1778 newinfo.metric = aggregate->metric;
1779 newinfo.metric_out = aggregate->metric_out;
1780 newinfo.tag = aggregate->tag;
1781 newinfo.tag_out = aggregate->tag_out;
1782
1783 ret = route_map_apply(
1784 ri->routemap[RIPNG_FILTER_OUT],
1785 (struct prefix *)p, RMAP_RIPNG,
1786 &newinfo);
1787
1788 if (ret == RMAP_DENYMATCH) {
1789 if (IS_RIPNG_DEBUG_PACKET)
1790 zlog_debug(
1791 "RIPng %s/%d is filtered by route-map out",
1792 inet6_ntoa(p->prefix),
1793 p->prefixlen);
1794 continue;
1795 }
1796
1797 aggregate->metric_out = newinfo.metric_out;
1798 aggregate->tag_out = newinfo.tag_out;
1799 if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out))
1800 aggregate->nexthop_out =
1801 newinfo.nexthop_out;
1802 }
1803
1804 /* There is no redistribute routemap for the aggregated
1805 * RTE */
1806
1807 /* Changed route only output. */
1808 /* XXX, vincent, in order to increase time convergence,
1809 * it should be announced if a child has changed.
1810 */
1811 if (route_type == ripng_changed_route)
1812 continue;
1813
1814 /* Apply offset-list */
1815 if (aggregate->metric_out != RIPNG_METRIC_INFINITY)
1816 ripng_offset_list_apply_out(
1817 ripng, p, ifp, &aggregate->metric_out);
1818
1819 if (aggregate->metric_out > RIPNG_METRIC_INFINITY)
1820 aggregate->metric_out = RIPNG_METRIC_INFINITY;
1821
1822 /* Add RTE to the list */
1823 ripng_rte_add(ripng_rte_list, p, NULL, aggregate);
1824 }
1825 }
1826
1827 /* Flush the list */
1828 ripng_rte_send(ripng_rte_list, ifp, to);
1829 ripng_rte_free(ripng_rte_list);
1830 }
1831
1832 struct ripng *ripng_lookup_by_vrf_id(vrf_id_t vrf_id)
1833 {
1834 struct vrf *vrf;
1835
1836 vrf = vrf_lookup_by_id(vrf_id);
1837 if (!vrf)
1838 return NULL;
1839
1840 return vrf->info;
1841 }
1842
1843 struct ripng *ripng_lookup_by_vrf_name(const char *vrf_name)
1844 {
1845 struct ripng ripng;
1846
1847 ripng.vrf_name = (char *)vrf_name;
1848
1849 return RB_FIND(ripng_instance_head, &ripng_instances, &ripng);
1850 }
1851
1852 /* Create new RIPng instance and set it to global variable. */
1853 struct ripng *ripng_create(const char *vrf_name, struct vrf *vrf, int socket)
1854 {
1855 struct ripng *ripng;
1856
1857 /* Allocaste RIPng instance. */
1858 ripng = XCALLOC(MTYPE_RIPNG, sizeof(struct ripng));
1859 ripng->vrf_name = XSTRDUP(MTYPE_RIPNG_VRF_NAME, vrf_name);
1860
1861 /* Default version and timer values. */
1862 ripng->version = RIPNG_V1;
1863 ripng->update_time = yang_get_default_uint32(
1864 "%s/timers/update-interval", RIPNG_INSTANCE);
1865 ripng->timeout_time = yang_get_default_uint32(
1866 "%s/timers/holddown-interval", RIPNG_INSTANCE);
1867 ripng->garbage_time = yang_get_default_uint32(
1868 "%s/timers/flush-interval", RIPNG_INSTANCE);
1869 ripng->default_metric =
1870 yang_get_default_uint8("%s/default-metric", RIPNG_INSTANCE);
1871 ripng->ecmp = yang_get_default_bool("%s/allow-ecmp", RIPNG_INSTANCE);
1872
1873 /* Make buffer. */
1874 ripng->ibuf = stream_new(RIPNG_MAX_PACKET_SIZE * 5);
1875 ripng->obuf = stream_new(RIPNG_MAX_PACKET_SIZE);
1876
1877 /* Initialize RIPng data structures. */
1878 ripng->table = agg_table_init();
1879 agg_set_table_info(ripng->table, ripng);
1880 ripng->peer_list = list_new();
1881 ripng->peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp;
1882 ripng->peer_list->del = ripng_peer_list_del;
1883 ripng->enable_if = vector_init(1);
1884 ripng->enable_network = agg_table_init();
1885 ripng->passive_interface = vector_init(1);
1886 ripng->offset_list_master = list_new();
1887 ripng->offset_list_master->cmp =
1888 (int (*)(void *, void *))offset_list_cmp;
1889 ripng->offset_list_master->del =
1890 (void (*)(void *))ripng_offset_list_del;
1891 ripng->distribute_ctx = distribute_list_ctx_create(vrf);
1892 distribute_list_add_hook(ripng->distribute_ctx,
1893 ripng_distribute_update);
1894 distribute_list_delete_hook(ripng->distribute_ctx,
1895 ripng_distribute_update);
1896
1897
1898 /* Enable the routing instance if possible. */
1899 if (vrf && vrf_is_enabled(vrf))
1900 ripng_instance_enable(ripng, vrf, socket);
1901 else {
1902 ripng->vrf = NULL;
1903 ripng->sock = -1;
1904 }
1905
1906 RB_INSERT(ripng_instance_head, &ripng_instances, ripng);
1907
1908 return ripng;
1909 }
1910
1911 /* Send RIPng request to the interface. */
1912 int ripng_request(struct interface *ifp)
1913 {
1914 struct rte *rte;
1915 struct ripng_packet ripng_packet;
1916
1917 /* In default ripd doesn't send RIP_REQUEST to the loopback interface.
1918 */
1919 if (if_is_loopback(ifp))
1920 return 0;
1921
1922 /* If interface is down, don't send RIP packet. */
1923 if (!if_is_up(ifp))
1924 return 0;
1925
1926 if (IS_RIPNG_DEBUG_EVENT)
1927 zlog_debug("RIPng send request to %s", ifp->name);
1928
1929 memset(&ripng_packet, 0, sizeof(ripng_packet));
1930 ripng_packet.command = RIPNG_REQUEST;
1931 ripng_packet.version = RIPNG_V1;
1932 rte = ripng_packet.rte;
1933 rte->metric = RIPNG_METRIC_INFINITY;
1934
1935 return ripng_send_packet((caddr_t)&ripng_packet, sizeof(ripng_packet),
1936 NULL, ifp);
1937 }
1938
1939
1940 static int ripng_update_jitter(int time)
1941 {
1942 return ((random() % (time + 1)) - (time / 2));
1943 }
1944
1945 void ripng_event(struct ripng *ripng, enum ripng_event event, int sock)
1946 {
1947 int jitter = 0;
1948
1949 switch (event) {
1950 case RIPNG_READ:
1951 thread_add_read(master, ripng_read, ripng, sock,
1952 &ripng->t_read);
1953 break;
1954 case RIPNG_UPDATE_EVENT:
1955 if (ripng->t_update) {
1956 thread_cancel(ripng->t_update);
1957 ripng->t_update = NULL;
1958 }
1959 /* Update timer jitter. */
1960 jitter = ripng_update_jitter(ripng->update_time);
1961
1962 ripng->t_update = NULL;
1963 thread_add_timer(master, ripng_update, ripng,
1964 sock ? 2 : ripng->update_time + jitter,
1965 &ripng->t_update);
1966 break;
1967 case RIPNG_TRIGGERED_UPDATE:
1968 if (ripng->t_triggered_interval)
1969 ripng->trigger = 1;
1970 else
1971 thread_add_event(master, ripng_triggered_update, ripng,
1972 0, &ripng->t_triggered_update);
1973 break;
1974 default:
1975 break;
1976 }
1977 }
1978
1979
1980 /* Print out routes update time. */
1981 static void ripng_vty_out_uptime(struct vty *vty, struct ripng_info *rinfo)
1982 {
1983 time_t clock;
1984 struct tm *tm;
1985 #define TIME_BUF 25
1986 char timebuf[TIME_BUF];
1987 struct thread *thread;
1988
1989 if ((thread = rinfo->t_timeout) != NULL) {
1990 clock = thread_timer_remain_second(thread);
1991 tm = gmtime(&clock);
1992 strftime(timebuf, TIME_BUF, "%M:%S", tm);
1993 vty_out(vty, "%5s", timebuf);
1994 } else if ((thread = rinfo->t_garbage_collect) != NULL) {
1995 clock = thread_timer_remain_second(thread);
1996 tm = gmtime(&clock);
1997 strftime(timebuf, TIME_BUF, "%M:%S", tm);
1998 vty_out(vty, "%5s", timebuf);
1999 }
2000 }
2001
2002 static char *ripng_route_subtype_print(struct ripng_info *rinfo)
2003 {
2004 static char str[3];
2005 memset(str, 0, 3);
2006
2007 if (rinfo->suppress)
2008 strcat(str, "S");
2009
2010 switch (rinfo->sub_type) {
2011 case RIPNG_ROUTE_RTE:
2012 strcat(str, "n");
2013 break;
2014 case RIPNG_ROUTE_STATIC:
2015 strcat(str, "s");
2016 break;
2017 case RIPNG_ROUTE_DEFAULT:
2018 strcat(str, "d");
2019 break;
2020 case RIPNG_ROUTE_REDISTRIBUTE:
2021 strcat(str, "r");
2022 break;
2023 case RIPNG_ROUTE_INTERFACE:
2024 strcat(str, "i");
2025 break;
2026 default:
2027 strcat(str, "?");
2028 break;
2029 }
2030
2031 return str;
2032 }
2033
2034 DEFUN (show_ipv6_ripng,
2035 show_ipv6_ripng_cmd,
2036 "show ipv6 ripng [vrf NAME]",
2037 SHOW_STR
2038 IPV6_STR
2039 "Show RIPng routes\n"
2040 VRF_CMD_HELP_STR)
2041 {
2042 struct ripng *ripng;
2043 struct agg_node *rp;
2044 struct ripng_info *rinfo;
2045 struct ripng_aggregate *aggregate;
2046 struct prefix_ipv6 *p;
2047 struct list *list = NULL;
2048 struct listnode *listnode = NULL;
2049 int len;
2050 const char *vrf_name;
2051 int idx = 0;
2052
2053 if (argv_find(argv, argc, "vrf", &idx))
2054 vrf_name = argv[idx + 1]->arg;
2055 else
2056 vrf_name = VRF_DEFAULT_NAME;
2057
2058 ripng = ripng_lookup_by_vrf_name(vrf_name);
2059 if (!ripng) {
2060 vty_out(vty, "%% RIPng instance not found\n");
2061 return CMD_SUCCESS;
2062 }
2063 if (!ripng->enabled) {
2064 vty_out(vty, "%% RIPng instance is disabled\n");
2065 return CMD_SUCCESS;
2066 }
2067
2068 /* Header of display. */
2069 vty_out(vty,
2070 "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP\n"
2071 "Sub-codes:\n"
2072 " (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n"
2073 " (i) - interface, (a/S) - aggregated/Suppressed\n\n"
2074 " Network Next Hop Via Metric Tag Time\n");
2075
2076 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
2077 if ((aggregate = rp->aggregate) != NULL) {
2078 p = (struct prefix_ipv6 *)&rp->p;
2079
2080 #ifdef DEBUG
2081 vty_out(vty, "R(a) %d/%d %s/%d ", aggregate->count,
2082 aggregate->suppress, inet6_ntoa(p->prefix),
2083 p->prefixlen);
2084 #else
2085 vty_out(vty, "R(a) %s/%d ", inet6_ntoa(p->prefix),
2086 p->prefixlen);
2087 #endif /* DEBUG */
2088 vty_out(vty, "\n");
2089 vty_out(vty, "%*s", 18, " ");
2090
2091 vty_out(vty, "%*s", 28, " ");
2092 vty_out(vty, "self %2d %3" ROUTE_TAG_PRI "\n",
2093 aggregate->metric, (route_tag_t)aggregate->tag);
2094 }
2095
2096 if ((list = rp->info) != NULL)
2097 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
2098 p = (struct prefix_ipv6 *)&rp->p;
2099
2100 #ifdef DEBUG
2101 vty_out(vty, "%c(%s) 0/%d %s/%d ",
2102 zebra_route_char(rinfo->type),
2103 ripng_route_subtype_print(rinfo),
2104 rinfo->suppress, inet6_ntoa(p->prefix),
2105 p->prefixlen);
2106 #else
2107 vty_out(vty, "%c(%s) %s/%d ",
2108 zebra_route_char(rinfo->type),
2109 ripng_route_subtype_print(rinfo),
2110 inet6_ntoa(p->prefix), p->prefixlen);
2111 #endif /* DEBUG */
2112 vty_out(vty, "\n");
2113 vty_out(vty, "%*s", 18, " ");
2114 len = vty_out(vty, "%s",
2115 inet6_ntoa(rinfo->nexthop));
2116
2117 len = 28 - len;
2118 if (len > 0)
2119 vty_out(vty, "%*s", len, " ");
2120
2121 /* from */
2122 if ((rinfo->type == ZEBRA_ROUTE_RIPNG)
2123 && (rinfo->sub_type == RIPNG_ROUTE_RTE)) {
2124 len = vty_out(
2125 vty, "%s",
2126 ifindex2ifname(
2127 rinfo->ifindex,
2128 ripng->vrf->vrf_id));
2129 } else if (rinfo->metric
2130 == RIPNG_METRIC_INFINITY) {
2131 len = vty_out(vty, "kill");
2132 } else
2133 len = vty_out(vty, "self");
2134
2135 len = 9 - len;
2136 if (len > 0)
2137 vty_out(vty, "%*s", len, " ");
2138
2139 vty_out(vty, " %2d %3" ROUTE_TAG_PRI " ",
2140 rinfo->metric, (route_tag_t)rinfo->tag);
2141
2142 /* time */
2143 if ((rinfo->type == ZEBRA_ROUTE_RIPNG)
2144 && (rinfo->sub_type == RIPNG_ROUTE_RTE)) {
2145 /* RTE from remote RIP routers */
2146 ripng_vty_out_uptime(vty, rinfo);
2147 } else if (rinfo->metric
2148 == RIPNG_METRIC_INFINITY) {
2149 /* poisonous reversed routes (gc) */
2150 ripng_vty_out_uptime(vty, rinfo);
2151 }
2152
2153 vty_out(vty, "\n");
2154 }
2155 }
2156
2157 return CMD_SUCCESS;
2158 }
2159
2160 DEFUN (show_ipv6_ripng_status,
2161 show_ipv6_ripng_status_cmd,
2162 "show ipv6 ripng [vrf NAME] status",
2163 SHOW_STR
2164 IPV6_STR
2165 "Show RIPng routes\n"
2166 VRF_CMD_HELP_STR
2167 "IPv6 routing protocol process parameters and statistics\n")
2168 {
2169 struct ripng *ripng;
2170 struct interface *ifp;
2171 const char *vrf_name;
2172 int idx = 0;
2173
2174 if (argv_find(argv, argc, "vrf", &idx))
2175 vrf_name = argv[idx + 1]->arg;
2176 else
2177 vrf_name = VRF_DEFAULT_NAME;
2178
2179 ripng = ripng_lookup_by_vrf_name(vrf_name);
2180 if (!ripng) {
2181 vty_out(vty, "%% RIPng instance not found\n");
2182 return CMD_SUCCESS;
2183 }
2184 if (!ripng->enabled) {
2185 vty_out(vty, "%% RIPng instance is disabled\n");
2186 return CMD_SUCCESS;
2187 }
2188
2189 vty_out(vty, "Routing Protocol is \"RIPng\"\n");
2190 vty_out(vty, " Sending updates every %u seconds with +/-50%%,",
2191 ripng->update_time);
2192 vty_out(vty, " next due in %lu seconds\n",
2193 thread_timer_remain_second(ripng->t_update));
2194 vty_out(vty, " Timeout after %u seconds,", ripng->timeout_time);
2195 vty_out(vty, " garbage collect after %u seconds\n",
2196 ripng->garbage_time);
2197
2198 /* Filtering status show. */
2199 config_show_distribute(vty, ripng->distribute_ctx);
2200
2201 /* Default metric information. */
2202 vty_out(vty, " Default redistribution metric is %d\n",
2203 ripng->default_metric);
2204
2205 /* Redistribute information. */
2206 vty_out(vty, " Redistributing:");
2207 ripng_redistribute_write(vty, ripng);
2208 vty_out(vty, "\n");
2209
2210 vty_out(vty, " Default version control: send version %d,",
2211 ripng->version);
2212 vty_out(vty, " receive version %d \n", ripng->version);
2213
2214 vty_out(vty, " Interface Send Recv\n");
2215
2216 FOR_ALL_INTERFACES (ripng->vrf, ifp) {
2217 struct ripng_interface *ri;
2218
2219 ri = ifp->info;
2220
2221 if (ri->enable_network || ri->enable_interface) {
2222
2223 vty_out(vty, " %-17s%-3d %-3d\n", ifp->name,
2224 ripng->version, ripng->version);
2225 }
2226 }
2227
2228 vty_out(vty, " Routing for Networks:\n");
2229 ripng_network_write(vty, ripng);
2230
2231 vty_out(vty, " Routing Information Sources:\n");
2232 vty_out(vty,
2233 " Gateway BadPackets BadRoutes Distance Last Update\n");
2234 ripng_peer_display(vty, ripng);
2235
2236 return CMD_SUCCESS;
2237 }
2238
2239 #if 0
2240 /* RIPng update timer setup. */
2241 DEFUN (ripng_update_timer,
2242 ripng_update_timer_cmd,
2243 "update-timer SECOND",
2244 "Set RIPng update timer in seconds\n"
2245 "Seconds\n")
2246 {
2247 unsigned long update;
2248 char *endptr = NULL;
2249
2250 update = strtoul (argv[0], &endptr, 10);
2251 if (update == ULONG_MAX || *endptr != '\0')
2252 {
2253 vty_out (vty, "update timer value error\n");
2254 return CMD_WARNING_CONFIG_FAILED;
2255 }
2256
2257 ripng->update_time = update;
2258
2259 ripng_event (RIPNG_UPDATE_EVENT, 0);
2260 return CMD_SUCCESS;
2261 }
2262
2263 DEFUN (no_ripng_update_timer,
2264 no_ripng_update_timer_cmd,
2265 "no update-timer SECOND",
2266 NO_STR
2267 "Unset RIPng update timer in seconds\n"
2268 "Seconds\n")
2269 {
2270 ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT;
2271 ripng_event (RIPNG_UPDATE_EVENT, 0);
2272 return CMD_SUCCESS;
2273 }
2274
2275 /* RIPng timeout timer setup. */
2276 DEFUN (ripng_timeout_timer,
2277 ripng_timeout_timer_cmd,
2278 "timeout-timer SECOND",
2279 "Set RIPng timeout timer in seconds\n"
2280 "Seconds\n")
2281 {
2282 unsigned long timeout;
2283 char *endptr = NULL;
2284
2285 timeout = strtoul (argv[0], &endptr, 10);
2286 if (timeout == ULONG_MAX || *endptr != '\0')
2287 {
2288 vty_out (vty, "timeout timer value error\n");
2289 return CMD_WARNING_CONFIG_FAILED;
2290 }
2291
2292 ripng->timeout_time = timeout;
2293
2294 return CMD_SUCCESS;
2295 }
2296
2297 DEFUN (no_ripng_timeout_timer,
2298 no_ripng_timeout_timer_cmd,
2299 "no timeout-timer SECOND",
2300 NO_STR
2301 "Unset RIPng timeout timer in seconds\n"
2302 "Seconds\n")
2303 {
2304 ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT;
2305 return CMD_SUCCESS;
2306 }
2307
2308 /* RIPng garbage timer setup. */
2309 DEFUN (ripng_garbage_timer,
2310 ripng_garbage_timer_cmd,
2311 "garbage-timer SECOND",
2312 "Set RIPng garbage timer in seconds\n"
2313 "Seconds\n")
2314 {
2315 unsigned long garbage;
2316 char *endptr = NULL;
2317
2318 garbage = strtoul (argv[0], &endptr, 10);
2319 if (garbage == ULONG_MAX || *endptr != '\0')
2320 {
2321 vty_out (vty, "garbage timer value error\n");
2322 return CMD_WARNING_CONFIG_FAILED;
2323 }
2324
2325 ripng->garbage_time = garbage;
2326
2327 return CMD_SUCCESS;
2328 }
2329
2330 DEFUN (no_ripng_garbage_timer,
2331 no_ripng_garbage_timer_cmd,
2332 "no garbage-timer SECOND",
2333 NO_STR
2334 "Unset RIPng garbage timer in seconds\n"
2335 "Seconds\n")
2336 {
2337 ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT;
2338 return CMD_SUCCESS;
2339 }
2340 #endif /* 0 */
2341
2342 #if 0
2343 DEFUN (show_ipv6_protocols,
2344 show_ipv6_protocols_cmd,
2345 "show ipv6 protocols",
2346 SHOW_STR
2347 IPV6_STR
2348 "Routing protocol information\n")
2349 {
2350 if (! ripng)
2351 return CMD_SUCCESS;
2352
2353 vty_out (vty, "Routing Protocol is \"ripng\"\n");
2354
2355 vty_out (vty, "Sending updates every %ld seconds, next due in %d seconds\n",
2356 ripng->update_time, 0);
2357
2358 vty_out (vty, "Timerout after %ld seconds, garbage correct %ld\n",
2359 ripng->timeout_time,
2360 ripng->garbage_time);
2361
2362 vty_out (vty, "Outgoing update filter list for all interfaces is not set");
2363 vty_out (vty, "Incoming update filter list for all interfaces is not set");
2364
2365 return CMD_SUCCESS;
2366 }
2367 #endif
2368
2369 /* Update ECMP routes to zebra when ECMP is disabled. */
2370 void ripng_ecmp_disable(struct ripng *ripng)
2371 {
2372 struct agg_node *rp;
2373 struct ripng_info *rinfo, *tmp_rinfo;
2374 struct list *list;
2375 struct listnode *node, *nextnode;
2376
2377 if (!ripng)
2378 return;
2379
2380 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp))
2381 if ((list = rp->info) != NULL && listcount(list) > 1) {
2382 rinfo = listgetdata(listhead(list));
2383 if (!ripng_route_rte(rinfo))
2384 continue;
2385
2386 /* Drop all other entries, except the first one. */
2387 for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo))
2388 if (tmp_rinfo != rinfo) {
2389 RIPNG_TIMER_OFF(tmp_rinfo->t_timeout);
2390 RIPNG_TIMER_OFF(
2391 tmp_rinfo->t_garbage_collect);
2392 list_delete_node(list, node);
2393 ripng_info_free(tmp_rinfo);
2394 }
2395
2396 /* Update zebra. */
2397 ripng_zebra_ipv6_add(ripng, rp);
2398
2399 /* Set the route change flag. */
2400 SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED);
2401
2402 /* Signal the output process to trigger an update. */
2403 ripng_event(ripng, RIPNG_TRIGGERED_UPDATE, 0);
2404 }
2405 }
2406
2407 /* RIPng configuration write function. */
2408 static int ripng_config_write(struct vty *vty)
2409 {
2410 struct ripng *ripng;
2411 int write = 0;
2412
2413 RB_FOREACH(ripng, ripng_instance_head, &ripng_instances) {
2414 char xpath[XPATH_MAXLEN];
2415 struct lyd_node *dnode;
2416
2417 snprintf(xpath, sizeof(xpath),
2418 "/frr-ripngd:ripngd/instance[vrf='%s']",
2419 ripng->vrf_name);
2420
2421 dnode = yang_dnode_get(running_config->dnode, xpath);
2422 assert(dnode);
2423
2424 nb_cli_show_dnode_cmds(vty, dnode, false);
2425
2426 config_write_distribute(vty, ripng->distribute_ctx);
2427 if (strmatch(ripng->vrf_name, VRF_DEFAULT_NAME))
2428 config_write_if_rmap(vty);
2429
2430 write = 1;
2431 }
2432
2433 return write;
2434 }
2435
2436 /* RIPng node structure. */
2437 static struct cmd_node cmd_ripng_node = {
2438 RIPNG_NODE, "%s(config-router)# ", 1,
2439 };
2440
2441 static void ripng_distribute_update(struct distribute_ctx *ctx,
2442 struct distribute *dist)
2443 {
2444 struct interface *ifp;
2445 struct ripng_interface *ri;
2446 struct access_list *alist;
2447 struct prefix_list *plist;
2448
2449 if (!ctx->vrf || !dist->ifname)
2450 return;
2451
2452 ifp = if_lookup_by_name(dist->ifname, ctx->vrf->vrf_id);
2453 if (ifp == NULL)
2454 return;
2455
2456 ri = ifp->info;
2457
2458 if (dist->list[DISTRIBUTE_V6_IN]) {
2459 alist = access_list_lookup(AFI_IP6,
2460 dist->list[DISTRIBUTE_V6_IN]);
2461 if (alist)
2462 ri->list[RIPNG_FILTER_IN] = alist;
2463 else
2464 ri->list[RIPNG_FILTER_IN] = NULL;
2465 } else
2466 ri->list[RIPNG_FILTER_IN] = NULL;
2467
2468 if (dist->list[DISTRIBUTE_V6_OUT]) {
2469 alist = access_list_lookup(AFI_IP6,
2470 dist->list[DISTRIBUTE_V6_OUT]);
2471 if (alist)
2472 ri->list[RIPNG_FILTER_OUT] = alist;
2473 else
2474 ri->list[RIPNG_FILTER_OUT] = NULL;
2475 } else
2476 ri->list[RIPNG_FILTER_OUT] = NULL;
2477
2478 if (dist->prefix[DISTRIBUTE_V6_IN]) {
2479 plist = prefix_list_lookup(AFI_IP6,
2480 dist->prefix[DISTRIBUTE_V6_IN]);
2481 if (plist)
2482 ri->prefix[RIPNG_FILTER_IN] = plist;
2483 else
2484 ri->prefix[RIPNG_FILTER_IN] = NULL;
2485 } else
2486 ri->prefix[RIPNG_FILTER_IN] = NULL;
2487
2488 if (dist->prefix[DISTRIBUTE_V6_OUT]) {
2489 plist = prefix_list_lookup(AFI_IP6,
2490 dist->prefix[DISTRIBUTE_V6_OUT]);
2491 if (plist)
2492 ri->prefix[RIPNG_FILTER_OUT] = plist;
2493 else
2494 ri->prefix[RIPNG_FILTER_OUT] = NULL;
2495 } else
2496 ri->prefix[RIPNG_FILTER_OUT] = NULL;
2497 }
2498
2499 void ripng_distribute_update_interface(struct interface *ifp)
2500 {
2501 struct ripng_interface *ri = ifp->info;
2502 struct ripng *ripng = ri->ripng;
2503 struct distribute *dist;
2504
2505 if (!ripng)
2506 return;
2507 dist = distribute_lookup(ripng->distribute_ctx, ifp->name);
2508 if (dist)
2509 ripng_distribute_update(ripng->distribute_ctx, dist);
2510 }
2511
2512 /* Update all interface's distribute list. */
2513 static void ripng_distribute_update_all(struct prefix_list *notused)
2514 {
2515 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
2516 struct interface *ifp;
2517
2518 FOR_ALL_INTERFACES (vrf, ifp)
2519 ripng_distribute_update_interface(ifp);
2520 }
2521
2522 static void ripng_distribute_update_all_wrapper(struct access_list *notused)
2523 {
2524 ripng_distribute_update_all(NULL);
2525 }
2526
2527 /* delete all the added ripng routes. */
2528 void ripng_clean(struct ripng *ripng)
2529 {
2530 if (ripng->enabled)
2531 ripng_instance_disable(ripng);
2532
2533 for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
2534 if (ripng->route_map[i].name)
2535 free(ripng->route_map[i].name);
2536
2537 agg_table_finish(ripng->table);
2538 list_delete(&ripng->peer_list);
2539 distribute_list_delete(&ripng->distribute_ctx);
2540
2541 stream_free(ripng->ibuf);
2542 stream_free(ripng->obuf);
2543
2544 ripng_clean_network(ripng);
2545 ripng_passive_interface_clean(ripng);
2546 vector_free(ripng->enable_if);
2547 agg_table_finish(ripng->enable_network);
2548 vector_free(ripng->passive_interface);
2549 list_delete(&ripng->offset_list_master);
2550 ripng_interface_clean(ripng);
2551 ripng_redistribute_clean(ripng);
2552
2553 RB_REMOVE(ripng_instance_head, &ripng_instances, ripng);
2554 XFREE(MTYPE_RIPNG_VRF_NAME, ripng->vrf_name);
2555 XFREE(MTYPE_RIPNG, ripng);
2556 }
2557
2558 static void ripng_if_rmap_update(struct if_rmap *if_rmap)
2559 {
2560 struct interface *ifp;
2561 struct ripng_interface *ri;
2562 struct route_map *rmap;
2563
2564 ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT);
2565 if (ifp == NULL)
2566 return;
2567
2568 ri = ifp->info;
2569
2570 if (if_rmap->routemap[IF_RMAP_IN]) {
2571 rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]);
2572 if (rmap)
2573 ri->routemap[IF_RMAP_IN] = rmap;
2574 else
2575 ri->routemap[IF_RMAP_IN] = NULL;
2576 } else
2577 ri->routemap[RIPNG_FILTER_IN] = NULL;
2578
2579 if (if_rmap->routemap[IF_RMAP_OUT]) {
2580 rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]);
2581 if (rmap)
2582 ri->routemap[IF_RMAP_OUT] = rmap;
2583 else
2584 ri->routemap[IF_RMAP_OUT] = NULL;
2585 } else
2586 ri->routemap[RIPNG_FILTER_OUT] = NULL;
2587 }
2588
2589 void ripng_if_rmap_update_interface(struct interface *ifp)
2590 {
2591 struct if_rmap *if_rmap;
2592
2593 if_rmap = if_rmap_lookup(ifp->name);
2594 if (if_rmap)
2595 ripng_if_rmap_update(if_rmap);
2596 }
2597
2598 static void ripng_routemap_update_redistribute(struct ripng *ripng)
2599 {
2600 for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2601 if (ripng->route_map[i].name)
2602 ripng->route_map[i].map = route_map_lookup_by_name(
2603 ripng->route_map[i].name);
2604 }
2605 }
2606
2607 static void ripng_routemap_update(const char *unused)
2608 {
2609 struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
2610 struct ripng *ripng;
2611 struct interface *ifp;
2612
2613 FOR_ALL_INTERFACES (vrf, ifp)
2614 ripng_if_rmap_update_interface(ifp);
2615
2616 ripng = vrf->info;
2617 if (ripng)
2618 ripng_routemap_update_redistribute(ripng);
2619 }
2620
2621 /* Link RIPng instance to VRF. */
2622 static void ripng_vrf_link(struct ripng *ripng, struct vrf *vrf)
2623 {
2624 struct interface *ifp;
2625
2626 ripng->vrf = vrf;
2627 ripng->distribute_ctx->vrf = vrf;
2628 vrf->info = ripng;
2629
2630 FOR_ALL_INTERFACES (vrf, ifp)
2631 ripng_interface_sync(ifp);
2632 }
2633
2634 /* Unlink RIPng instance from VRF. */
2635 static void ripng_vrf_unlink(struct ripng *ripng, struct vrf *vrf)
2636 {
2637 struct interface *ifp;
2638
2639 ripng->vrf = NULL;
2640 ripng->distribute_ctx->vrf = NULL;
2641 vrf->info = NULL;
2642
2643 FOR_ALL_INTERFACES (vrf, ifp)
2644 ripng_interface_sync(ifp);
2645 }
2646
2647 static void ripng_instance_enable(struct ripng *ripng, struct vrf *vrf,
2648 int sock)
2649 {
2650 ripng->sock = sock;
2651
2652 ripng_vrf_link(ripng, vrf);
2653 ripng->enabled = true;
2654
2655 /* Create read and timer thread. */
2656 ripng_event(ripng, RIPNG_READ, ripng->sock);
2657 ripng_event(ripng, RIPNG_UPDATE_EVENT, 1);
2658
2659 ripng_zebra_vrf_register(vrf);
2660 }
2661
2662 static void ripng_instance_disable(struct ripng *ripng)
2663 {
2664 struct vrf *vrf = ripng->vrf;
2665 struct agg_node *rp;
2666
2667 /* Clear RIPng routes */
2668 for (rp = agg_route_top(ripng->table); rp; rp = agg_route_next(rp)) {
2669 struct ripng_aggregate *aggregate;
2670 struct list *list;
2671
2672 if ((list = rp->info) != NULL) {
2673 struct ripng_info *rinfo;
2674 struct listnode *listnode;
2675
2676 rinfo = listgetdata(listhead(list));
2677 if (ripng_route_rte(rinfo))
2678 ripng_zebra_ipv6_delete(ripng, rp);
2679
2680 for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
2681 RIPNG_TIMER_OFF(rinfo->t_timeout);
2682 RIPNG_TIMER_OFF(rinfo->t_garbage_collect);
2683 ripng_info_free(rinfo);
2684 }
2685 list_delete(&list);
2686 rp->info = NULL;
2687 agg_unlock_node(rp);
2688 }
2689
2690 if ((aggregate = rp->aggregate) != NULL) {
2691 ripng_aggregate_free(aggregate);
2692 rp->aggregate = NULL;
2693 agg_unlock_node(rp);
2694 }
2695 }
2696
2697 /* Cancel the RIPng timers */
2698 RIPNG_TIMER_OFF(ripng->t_update);
2699 RIPNG_TIMER_OFF(ripng->t_triggered_update);
2700 RIPNG_TIMER_OFF(ripng->t_triggered_interval);
2701
2702 /* Cancel the read thread */
2703 if (ripng->t_read) {
2704 thread_cancel(ripng->t_read);
2705 ripng->t_read = NULL;
2706 }
2707
2708 /* Close the RIPng socket */
2709 if (ripng->sock >= 0) {
2710 close(ripng->sock);
2711 ripng->sock = -1;
2712 }
2713
2714 /* Clear existing peers. */
2715 list_delete_all_node(ripng->peer_list);
2716
2717 ripng_zebra_vrf_deregister(vrf);
2718
2719 ripng_vrf_unlink(ripng, vrf);
2720 ripng->enabled = false;
2721 }
2722
2723 static int ripng_vrf_new(struct vrf *vrf)
2724 {
2725 if (IS_RIPNG_DEBUG_EVENT)
2726 zlog_debug("%s: VRF created: %s(%u)", __func__, vrf->name,
2727 vrf->vrf_id);
2728
2729 return 0;
2730 }
2731
2732 static int ripng_vrf_delete(struct vrf *vrf)
2733 {
2734 if (IS_RIPNG_DEBUG_EVENT)
2735 zlog_debug("%s: VRF deleted: %s(%u)", __func__, vrf->name,
2736 vrf->vrf_id);
2737
2738 return 0;
2739 }
2740
2741 static int ripng_vrf_enable(struct vrf *vrf)
2742 {
2743 struct ripng *ripng;
2744 int socket;
2745
2746 ripng = ripng_lookup_by_vrf_name(vrf->name);
2747 if (!ripng || ripng->enabled)
2748 return 0;
2749
2750 if (IS_RIPNG_DEBUG_EVENT)
2751 zlog_debug("%s: VRF %s(%u) enabled", __func__, vrf->name,
2752 vrf->vrf_id);
2753
2754 /* Activate the VRF RIPng instance. */
2755 if (!ripng->enabled) {
2756 socket = ripng_make_socket(vrf);
2757 if (socket < 0)
2758 return -1;
2759
2760 ripng_instance_enable(ripng, vrf, socket);
2761 }
2762
2763 return 0;
2764 }
2765
2766 static int ripng_vrf_disable(struct vrf *vrf)
2767 {
2768 struct ripng *ripng;
2769
2770 ripng = ripng_lookup_by_vrf_name(vrf->name);
2771 if (!ripng || !ripng->enabled)
2772 return 0;
2773
2774 if (IS_RIPNG_DEBUG_EVENT)
2775 zlog_debug("%s: VRF %s(%u) disabled", __func__, vrf->name,
2776 vrf->vrf_id);
2777
2778 /* Deactivate the VRF RIPng instance. */
2779 if (ripng->enabled)
2780 ripng_instance_disable(ripng);
2781
2782 return 0;
2783 }
2784
2785 void ripng_vrf_init(void)
2786 {
2787 vrf_init(ripng_vrf_new, ripng_vrf_enable, ripng_vrf_disable,
2788 ripng_vrf_delete, NULL);
2789 }
2790
2791 void ripng_vrf_terminate(void)
2792 {
2793 vrf_terminate();
2794 }
2795
2796 /* Initialize ripng structure and set commands. */
2797 void ripng_init()
2798 {
2799 /* Install RIPNG_NODE. */
2800 install_node(&cmd_ripng_node, ripng_config_write);
2801
2802 /* Install ripng commands. */
2803 install_element(VIEW_NODE, &show_ipv6_ripng_cmd);
2804 install_element(VIEW_NODE, &show_ipv6_ripng_status_cmd);
2805
2806 install_default(RIPNG_NODE);
2807
2808 #if 0
2809 install_element (VIEW_NODE, &show_ipv6_protocols_cmd);
2810 install_element (RIPNG_NODE, &ripng_update_timer_cmd);
2811 install_element (RIPNG_NODE, &no_ripng_update_timer_cmd);
2812 install_element (RIPNG_NODE, &ripng_timeout_timer_cmd);
2813 install_element (RIPNG_NODE, &no_ripng_timeout_timer_cmd);
2814 install_element (RIPNG_NODE, &ripng_garbage_timer_cmd);
2815 install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd);
2816 #endif /* 0 */
2817
2818 ripng_if_init();
2819 ripng_debug_init();
2820
2821 /* Access list install. */
2822 access_list_init();
2823 access_list_add_hook(ripng_distribute_update_all_wrapper);
2824 access_list_delete_hook(ripng_distribute_update_all_wrapper);
2825
2826 /* Prefix list initialize.*/
2827 prefix_list_init();
2828 prefix_list_add_hook(ripng_distribute_update_all);
2829 prefix_list_delete_hook(ripng_distribute_update_all);
2830
2831 /* Distribute list install. */
2832 distribute_list_init(RIPNG_NODE);
2833
2834 /* Route-map for interface. */
2835 ripng_route_map_init();
2836
2837 route_map_add_hook(ripng_routemap_update);
2838 route_map_delete_hook(ripng_routemap_update);
2839
2840 if_rmap_init(RIPNG_NODE);
2841 if_rmap_hook_add(ripng_if_rmap_update);
2842 if_rmap_hook_delete(ripng_if_rmap_update);
2843 }