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