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