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