diff options
Diffstat (limited to 'ripngd/ripngd.c')
| -rw-r--r-- | ripngd/ripngd.c | 4697 |
1 files changed, 2306 insertions, 2391 deletions
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index a50204ae35..51475dc642 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * 02111-1307, USA. */ #include <zebra.h> @@ -47,493 +47,470 @@ ripng->fd must be negative value. */ struct ripng *ripng = NULL; -enum -{ - ripng_all_route, - ripng_changed_route, +enum { ripng_all_route, + ripng_changed_route, }; extern struct zebra_privs_t ripngd_privs; /* Prototypes. */ -void -ripng_output_process (struct interface *, struct sockaddr_in6 *, int); +void ripng_output_process(struct interface *, struct sockaddr_in6 *, int); -int -ripng_triggered_update (struct thread *); +int ripng_triggered_update(struct thread *); /* RIPng next hop specification. */ -struct ripng_nexthop -{ - enum ripng_nexthop_type - { - RIPNG_NEXTHOP_UNSPEC, - RIPNG_NEXTHOP_ADDRESS - } flag; - struct in6_addr address; +struct ripng_nexthop { + enum ripng_nexthop_type { + RIPNG_NEXTHOP_UNSPEC, + RIPNG_NEXTHOP_ADDRESS + } flag; + struct in6_addr address; }; -static int -ripng_route_rte (struct ripng_info *rinfo) +static int ripng_route_rte(struct ripng_info *rinfo) { - return (rinfo->type == ZEBRA_ROUTE_RIPNG && rinfo->sub_type == RIPNG_ROUTE_RTE); + return (rinfo->type == ZEBRA_ROUTE_RIPNG + && rinfo->sub_type == RIPNG_ROUTE_RTE); } /* Allocate new ripng information. */ -struct ripng_info * -ripng_info_new () +struct ripng_info *ripng_info_new() { - struct ripng_info *new; + struct ripng_info *new; - new = XCALLOC (MTYPE_RIPNG_ROUTE, sizeof (struct ripng_info)); - return new; + new = XCALLOC(MTYPE_RIPNG_ROUTE, sizeof(struct ripng_info)); + return new; } /* Free ripng information. */ -void -ripng_info_free (struct ripng_info *rinfo) +void ripng_info_free(struct ripng_info *rinfo) { - XFREE (MTYPE_RIPNG_ROUTE, rinfo); + XFREE(MTYPE_RIPNG_ROUTE, rinfo); } /* Create ripng socket. */ -static int -ripng_make_socket (void) +static int ripng_make_socket(void) { - int ret; - int sock; - struct sockaddr_in6 ripaddr; + int ret; + int sock; + struct sockaddr_in6 ripaddr; - sock = socket (AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) - { - zlog_err("Can't make ripng socket"); - return sock; - } + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock < 0) { + zlog_err("Can't make ripng socket"); + return sock; + } - setsockopt_so_recvbuf (sock, 8096); - ret = setsockopt_ipv6_pktinfo (sock, 1); - if (ret < 0) - return ret; + setsockopt_so_recvbuf(sock, 8096); + ret = setsockopt_ipv6_pktinfo(sock, 1); + if (ret < 0) + return ret; #ifdef IPTOS_PREC_INTERNETCONTROL - ret = setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL); - if (ret < 0) - return ret; + ret = setsockopt_ipv6_tclass(sock, IPTOS_PREC_INTERNETCONTROL); + if (ret < 0) + return ret; #endif - ret = setsockopt_ipv6_multicast_hops (sock, 255); - if (ret < 0) - return ret; - ret = setsockopt_ipv6_multicast_loop (sock, 0); - if (ret < 0) - return ret; - ret = setsockopt_ipv6_hoplimit (sock, 1); - if (ret < 0) - return ret; - - memset (&ripaddr, 0, sizeof (ripaddr)); - ripaddr.sin6_family = AF_INET6; + ret = setsockopt_ipv6_multicast_hops(sock, 255); + if (ret < 0) + return ret; + ret = setsockopt_ipv6_multicast_loop(sock, 0); + if (ret < 0) + return ret; + ret = setsockopt_ipv6_hoplimit(sock, 1); + if (ret < 0) + return ret; + + memset(&ripaddr, 0, sizeof(ripaddr)); + ripaddr.sin6_family = AF_INET6; #ifdef SIN6_LEN - ripaddr.sin6_len = sizeof (struct sockaddr_in6); + ripaddr.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - ripaddr.sin6_port = htons (RIPNG_PORT_DEFAULT); + ripaddr.sin6_port = htons(RIPNG_PORT_DEFAULT); - if (ripngd_privs.change (ZPRIVS_RAISE)) - zlog_err ("ripng_make_socket: could not raise privs"); - - ret = bind (sock, (struct sockaddr *) &ripaddr, sizeof (ripaddr)); - if (ret < 0) - { - zlog_err("Can't bind ripng socket: %s.", safe_strerror(errno)); - if (ripngd_privs.change (ZPRIVS_LOWER)) - zlog_err ("ripng_make_socket: could not lower privs"); - return ret; - } - if (ripngd_privs.change (ZPRIVS_LOWER)) - zlog_err ("ripng_make_socket: could not lower privs"); - return sock; + if (ripngd_privs.change(ZPRIVS_RAISE)) + zlog_err("ripng_make_socket: could not raise privs"); + + ret = bind(sock, (struct sockaddr *)&ripaddr, sizeof(ripaddr)); + if (ret < 0) { + zlog_err("Can't bind ripng socket: %s.", safe_strerror(errno)); + if (ripngd_privs.change(ZPRIVS_LOWER)) + zlog_err("ripng_make_socket: could not lower privs"); + return ret; + } + if (ripngd_privs.change(ZPRIVS_LOWER)) + zlog_err("ripng_make_socket: could not lower privs"); + return sock; } /* Send RIPng packet. */ -int -ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to, - struct interface *ifp) -{ - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsgptr; - char adata [256]; - struct in6_pktinfo *pkt; - struct sockaddr_in6 addr; - - if (IS_RIPNG_DEBUG_SEND) { - if (to) - zlog_debug ("send to %s", inet6_ntoa (to->sin6_addr)); - zlog_debug (" send interface %s", ifp->name); - zlog_debug (" send packet size %d", bufsize); - } - - memset (&addr, 0, sizeof (struct sockaddr_in6)); - addr.sin6_family = AF_INET6; +int ripng_send_packet(caddr_t buf, int bufsize, struct sockaddr_in6 *to, + struct interface *ifp) +{ + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + char adata[256]; + struct in6_pktinfo *pkt; + struct sockaddr_in6 addr; + + if (IS_RIPNG_DEBUG_SEND) { + if (to) + zlog_debug("send to %s", inet6_ntoa(to->sin6_addr)); + zlog_debug(" send interface %s", ifp->name); + zlog_debug(" send packet size %d", bufsize); + } + + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_family = AF_INET6; #ifdef SIN6_LEN - addr.sin6_len = sizeof (struct sockaddr_in6); + addr.sin6_len = sizeof(struct sockaddr_in6); #endif /* SIN6_LEN */ - addr.sin6_flowinfo = htonl (RIPNG_PRIORITY_DEFAULT); - - /* When destination is specified. */ - if (to != NULL) - { - addr.sin6_addr = to->sin6_addr; - addr.sin6_port = to->sin6_port; - } - else - { - inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr); - addr.sin6_port = htons (RIPNG_PORT_DEFAULT); - } - - msg.msg_name = (void *) &addr; - msg.msg_namelen = sizeof (struct sockaddr_in6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - - iov.iov_base = buf; - iov.iov_len = bufsize; - - cmsgptr = (struct cmsghdr *)adata; - cmsgptr->cmsg_len = CMSG_LEN(sizeof (struct in6_pktinfo)); - cmsgptr->cmsg_level = IPPROTO_IPV6; - cmsgptr->cmsg_type = IPV6_PKTINFO; - - pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); - memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr)); - pkt->ipi6_ifindex = ifp->ifindex; - - ret = sendmsg (ripng->sock, &msg, 0); + addr.sin6_flowinfo = htonl(RIPNG_PRIORITY_DEFAULT); + + /* When destination is specified. */ + if (to != NULL) { + addr.sin6_addr = to->sin6_addr; + addr.sin6_port = to->sin6_port; + } else { + inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr); + addr.sin6_port = htons(RIPNG_PORT_DEFAULT); + } - if (ret < 0) { - if (to) - zlog_err ("RIPng send fail on %s to %s: %s", ifp->name, - inet6_ntoa (to->sin6_addr), safe_strerror (errno)); - else - zlog_err ("RIPng send fail on %s: %s", ifp->name, safe_strerror (errno)); - } + msg.msg_name = (void *)&addr; + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + + iov.iov_base = buf; + iov.iov_len = bufsize; + + cmsgptr = (struct cmsghdr *)adata; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + + pkt = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); + pkt->ipi6_ifindex = ifp->ifindex; + + ret = sendmsg(ripng->sock, &msg, 0); + + if (ret < 0) { + if (to) + zlog_err("RIPng send fail on %s to %s: %s", ifp->name, + inet6_ntoa(to->sin6_addr), + safe_strerror(errno)); + else + zlog_err("RIPng send fail on %s: %s", ifp->name, + safe_strerror(errno)); + } - return ret; + return ret; } /* Receive UDP RIPng packet from socket. */ -static int -ripng_recv_packet (int sock, u_char *buf, int bufsize, - struct sockaddr_in6 *from, ifindex_t *ifindex, - int *hoplimit) -{ - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *cmsgptr; - struct in6_addr dst = { .s6_addr = { 0 } }; - - memset(&dst, 0, sizeof(struct in6_addr)); - - /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this - point I can't determine size of cmsghdr */ - char adata[1024]; - - /* Fill in message and iovec. */ - msg.msg_name = (void *) from; - msg.msg_namelen = sizeof (struct sockaddr_in6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = sizeof adata; - iov.iov_base = buf; - iov.iov_len = bufsize; - - /* If recvmsg fail return minus value. */ - ret = recvmsg (sock, &msg, 0); - if (ret < 0) - return ret; - - for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; - cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) - { - /* I want interface index which this packet comes from. */ - if (cmsgptr->cmsg_level == IPPROTO_IPV6 && - cmsgptr->cmsg_type == IPV6_PKTINFO) - { - struct in6_pktinfo *ptr; - - ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr); - *ifindex = ptr->ipi6_ifindex; - dst = ptr->ipi6_addr; - - if (*ifindex == 0) - zlog_warn ("Interface index returned by IPV6_PKTINFO is zero"); - } - - /* Incoming packet's multicast hop limit. */ - if (cmsgptr->cmsg_level == IPPROTO_IPV6 && - cmsgptr->cmsg_type == IPV6_HOPLIMIT) - { - int *phoplimit = (int *) CMSG_DATA (cmsgptr); - *hoplimit = *phoplimit; +static int ripng_recv_packet(int sock, u_char *buf, int bufsize, + struct sockaddr_in6 *from, ifindex_t *ifindex, + int *hoplimit) +{ + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + struct in6_addr dst = {.s6_addr = {0}}; + + memset(&dst, 0, sizeof(struct in6_addr)); + + /* Ancillary data. This store cmsghdr and in6_pktinfo. But at this + point I can't determine size of cmsghdr */ + char adata[1024]; + + /* Fill in message and iovec. */ + msg.msg_name = (void *)from; + msg.msg_namelen = sizeof(struct sockaddr_in6); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + iov.iov_base = buf; + iov.iov_len = bufsize; + + /* If recvmsg fail return minus value. */ + ret = recvmsg(sock, &msg, 0); + if (ret < 0) + return ret; + + for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL; + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + /* I want interface index which this packet comes from. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_PKTINFO) { + struct in6_pktinfo *ptr; + + ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); + *ifindex = ptr->ipi6_ifindex; + dst = ptr->ipi6_addr; + + if (*ifindex == 0) + zlog_warn( + "Interface index returned by IPV6_PKTINFO is zero"); + } + + /* Incoming packet's multicast hop limit. */ + if (cmsgptr->cmsg_level == IPPROTO_IPV6 + && cmsgptr->cmsg_type == IPV6_HOPLIMIT) { + int *phoplimit = (int *)CMSG_DATA(cmsgptr); + *hoplimit = *phoplimit; + } } - } - /* Hoplimit check shold be done when destination address is - multicast address. */ - if (! IN6_IS_ADDR_MULTICAST (&dst)) - *hoplimit = -1; + /* Hoplimit check shold be done when destination address is + multicast address. */ + if (!IN6_IS_ADDR_MULTICAST(&dst)) + *hoplimit = -1; - return ret; + return ret; } /* Dump rip packet */ -void -ripng_packet_dump (struct ripng_packet *packet, int size, const char *sndrcv) -{ - caddr_t lim; - struct rte *rte; - const char *command_str; - - /* Set command string. */ - if (packet->command == RIPNG_REQUEST) - command_str = "request"; - else if (packet->command == RIPNG_RESPONSE) - command_str = "response"; - else - command_str = "unknown"; - - /* Dump packet header. */ - zlog_debug ("%s %s version %d packet size %d", - sndrcv, command_str, packet->version, size); - - /* Dump each routing table entry. */ - rte = packet->rte; - - for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) - { - if (rte->metric == RIPNG_METRIC_NEXTHOP) - zlog_debug (" nexthop %s/%d", inet6_ntoa (rte->addr), rte->prefixlen); - else - zlog_debug (" %s/%d metric %d tag %"ROUTE_TAG_PRI, - inet6_ntoa (rte->addr), rte->prefixlen, - rte->metric, (route_tag_t)ntohs (rte->tag)); - } +void ripng_packet_dump(struct ripng_packet *packet, int size, + const char *sndrcv) +{ + caddr_t lim; + struct rte *rte; + const char *command_str; + + /* Set command string. */ + if (packet->command == RIPNG_REQUEST) + command_str = "request"; + else if (packet->command == RIPNG_RESPONSE) + command_str = "response"; + else + command_str = "unknown"; + + /* Dump packet header. */ + zlog_debug("%s %s version %d packet size %d", sndrcv, command_str, + packet->version, size); + + /* Dump each routing table entry. */ + rte = packet->rte; + + for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) { + if (rte->metric == RIPNG_METRIC_NEXTHOP) + zlog_debug(" nexthop %s/%d", inet6_ntoa(rte->addr), + rte->prefixlen); + else + zlog_debug(" %s/%d metric %d tag %" ROUTE_TAG_PRI, + inet6_ntoa(rte->addr), rte->prefixlen, + rte->metric, (route_tag_t)ntohs(rte->tag)); + } } /* RIPng next hop address RTE (Route Table Entry). */ -static void -ripng_nexthop_rte (struct rte *rte, - struct sockaddr_in6 *from, - struct ripng_nexthop *nexthop) -{ - char buf[INET6_BUFSIZ]; - - /* Logging before checking RTE. */ - if (IS_RIPNG_DEBUG_RECV) - zlog_debug ("RIPng nexthop RTE address %s tag %"ROUTE_TAG_PRI" prefixlen %d", - inet6_ntoa (rte->addr), (route_tag_t)ntohs (rte->tag), rte->prefixlen); - - /* RFC2080 2.1.1 Next Hop: - The route tag and prefix length in the next hop RTE must be - set to zero on sending and ignored on receiption. */ - if (ntohs (rte->tag) != 0) - zlog_warn ("RIPng nexthop RTE with non zero tag value %"ROUTE_TAG_PRI" from %s", - (route_tag_t)ntohs (rte->tag), inet6_ntoa (from->sin6_addr)); - - if (rte->prefixlen != 0) - zlog_warn ("RIPng nexthop RTE with non zero prefixlen value %d from %s", - rte->prefixlen, inet6_ntoa (from->sin6_addr)); - - /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a - next hop RTE indicates that the next hop address should be the - originator of the RIPng advertisement. An address specified as a - next hop must be a link-local address. */ - if (IN6_IS_ADDR_UNSPECIFIED (&rte->addr)) - { - nexthop->flag = RIPNG_NEXTHOP_UNSPEC; - memset (&nexthop->address, 0, sizeof (struct in6_addr)); - return; - } +static void ripng_nexthop_rte(struct rte *rte, struct sockaddr_in6 *from, + struct ripng_nexthop *nexthop) +{ + char buf[INET6_BUFSIZ]; + + /* Logging before checking RTE. */ + if (IS_RIPNG_DEBUG_RECV) + zlog_debug("RIPng nexthop RTE address %s tag %" ROUTE_TAG_PRI + " prefixlen %d", + inet6_ntoa(rte->addr), (route_tag_t)ntohs(rte->tag), + rte->prefixlen); + + /* RFC2080 2.1.1 Next Hop: + The route tag and prefix length in the next hop RTE must be + set to zero on sending and ignored on receiption. */ + if (ntohs(rte->tag) != 0) + zlog_warn( + "RIPng nexthop RTE with non zero tag value %" ROUTE_TAG_PRI + " from %s", + (route_tag_t)ntohs(rte->tag), + inet6_ntoa(from->sin6_addr)); + + if (rte->prefixlen != 0) + zlog_warn( + "RIPng nexthop RTE with non zero prefixlen value %d from %s", + rte->prefixlen, inet6_ntoa(from->sin6_addr)); + + /* Specifying a value of 0:0:0:0:0:0:0:0 in the prefix field of a + next hop RTE indicates that the next hop address should be the + originator of the RIPng advertisement. An address specified as a + next hop must be a link-local address. */ + if (IN6_IS_ADDR_UNSPECIFIED(&rte->addr)) { + nexthop->flag = RIPNG_NEXTHOP_UNSPEC; + memset(&nexthop->address, 0, sizeof(struct in6_addr)); + return; + } - if (IN6_IS_ADDR_LINKLOCAL (&rte->addr)) - { - nexthop->flag = RIPNG_NEXTHOP_ADDRESS; - IPV6_ADDR_COPY (&nexthop->address, &rte->addr); - return; - } + if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) { + nexthop->flag = RIPNG_NEXTHOP_ADDRESS; + IPV6_ADDR_COPY(&nexthop->address, &rte->addr); + return; + } - /* The purpose of the next hop RTE is to eliminate packets being - routed through extra hops in the system. It is particularly useful - when RIPng is not being run on all of the routers on a network. - Note that next hop RTE is "advisory". That is, if the provided - information is ignored, a possibly sub-optimal, but absolutely - valid, route may be taken. If the received next hop address is not - a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */ - zlog_warn ("RIPng nexthop RTE with non link-local address %s from %s", - inet6_ntoa (rte->addr), - inet_ntop (AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ)); + /* The purpose of the next hop RTE is to eliminate packets being + routed through extra hops in the system. It is particularly useful + when RIPng is not being run on all of the routers on a network. + Note that next hop RTE is "advisory". That is, if the provided + information is ignored, a possibly sub-optimal, but absolutely + valid, route may be taken. If the received next hop address is not + a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */ + zlog_warn("RIPng nexthop RTE with non link-local address %s from %s", + inet6_ntoa(rte->addr), + inet_ntop(AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ)); - nexthop->flag = RIPNG_NEXTHOP_UNSPEC; - memset (&nexthop->address, 0, sizeof (struct in6_addr)); + nexthop->flag = RIPNG_NEXTHOP_UNSPEC; + memset(&nexthop->address, 0, sizeof(struct in6_addr)); - return; + return; } /* If ifp has same link-local address then return 1. */ -static int -ripng_lladdr_check (struct interface *ifp, struct in6_addr *addr) +static int ripng_lladdr_check(struct interface *ifp, struct in6_addr *addr) { - struct listnode *node; - struct connected *connected; - struct prefix *p; + struct listnode *node; + struct connected *connected; + struct prefix *p; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) - { - p = connected->address; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + p = connected->address; - if (p->family == AF_INET6 && - IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6) && - IN6_ARE_ADDR_EQUAL (&p->u.prefix6, addr)) - return 1; - } - return 0; + if (p->family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6) + && IN6_ARE_ADDR_EQUAL(&p->u.prefix6, addr)) + return 1; + } + return 0; } /* RIPng route garbage collect timer. */ -static int -ripng_garbage_collect (struct thread *t) +static int ripng_garbage_collect(struct thread *t) { - struct ripng_info *rinfo; - struct route_node *rp; + struct ripng_info *rinfo; + struct route_node *rp; - rinfo = THREAD_ARG (t); - rinfo->t_garbage_collect = NULL; + rinfo = THREAD_ARG(t); + rinfo->t_garbage_collect = NULL; - /* Off timeout timer. */ - RIPNG_TIMER_OFF (rinfo->t_timeout); - - /* Get route_node pointer. */ - rp = rinfo->rp; + /* Off timeout timer. */ + RIPNG_TIMER_OFF(rinfo->t_timeout); - /* Unlock route_node. */ - listnode_delete (rp->info, rinfo); - if (list_isempty ((struct list *)rp->info)) - { - list_free (rp->info); - rp->info = NULL; - route_unlock_node (rp); - } + /* Get route_node pointer. */ + rp = rinfo->rp; - /* Free RIPng routing information. */ - ripng_info_free (rinfo); + /* Unlock route_node. */ + listnode_delete(rp->info, rinfo); + if (list_isempty((struct list *)rp->info)) { + list_free(rp->info); + rp->info = NULL; + route_unlock_node(rp); + } + + /* Free RIPng routing information. */ + ripng_info_free(rinfo); - return 0; + return 0; } -static void ripng_timeout_update (struct ripng_info *rinfo); +static void ripng_timeout_update(struct ripng_info *rinfo); /* Add new route to the ECMP list. * RETURN: the new entry added in the list, or NULL if it is not the first * entry and ECMP is not allowed. */ -struct ripng_info * -ripng_ecmp_add (struct ripng_info *rinfo_new) +struct ripng_info *ripng_ecmp_add(struct ripng_info *rinfo_new) { - struct route_node *rp = rinfo_new->rp; - struct ripng_info *rinfo = NULL; - struct list *list = NULL; + struct route_node *rp = rinfo_new->rp; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; - if (rp->info == NULL) - rp->info = list_new (); - list = (struct list *)rp->info; + if (rp->info == NULL) + rp->info = list_new(); + list = (struct list *)rp->info; - /* If ECMP is not allowed and some entry already exists in the list, - * do nothing. */ - if (listcount (list) && !ripng->ecmp) - return NULL; + /* If ECMP is not allowed and some entry already exists in the list, + * do nothing. */ + if (listcount(list) && !ripng->ecmp) + return NULL; - rinfo = ripng_info_new (); - memcpy (rinfo, rinfo_new, sizeof (struct ripng_info)); - listnode_add (list, rinfo); + rinfo = ripng_info_new(); + memcpy(rinfo, rinfo_new, sizeof(struct ripng_info)); + listnode_add(list, rinfo); - if (ripng_route_rte (rinfo)) - { - ripng_timeout_update (rinfo); - ripng_zebra_ipv6_add (rp); - } + if (ripng_route_rte(rinfo)) { + ripng_timeout_update(rinfo); + ripng_zebra_ipv6_add(rp); + } - ripng_aggregate_increment (rp, rinfo); + ripng_aggregate_increment(rp, rinfo); - /* Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + /* Set the route change flag on the first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); - /* Signal the output process to trigger an update. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update. */ + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Replace the ECMP list with the new route. * RETURN: the new entry added in the list */ -struct ripng_info * -ripng_ecmp_replace (struct ripng_info *rinfo_new) -{ - struct route_node *rp = rinfo_new->rp; - struct list *list = (struct list *)rp->info; - struct ripng_info *rinfo = NULL, *tmp_rinfo = NULL; - struct listnode *node = NULL, *nextnode = NULL; - - if (list == NULL || listcount (list) == 0) - return ripng_ecmp_add (rinfo_new); - - /* Get the first entry */ - rinfo = listgetdata (listhead (list)); - - /* Learnt route replaced by a local one. Delete it from zebra. */ - if (ripng_route_rte (rinfo) && !ripng_route_rte (rinfo_new)) - if (CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete (rp); - - if (rinfo->metric != RIPNG_METRIC_INFINITY) - ripng_aggregate_decrement_list (rp, list); - - /* Re-use the first entry, and delete the others. */ - for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) - if (tmp_rinfo != rinfo) - { - RIPNG_TIMER_OFF (tmp_rinfo->t_timeout); - RIPNG_TIMER_OFF (tmp_rinfo->t_garbage_collect); - list_delete_node (list, node); - ripng_info_free (tmp_rinfo); - } - - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - memcpy (rinfo, rinfo_new, sizeof (struct ripng_info)); - - if (ripng_route_rte (rinfo)) - { - ripng_timeout_update (rinfo); - /* The ADD message implies an update. */ - ripng_zebra_ipv6_add (rp); - } +struct ripng_info *ripng_ecmp_replace(struct ripng_info *rinfo_new) +{ + struct route_node *rp = rinfo_new->rp; + struct list *list = (struct list *)rp->info; + struct ripng_info *rinfo = NULL, *tmp_rinfo = NULL; + struct listnode *node = NULL, *nextnode = NULL; + + if (list == NULL || listcount(list) == 0) + return ripng_ecmp_add(rinfo_new); + + /* Get the first entry */ + rinfo = listgetdata(listhead(list)); + + /* Learnt route replaced by a local one. Delete it from zebra. */ + if (ripng_route_rte(rinfo) && !ripng_route_rte(rinfo_new)) + if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete(rp); + + if (rinfo->metric != RIPNG_METRIC_INFINITY) + ripng_aggregate_decrement_list(rp, list); + + /* Re-use the first entry, and delete the others. */ + for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) { + RIPNG_TIMER_OFF(tmp_rinfo->t_timeout); + RIPNG_TIMER_OFF(tmp_rinfo->t_garbage_collect); + list_delete_node(list, node); + ripng_info_free(tmp_rinfo); + } + + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_OFF(rinfo->t_garbage_collect); + memcpy(rinfo, rinfo_new, sizeof(struct ripng_info)); - ripng_aggregate_increment (rp, rinfo); + if (ripng_route_rte(rinfo)) { + ripng_timeout_update(rinfo); + /* The ADD message implies an update. */ + ripng_zebra_ipv6_add(rp); + } + + ripng_aggregate_increment(rp, rinfo); - /* Set the route change flag. */ - SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + /* Set the route change flag. */ + SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); - /* Signal the output process to trigger an update. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update. */ + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Delete one route from the ECMP list. @@ -542,1449 +519,1426 @@ ripng_ecmp_replace (struct ripng_info *rinfo_new) * the entry - the entry is the last one in the list; its metric is set * to INFINITY, and the garbage collector is started for it */ -struct ripng_info * -ripng_ecmp_delete (struct ripng_info *rinfo) -{ - struct route_node *rp = rinfo->rp; - struct list *list = (struct list *)rp->info; - - RIPNG_TIMER_OFF (rinfo->t_timeout); - - if (rinfo->metric != RIPNG_METRIC_INFINITY) - ripng_aggregate_decrement (rp, rinfo); - - if (listcount (list) > 1) - { - /* Some other ECMP entries still exist. Just delete this entry. */ - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - listnode_delete (list, rinfo); - if (ripng_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) - /* The ADD message implies the update. */ - ripng_zebra_ipv6_add (rp); - ripng_info_free (rinfo); - rinfo = NULL; - } - else - { - assert (rinfo == listgetdata (listhead (list))); - - /* This is the only entry left in the list. We must keep it in - * the list for garbage collection time, with INFINITY metric. */ - - rinfo->metric = RIPNG_METRIC_INFINITY; - RIPNG_TIMER_ON (rinfo->t_garbage_collect, - ripng_garbage_collect, ripng->garbage_time); - - if (ripng_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete (rp); - } +struct ripng_info *ripng_ecmp_delete(struct ripng_info *rinfo) +{ + struct route_node *rp = rinfo->rp; + struct list *list = (struct list *)rp->info; + + RIPNG_TIMER_OFF(rinfo->t_timeout); + + if (rinfo->metric != RIPNG_METRIC_INFINITY) + ripng_aggregate_decrement(rp, rinfo); + + if (listcount(list) > 1) { + /* Some other ECMP entries still exist. Just delete this entry. + */ + RIPNG_TIMER_OFF(rinfo->t_garbage_collect); + listnode_delete(list, rinfo); + if (ripng_route_rte(rinfo) + && CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + /* The ADD message implies the update. */ + ripng_zebra_ipv6_add(rp); + ripng_info_free(rinfo); + rinfo = NULL; + } else { + assert(rinfo == listgetdata(listhead(list))); + + /* This is the only entry left in the list. We must keep it in + * the list for garbage collection time, with INFINITY metric. + */ + + rinfo->metric = RIPNG_METRIC_INFINITY; + RIPNG_TIMER_ON(rinfo->t_garbage_collect, ripng_garbage_collect, + ripng->garbage_time); + + if (ripng_route_rte(rinfo) + && CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete(rp); + } - /* Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + /* Set the route change flag on the first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); - /* Signal the output process to trigger an update. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update. */ + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Timeout RIPng routes. */ -static int -ripng_timeout (struct thread *t) +static int ripng_timeout(struct thread *t) { - ripng_ecmp_delete ((struct ripng_info *)THREAD_ARG (t)); - return 0; + ripng_ecmp_delete((struct ripng_info *)THREAD_ARG(t)); + return 0; } -static void -ripng_timeout_update (struct ripng_info *rinfo) +static void ripng_timeout_update(struct ripng_info *rinfo) { - if (rinfo->metric != RIPNG_METRIC_INFINITY) - { - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_ON (rinfo->t_timeout, ripng_timeout, ripng->timeout_time); - } + if (rinfo->metric != RIPNG_METRIC_INFINITY) { + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_ON(rinfo->t_timeout, ripng_timeout, + ripng->timeout_time); + } } -static int -ripng_filter (int ripng_distribute, struct prefix_ipv6 *p, - struct ripng_interface *ri) -{ - struct distribute *dist; - struct access_list *alist; - struct prefix_list *plist; - int distribute = ripng_distribute == RIPNG_FILTER_OUT ? - DISTRIBUTE_V6_OUT : DISTRIBUTE_V6_IN; - const char *inout = ripng_distribute == RIPNG_FILTER_OUT ? "out" : "in"; - - /* Input distribute-list filtering. */ - if (ri->list[ripng_distribute]) - { - if (access_list_apply (ri->list[ripng_distribute], - (struct prefix *) p) == FILTER_DENY) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by distribute %s", - inet6_ntoa (p->prefix), p->prefixlen, inout); - return -1; +static int ripng_filter(int ripng_distribute, struct prefix_ipv6 *p, + struct ripng_interface *ri) +{ + struct distribute *dist; + struct access_list *alist; + struct prefix_list *plist; + int distribute = ripng_distribute == RIPNG_FILTER_OUT + ? DISTRIBUTE_V6_OUT + : DISTRIBUTE_V6_IN; + const char *inout = ripng_distribute == RIPNG_FILTER_OUT ? "out" : "in"; + + /* Input distribute-list filtering. */ + if (ri->list[ripng_distribute]) { + if (access_list_apply(ri->list[ripng_distribute], + (struct prefix *)p) + == FILTER_DENY) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug("%s/%d filtered by distribute %s", + inet6_ntoa(p->prefix), p->prefixlen, + inout); + return -1; + } + } + if (ri->prefix[ripng_distribute]) { + if (prefix_list_apply(ri->prefix[ripng_distribute], + (struct prefix *)p) + == PREFIX_DENY) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug("%s/%d filtered by prefix-list %s", + inet6_ntoa(p->prefix), p->prefixlen, + inout); + return -1; } - } - if (ri->prefix[ripng_distribute]) -{ - if (prefix_list_apply (ri->prefix[ripng_distribute], - (struct prefix *) p) == PREFIX_DENY) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by prefix-list %s", - inet6_ntoa (p->prefix), p->prefixlen, inout); - return -1; } - } - /* All interface filter check. */ - dist = distribute_lookup (NULL); - if (dist) - { - if (dist->list[distribute]) - { - alist = access_list_lookup (AFI_IP6, dist->list[distribute]); - - if (alist) - { - if (access_list_apply (alist, - (struct prefix *) p) == FILTER_DENY) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by distribute %s", - inet6_ntoa (p->prefix), p->prefixlen, inout); - return -1; + /* All interface filter check. */ + dist = distribute_lookup(NULL); + if (dist) { + if (dist->list[distribute]) { + alist = access_list_lookup(AFI_IP6, + dist->list[distribute]); + + if (alist) { + if (access_list_apply(alist, (struct prefix *)p) + == FILTER_DENY) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "%s/%d filtered by distribute %s", + inet6_ntoa(p->prefix), + p->prefixlen, inout); + return -1; + } + } } - } - } - if (dist->prefix[distribute]) - { - plist = prefix_list_lookup (AFI_IP6, dist->prefix[distribute]); - - if (plist) - { - if (prefix_list_apply (plist, - (struct prefix *) p) == PREFIX_DENY) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by prefix-list %s", - inet6_ntoa (p->prefix), p->prefixlen, inout); - return -1; + if (dist->prefix[distribute]) { + plist = prefix_list_lookup(AFI_IP6, + dist->prefix[distribute]); + + if (plist) { + if (prefix_list_apply(plist, (struct prefix *)p) + == PREFIX_DENY) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "%s/%d filtered by prefix-list %s", + inet6_ntoa(p->prefix), + p->prefixlen, inout); + return -1; + } + } } - } } - } - return 0; + return 0; } /* Process RIPng route according to RFC2080. */ -static void -ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, - struct ripng_nexthop *ripng_nexthop, - struct interface *ifp) -{ - int ret; - struct prefix_ipv6 p; - struct route_node *rp; - struct ripng_info *rinfo = NULL, newinfo; - struct ripng_interface *ri; - struct in6_addr *nexthop; - int same = 0; - struct list *list = NULL; - struct listnode *node = NULL; - - /* Make prefix structure. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - /* p.prefix = rte->addr; */ - IPV6_ADDR_COPY (&p.prefix, &rte->addr); - p.prefixlen = rte->prefixlen; - - /* Make sure mask is applied. */ - /* XXX We have to check the prefix is valid or not before call - apply_mask_ipv6. */ - apply_mask_ipv6 (&p); - - /* Apply input filters. */ - ri = ifp->info; - - ret = ripng_filter (RIPNG_FILTER_IN, &p, ri); - if (ret < 0) - return; - - memset (&newinfo, 0, sizeof (newinfo)); - newinfo.type = ZEBRA_ROUTE_RIPNG; - newinfo.sub_type = RIPNG_ROUTE_RTE; - if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) - newinfo.nexthop = ripng_nexthop->address; - else - newinfo.nexthop = from->sin6_addr; - newinfo.from = from->sin6_addr; - newinfo.ifindex = ifp->ifindex; - newinfo.metric = rte->metric; - newinfo.metric_out = rte->metric; /* XXX */ - newinfo.tag = ntohs (rte->tag); /* XXX */ - - /* Modify entry. */ - if (ri->routemap[RIPNG_FILTER_IN]) - { - int ret; - - ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN], - (struct prefix *)&p, RMAP_RIPNG, &newinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("RIPng %s/%d is filtered by route-map in", - inet6_ntoa (p.prefix), p.prefixlen); - return; - } - - /* Get back the object */ - if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) { - if (! IPV6_ADDR_SAME(&newinfo.nexthop, &ripng_nexthop->address) ) { - /* the nexthop get changed by the routemap */ - if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) - ripng_nexthop->address = newinfo.nexthop; - else - ripng_nexthop->address = in6addr_any; - } - } else { - if (! IPV6_ADDR_SAME(&newinfo.nexthop, &from->sin6_addr) ) { - /* the nexthop get changed by the routemap */ - if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) { - ripng_nexthop->flag = RIPNG_NEXTHOP_ADDRESS; - ripng_nexthop->address = newinfo.nexthop; - } - } - } - rte->tag = htons(newinfo.tag_out); /* XXX */ - rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */ - } +static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, + struct ripng_nexthop *ripng_nexthop, + struct interface *ifp) +{ + int ret; + struct prefix_ipv6 p; + struct route_node *rp; + struct ripng_info *rinfo = NULL, newinfo; + struct ripng_interface *ri; + struct in6_addr *nexthop; + int same = 0; + struct list *list = NULL; + struct listnode *node = NULL; + + /* Make prefix structure. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + /* p.prefix = rte->addr; */ + IPV6_ADDR_COPY(&p.prefix, &rte->addr); + p.prefixlen = rte->prefixlen; + + /* Make sure mask is applied. */ + /* XXX We have to check the prefix is valid or not before call + apply_mask_ipv6. */ + apply_mask_ipv6(&p); + + /* Apply input filters. */ + ri = ifp->info; + + ret = ripng_filter(RIPNG_FILTER_IN, &p, ri); + if (ret < 0) + return; + + memset(&newinfo, 0, sizeof(newinfo)); + newinfo.type = ZEBRA_ROUTE_RIPNG; + newinfo.sub_type = RIPNG_ROUTE_RTE; + if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) + newinfo.nexthop = ripng_nexthop->address; + else + newinfo.nexthop = from->sin6_addr; + newinfo.from = from->sin6_addr; + newinfo.ifindex = ifp->ifindex; + newinfo.metric = rte->metric; + newinfo.metric_out = rte->metric; /* XXX */ + newinfo.tag = ntohs(rte->tag); /* XXX */ + + /* Modify entry. */ + if (ri->routemap[RIPNG_FILTER_IN]) { + int ret; + + ret = route_map_apply(ri->routemap[RIPNG_FILTER_IN], + (struct prefix *)&p, RMAP_RIPNG, + &newinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "RIPng %s/%d is filtered by route-map in", + inet6_ntoa(p.prefix), p.prefixlen); + return; + } - /* Once the entry has been validated, update the metric by - * adding the cost of the network on wich the message - * arrived. If the result is greater than infinity, use infinity - * (RFC2453 Sec. 3.9.2) - **/ - - /* Zebra ripngd can handle offset-list in. */ - ret = ripng_offset_list_apply_in (&p, ifp, &rte->metric); - - /* If offset-list does not modify the metric use interface's - * one. */ - if (! ret) - rte->metric += ifp->metric ? ifp->metric : 1; - - if (rte->metric > RIPNG_METRIC_INFINITY) - rte->metric = RIPNG_METRIC_INFINITY; - - /* Set nexthop pointer. */ - if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) - nexthop = &ripng_nexthop->address; - else - nexthop = &from->sin6_addr; - - /* Lookup RIPng routing table. */ - rp = route_node_get (ripng->table, (struct prefix *) &p); - - newinfo.rp = rp; - newinfo.nexthop = *nexthop; - newinfo.metric = rte->metric; - newinfo.tag = ntohs (rte->tag); - - /* Check to see whether there is already RIPng route on the table. */ - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) - { - /* Need to compare with redistributed entry or local entry */ - if (!ripng_route_rte (rinfo)) - break; - - if (IPV6_ADDR_SAME (&rinfo->from, &from->sin6_addr) && - IPV6_ADDR_SAME (&rinfo->nexthop, nexthop)) - break; - - if (!listnextnode (node)) - { - /* Not found in the list */ - - if (rte->metric > rinfo->metric) - { - /* New route has a greater metric. Discard it. */ - route_unlock_node (rp); - return; - } - - if (rte->metric < rinfo->metric) - /* New route has a smaller metric. Replace the ECMP list - * with the new one in below. */ - break; - - /* Metrics are same. Unless ECMP is disabled, keep "rinfo" null and - * the new route is added in the ECMP list in below. */ - if (! ripng->ecmp) - break; - } - } - - if (rinfo) - { - /* Redistributed route check. */ - if (rinfo->type != ZEBRA_ROUTE_RIPNG - && rinfo->metric != RIPNG_METRIC_INFINITY) - { - route_unlock_node (rp); - return; - } - - /* Local static route. */ - if (rinfo->type == ZEBRA_ROUTE_RIPNG - && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) || - (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) - && rinfo->metric != RIPNG_METRIC_INFINITY) - { - route_unlock_node (rp); - return; - } - } + /* Get back the object */ + if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) { + if (!IPV6_ADDR_SAME(&newinfo.nexthop, + &ripng_nexthop->address)) { + /* the nexthop get changed by the routemap */ + if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) + ripng_nexthop->address = + newinfo.nexthop; + else + ripng_nexthop->address = in6addr_any; + } + } else { + if (!IPV6_ADDR_SAME(&newinfo.nexthop, + &from->sin6_addr)) { + /* the nexthop get changed by the routemap */ + if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop)) { + ripng_nexthop->flag = + RIPNG_NEXTHOP_ADDRESS; + ripng_nexthop->address = + newinfo.nexthop; + } + } + } + rte->tag = htons(newinfo.tag_out); /* XXX */ + rte->metric = + newinfo.metric_out; /* XXX: the routemap uses the + metric_out field */ + } - if (!rinfo) - { - /* Now, check to see whether there is already an explicit route - for the destination prefix. If there is no such route, add - this route to the routing table, unless the metric is - infinity (there is no point in adding a route which - unusable). */ - if (rte->metric != RIPNG_METRIC_INFINITY) - ripng_ecmp_add (&newinfo); - } - else - { - /* If there is an existing route, compare the next hop address - to the address of the router from which the datagram came. - If this datagram is from the same router as the existing - route, reinitialize the timeout. */ - same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) - && (rinfo->ifindex == ifp->ifindex)); - - /* - * RFC 2080 - Section 2.4.2: - * "If the new metric is the same as the old one, examine the timeout - * for the existing route. If it is at least halfway to the expiration - * point, switch to the new route. This heuristic is optional, but - * highly recommended". - */ - if (!ripng->ecmp && !same && - rinfo->metric == rte->metric && rinfo->t_timeout && - (thread_timer_remain_second (rinfo->t_timeout) < (ripng->timeout_time / 2))) - { - ripng_ecmp_replace (&newinfo); - } - /* Next, compare the metrics. If the datagram is from the same - router as the existing route, and the new metric is different - than the old one; or, if the new metric is lower than the old - one; do the following actions: */ - else if ((same && rinfo->metric != rte->metric) || - rte->metric < rinfo->metric) - { - if (listcount (list) == 1) - { - if (newinfo.metric != RIPNG_METRIC_INFINITY) - ripng_ecmp_replace (&newinfo); - else - ripng_ecmp_delete (rinfo); - } - else - { - if (newinfo.metric < rinfo->metric) - ripng_ecmp_replace (&newinfo); - else /* newinfo.metric > rinfo->metric */ - ripng_ecmp_delete (rinfo); - } - } - else /* same & no change */ - ripng_timeout_update (rinfo); - - /* Unlock tempolary lock of the route. */ - route_unlock_node (rp); - } -} + /* Once the entry has been validated, update the metric by + * adding the cost of the network on wich the message + * arrived. If the result is greater than infinity, use infinity + * (RFC2453 Sec. 3.9.2) + **/ + + /* Zebra ripngd can handle offset-list in. */ + ret = ripng_offset_list_apply_in(&p, ifp, &rte->metric); + + /* If offset-list does not modify the metric use interface's + * one. */ + if (!ret) + rte->metric += ifp->metric ? ifp->metric : 1; + + if (rte->metric > RIPNG_METRIC_INFINITY) + rte->metric = RIPNG_METRIC_INFINITY; + + /* Set nexthop pointer. */ + if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) + nexthop = &ripng_nexthop->address; + else + nexthop = &from->sin6_addr; + + /* Lookup RIPng routing table. */ + rp = route_node_get(ripng->table, (struct prefix *)&p); + + newinfo.rp = rp; + newinfo.nexthop = *nexthop; + newinfo.metric = rte->metric; + newinfo.tag = ntohs(rte->tag); + + /* Check to see whether there is already RIPng route on the table. */ + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) { + /* Need to compare with redistributed entry or local + * entry */ + if (!ripng_route_rte(rinfo)) + break; + + if (IPV6_ADDR_SAME(&rinfo->from, &from->sin6_addr) + && IPV6_ADDR_SAME(&rinfo->nexthop, nexthop)) + break; + + if (!listnextnode(node)) { + /* Not found in the list */ + + if (rte->metric > rinfo->metric) { + /* New route has a greater metric. + * Discard it. */ + route_unlock_node(rp); + return; + } + + if (rte->metric < rinfo->metric) + /* New route has a smaller metric. + * Replace the ECMP list + * with the new one in below. */ + break; + + /* Metrics are same. Unless ECMP is disabled, + * keep "rinfo" null and + * the new route is added in the ECMP list in + * below. */ + if (!ripng->ecmp) + break; + } + } -/* Add redistributed route to RIPng table. */ -void -ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, - ifindex_t ifindex, struct in6_addr *nexthop, - route_tag_t tag) -{ - struct route_node *rp; - struct ripng_info *rinfo = NULL, newinfo; - struct list *list = NULL; - - /* Redistribute route */ - if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) - return; - if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) - return; - - rp = route_node_get (ripng->table, (struct prefix *) p); - - memset (&newinfo, 0, sizeof (struct ripng_info)); - newinfo.type = type; - newinfo.sub_type = sub_type; - newinfo.ifindex = ifindex; - newinfo.metric = 1; - if (tag <= UINT16_MAX) /* RIPng only supports 16 bit tags */ - newinfo.tag = tag; - newinfo.rp = rp; - if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop)) - newinfo.nexthop = *nexthop; - - if ((list = rp->info) != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - - if (rinfo->type == ZEBRA_ROUTE_CONNECT - && rinfo->sub_type == RIPNG_ROUTE_INTERFACE - && rinfo->metric != RIPNG_METRIC_INFINITY) { - route_unlock_node (rp); - return; - } - - /* Manually configured RIPng route check. - * They have the precedence on all the other entries. - **/ - if (rinfo->type == ZEBRA_ROUTE_RIPNG - && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) || - (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) ) { - if (type != ZEBRA_ROUTE_RIPNG || ((sub_type != RIPNG_ROUTE_STATIC) && - (sub_type != RIPNG_ROUTE_DEFAULT))) { - route_unlock_node (rp); - return; - } - } - - ripng_ecmp_replace (&newinfo); - route_unlock_node (rp); - } - else - ripng_ecmp_add (&newinfo); + if (rinfo) { + /* Redistributed route check. */ + if (rinfo->type != ZEBRA_ROUTE_RIPNG + && rinfo->metric != RIPNG_METRIC_INFINITY) { + route_unlock_node(rp); + return; + } - if (IS_RIPNG_DEBUG_EVENT) { - if (!nexthop) - zlog_debug ("Redistribute new prefix %s/%d on the interface %s", - inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, VRF_DEFAULT)); - else - zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s", - inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop), - ifindex2ifname(ifindex, VRF_DEFAULT)); - } + /* Local static route. */ + if (rinfo->type == ZEBRA_ROUTE_RIPNG + && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) + || (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) + && rinfo->metric != RIPNG_METRIC_INFINITY) { + route_unlock_node(rp); + return; + } + } - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + if (!rinfo) { + /* Now, check to see whether there is already an explicit route + for the destination prefix. If there is no such route, add + this route to the routing table, unless the metric is + infinity (there is no point in adding a route which + unusable). */ + if (rte->metric != RIPNG_METRIC_INFINITY) + ripng_ecmp_add(&newinfo); + } else { + /* If there is an existing route, compare the next hop address + to the address of the router from which the datagram came. + If this datagram is from the same router as the existing + route, reinitialize the timeout. */ + same = (IN6_ARE_ADDR_EQUAL(&rinfo->from, &from->sin6_addr) + && (rinfo->ifindex == ifp->ifindex)); + + /* + * RFC 2080 - Section 2.4.2: + * "If the new metric is the same as the old one, examine the + * timeout + * for the existing route. If it is at least halfway to the + * expiration + * point, switch to the new route. This heuristic is optional, + * but + * highly recommended". + */ + if (!ripng->ecmp && !same && rinfo->metric == rte->metric + && rinfo->t_timeout + && (thread_timer_remain_second(rinfo->t_timeout) + < (ripng->timeout_time / 2))) { + ripng_ecmp_replace(&newinfo); + } + /* Next, compare the metrics. If the datagram is from the same + router as the existing route, and the new metric is different + than the old one; or, if the new metric is lower than the old + one; do the following actions: */ + else if ((same && rinfo->metric != rte->metric) + || rte->metric < rinfo->metric) { + if (listcount(list) == 1) { + if (newinfo.metric != RIPNG_METRIC_INFINITY) + ripng_ecmp_replace(&newinfo); + else + ripng_ecmp_delete(rinfo); + } else { + if (newinfo.metric < rinfo->metric) + ripng_ecmp_replace(&newinfo); + else /* newinfo.metric > rinfo->metric */ + ripng_ecmp_delete(rinfo); + } + } else /* same & no change */ + ripng_timeout_update(rinfo); + + /* Unlock tempolary lock of the route. */ + route_unlock_node(rp); + } } -/* Delete redistributed route to RIPng table. */ -void -ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, - ifindex_t ifindex) -{ - struct route_node *rp; - struct ripng_info *rinfo; +/* Add redistributed route to RIPng table. */ +void ripng_redistribute_add(int type, int sub_type, struct prefix_ipv6 *p, + ifindex_t ifindex, struct in6_addr *nexthop, + route_tag_t tag) +{ + struct route_node *rp; + struct ripng_info *rinfo = NULL, newinfo; + struct list *list = NULL; + + /* Redistribute route */ + if (IN6_IS_ADDR_LINKLOCAL(&p->prefix)) + return; + if (IN6_IS_ADDR_LOOPBACK(&p->prefix)) + return; + + rp = route_node_get(ripng->table, (struct prefix *)p); + + memset(&newinfo, 0, sizeof(struct ripng_info)); + newinfo.type = type; + newinfo.sub_type = sub_type; + newinfo.ifindex = ifindex; + newinfo.metric = 1; + if (tag <= UINT16_MAX) /* RIPng only supports 16 bit tags */ + newinfo.tag = tag; + newinfo.rp = rp; + if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop)) + newinfo.nexthop = *nexthop; + + if ((list = rp->info) != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + + if (rinfo->type == ZEBRA_ROUTE_CONNECT + && rinfo->sub_type == RIPNG_ROUTE_INTERFACE + && rinfo->metric != RIPNG_METRIC_INFINITY) { + route_unlock_node(rp); + return; + } - if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) - return; - if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) - return; + /* Manually configured RIPng route check. + * They have the precedence on all the other entries. + **/ + if (rinfo->type == ZEBRA_ROUTE_RIPNG + && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) + || (rinfo->sub_type == RIPNG_ROUTE_DEFAULT))) { + if (type != ZEBRA_ROUTE_RIPNG + || ((sub_type != RIPNG_ROUTE_STATIC) + && (sub_type != RIPNG_ROUTE_DEFAULT))) { + route_unlock_node(rp); + return; + } + } - rp = route_node_lookup (ripng->table, (struct prefix *) p); + ripng_ecmp_replace(&newinfo); + route_unlock_node(rp); + } else + ripng_ecmp_add(&newinfo); + + if (IS_RIPNG_DEBUG_EVENT) { + if (!nexthop) + zlog_debug( + "Redistribute new prefix %s/%d on the interface %s", + inet6_ntoa(p->prefix), p->prefixlen, + ifindex2ifname(ifindex, VRF_DEFAULT)); + else + zlog_debug( + "Redistribute new prefix %s/%d with nexthop %s on the interface %s", + inet6_ntoa(p->prefix), p->prefixlen, + inet6_ntoa(*nexthop), + ifindex2ifname(ifindex, VRF_DEFAULT)); + } - if (rp) - { - struct list *list = rp->info; - - if (list != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - if (rinfo != NULL - && rinfo->type == type - && rinfo->sub_type == sub_type - && rinfo->ifindex == ifindex) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIPNG_METRIC_INFINITY; - RIPNG_TIMER_ON (rinfo->t_garbage_collect, - ripng_garbage_collect, ripng->garbage_time); - RIPNG_TIMER_OFF (rinfo->t_timeout); - - /* Aggregate count decrement. */ - ripng_aggregate_decrement (rp, rinfo); - - rinfo->flags |= RIPNG_RTF_CHANGED; - - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("Poisone %s/%d on the interface %s with an " - "infinity metric [delete]", - inet6_ntoa (p->prefix), p->prefixlen, - ifindex2ifname (ifindex, VRF_DEFAULT)); - - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - } - } - route_unlock_node (rp); - } + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); +} + +/* Delete redistributed route to RIPng table. */ +void ripng_redistribute_delete(int type, int sub_type, struct prefix_ipv6 *p, + ifindex_t ifindex) +{ + struct route_node *rp; + struct ripng_info *rinfo; + + if (IN6_IS_ADDR_LINKLOCAL(&p->prefix)) + return; + if (IN6_IS_ADDR_LOOPBACK(&p->prefix)) + return; + + rp = route_node_lookup(ripng->table, (struct prefix *)p); + + if (rp) { + struct list *list = rp->info; + + if (list != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + if (rinfo != NULL && rinfo->type == type + && rinfo->sub_type == sub_type + && rinfo->ifindex == ifindex) { + /* Perform poisoned reverse. */ + rinfo->metric = RIPNG_METRIC_INFINITY; + RIPNG_TIMER_ON(rinfo->t_garbage_collect, + ripng_garbage_collect, + ripng->garbage_time); + RIPNG_TIMER_OFF(rinfo->t_timeout); + + /* Aggregate count decrement. */ + ripng_aggregate_decrement(rp, rinfo); + + rinfo->flags |= RIPNG_RTF_CHANGED; + + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug( + "Poisone %s/%d on the interface %s with an " + "infinity metric [delete]", + inet6_ntoa(p->prefix), + p->prefixlen, + ifindex2ifname(ifindex, + VRF_DEFAULT)); + + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + } + } + route_unlock_node(rp); + } } /* Withdraw redistributed route. */ -void -ripng_redistribute_withdraw (int type) -{ - struct route_node *rp; - struct ripng_info *rinfo = NULL; - struct list *list = NULL; +void ripng_redistribute_withdraw(int type) +{ + struct route_node *rp; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; + + if (!ripng) + return; + + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) { + rinfo = listgetdata(listhead(list)); + if ((rinfo->type == type) + && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE)) { + /* Perform poisoned reverse. */ + rinfo->metric = RIPNG_METRIC_INFINITY; + RIPNG_TIMER_ON(rinfo->t_garbage_collect, + ripng_garbage_collect, + ripng->garbage_time); + RIPNG_TIMER_OFF(rinfo->t_timeout); + + /* Aggregate count decrement. */ + ripng_aggregate_decrement(rp, rinfo); + + rinfo->flags |= RIPNG_RTF_CHANGED; + + if (IS_RIPNG_DEBUG_EVENT) { + struct prefix_ipv6 *p = + (struct prefix_ipv6 *)&rp->p; + + zlog_debug( + "Poisone %s/%d on the interface %s [withdraw]", + inet6_ntoa(p->prefix), + p->prefixlen, + ifindex2ifname(rinfo->ifindex, + VRF_DEFAULT)); + } + + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + } + } +} - if (!ripng) - return; - - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - { - rinfo = listgetdata (listhead (list)); - if ((rinfo->type == type) - && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE)) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIPNG_METRIC_INFINITY; - RIPNG_TIMER_ON (rinfo->t_garbage_collect, - ripng_garbage_collect, ripng->garbage_time); - RIPNG_TIMER_OFF (rinfo->t_timeout); +/* RIP routing information. */ +static void ripng_response_process(struct ripng_packet *packet, int size, + struct sockaddr_in6 *from, + struct interface *ifp, int hoplimit) +{ + caddr_t lim; + struct rte *rte; + struct ripng_nexthop nexthop; + + /* RFC2080 2.4.2 Response Messages: + The Response must be ignored if it is not from the RIPng port. */ + if (ntohs(from->sin6_port) != RIPNG_PORT_DEFAULT) { + zlog_warn("RIPng packet comes from non RIPng port %d from %s", + ntohs(from->sin6_port), inet6_ntoa(from->sin6_addr)); + ripng_peer_bad_packet(from); + return; + } - /* Aggregate count decrement. */ - ripng_aggregate_decrement (rp, rinfo); + /* The datagram's IPv6 source address should be checked to see + whether the datagram is from a valid neighbor; the source of the + datagram must be a link-local address. */ + if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) { + zlog_warn("RIPng packet comes from non link local address %s", + inet6_ntoa(from->sin6_addr)); + ripng_peer_bad_packet(from); + return; + } - rinfo->flags |= RIPNG_RTF_CHANGED; + /* It is also worth checking to see whether the response is from one + of the router's own addresses. Interfaces on broadcast networks + may receive copies of their own multicasts immediately. If a + router processes its own output as new input, confusion is likely, + and such datagrams must be ignored. */ + if (ripng_lladdr_check(ifp, &from->sin6_addr)) { + zlog_warn( + "RIPng packet comes from my own link local address %s", + inet6_ntoa(from->sin6_addr)); + ripng_peer_bad_packet(from); + return; + } - if (IS_RIPNG_DEBUG_EVENT) { - struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p; + /* As an additional check, periodic advertisements must have their + hop counts set to 255, and inbound, multicast packets sent from the + RIPng port (i.e. periodic advertisement or triggered update + packets) must be examined to ensure that the hop count is 255. */ + if (hoplimit >= 0 && hoplimit != 255) { + zlog_warn( + "RIPng packet comes with non 255 hop count %d from %s", + hoplimit, inet6_ntoa(from->sin6_addr)); + ripng_peer_bad_packet(from); + return; + } - zlog_debug ("Poisone %s/%d on the interface %s [withdraw]", - inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); - } + /* Update RIPng peer. */ + ripng_peer_update(from, packet->version); - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - } - } -} + /* Reset nexthop. */ + memset(&nexthop, 0, sizeof(struct ripng_nexthop)); + nexthop.flag = RIPNG_NEXTHOP_UNSPEC; -/* RIP routing information. */ -static void -ripng_response_process (struct ripng_packet *packet, int size, - struct sockaddr_in6 *from, struct interface *ifp, - int hoplimit) -{ - caddr_t lim; - struct rte *rte; - struct ripng_nexthop nexthop; - - /* RFC2080 2.4.2 Response Messages: - The Response must be ignored if it is not from the RIPng port. */ - if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT) - { - zlog_warn ("RIPng packet comes from non RIPng port %d from %s", - ntohs (from->sin6_port), inet6_ntoa (from->sin6_addr)); - ripng_peer_bad_packet (from); - return; - } + /* Set RTE pointer. */ + rte = packet->rte; - /* The datagram's IPv6 source address should be checked to see - whether the datagram is from a valid neighbor; the source of the - datagram must be a link-local address. */ - if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) - { - zlog_warn ("RIPng packet comes from non link local address %s", - inet6_ntoa (from->sin6_addr)); - ripng_peer_bad_packet (from); - return; - } + for (lim = ((caddr_t)packet) + size; (caddr_t)rte < lim; rte++) { + /* First of all, we have to check this RTE is next hop RTE or + not. Next hop RTE is completely different with normal RTE so + we need special treatment. */ + if (rte->metric == RIPNG_METRIC_NEXTHOP) { + ripng_nexthop_rte(rte, from, &nexthop); + continue; + } - /* It is also worth checking to see whether the response is from one - of the router's own addresses. Interfaces on broadcast networks - may receive copies of their own multicasts immediately. If a - router processes its own output as new input, confusion is likely, - and such datagrams must be ignored. */ - if (ripng_lladdr_check (ifp, &from->sin6_addr)) - { - zlog_warn ("RIPng packet comes from my own link local address %s", - inet6_ntoa (from->sin6_addr)); - ripng_peer_bad_packet (from); - return; - } + /* RTE information validation. */ + + /* - is the destination prefix valid (e.g., not a multicast + prefix and not a link-local address) A link-local address + should never be present in an RTE. */ + if (IN6_IS_ADDR_MULTICAST(&rte->addr)) { + zlog_warn( + "Destination prefix is a multicast address %s/%d [%d]", + inet6_ntoa(rte->addr), rte->prefixlen, + rte->metric); + ripng_peer_bad_route(from); + continue; + } + if (IN6_IS_ADDR_LINKLOCAL(&rte->addr)) { + zlog_warn( + "Destination prefix is a link-local address %s/%d [%d]", + inet6_ntoa(rte->addr), rte->prefixlen, + rte->metric); + ripng_peer_bad_route(from); + continue; + } + if (IN6_IS_ADDR_LOOPBACK(&rte->addr)) { + zlog_warn( + "Destination prefix is a loopback address %s/%d [%d]", + inet6_ntoa(rte->addr), rte->prefixlen, + rte->metric); + ripng_peer_bad_route(from); + continue; + } - /* As an additional check, periodic advertisements must have their - hop counts set to 255, and inbound, multicast packets sent from the - RIPng port (i.e. periodic advertisement or triggered update - packets) must be examined to ensure that the hop count is 255. */ - if (hoplimit >= 0 && hoplimit != 255) - { - zlog_warn ("RIPng packet comes with non 255 hop count %d from %s", - hoplimit, inet6_ntoa (from->sin6_addr)); - ripng_peer_bad_packet (from); - return; - } + /* - is the prefix length valid (i.e., between 0 and 128, + inclusive) */ + if (rte->prefixlen > 128) { + zlog_warn("Invalid prefix length %s/%d from %s%%%s", + inet6_ntoa(rte->addr), rte->prefixlen, + inet6_ntoa(from->sin6_addr), ifp->name); + ripng_peer_bad_route(from); + continue; + } - /* Update RIPng peer. */ - ripng_peer_update (from, packet->version); - - /* Reset nexthop. */ - memset (&nexthop, 0, sizeof (struct ripng_nexthop)); - nexthop.flag = RIPNG_NEXTHOP_UNSPEC; + /* - is the metric valid (i.e., between 1 and 16, inclusive) */ + if (!(rte->metric >= 1 && rte->metric <= 16)) { + zlog_warn("Invalid metric %d from %s%%%s", rte->metric, + inet6_ntoa(from->sin6_addr), ifp->name); + ripng_peer_bad_route(from); + continue; + } - /* Set RTE pointer. */ - rte = packet->rte; + /* Vincent: XXX Should we compute the direclty reachable nexthop + * for our RIPng network ? + **/ - for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++) - { - /* First of all, we have to check this RTE is next hop RTE or - not. Next hop RTE is completely different with normal RTE so - we need special treatment. */ - if (rte->metric == RIPNG_METRIC_NEXTHOP) - { - ripng_nexthop_rte (rte, from, &nexthop); - continue; - } - - /* RTE information validation. */ - - /* - is the destination prefix valid (e.g., not a multicast - prefix and not a link-local address) A link-local address - should never be present in an RTE. */ - if (IN6_IS_ADDR_MULTICAST (&rte->addr)) - { - zlog_warn ("Destination prefix is a multicast address %s/%d [%d]", - inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route (from); - continue; - } - if (IN6_IS_ADDR_LINKLOCAL (&rte->addr)) - { - zlog_warn ("Destination prefix is a link-local address %s/%d [%d]", - inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route (from); - continue; - } - if (IN6_IS_ADDR_LOOPBACK (&rte->addr)) - { - zlog_warn ("Destination prefix is a loopback address %s/%d [%d]", - inet6_ntoa (rte->addr), rte->prefixlen, rte->metric); - ripng_peer_bad_route (from); - continue; - } - - /* - is the prefix length valid (i.e., between 0 and 128, - inclusive) */ - if (rte->prefixlen > 128) - { - zlog_warn ("Invalid prefix length %s/%d from %s%%%s", - inet6_ntoa (rte->addr), rte->prefixlen, - inet6_ntoa (from->sin6_addr), ifp->name); - ripng_peer_bad_route (from); - continue; - } - - /* - is the metric valid (i.e., between 1 and 16, inclusive) */ - if (! (rte->metric >= 1 && rte->metric <= 16)) - { - zlog_warn ("Invalid metric %d from %s%%%s", rte->metric, - inet6_ntoa (from->sin6_addr), ifp->name); - ripng_peer_bad_route (from); - continue; - } - - /* Vincent: XXX Should we compute the direclty reachable nexthop - * for our RIPng network ? - **/ - - /* Routing table updates. */ - ripng_route_process (rte, from, &nexthop, ifp); - } + /* Routing table updates. */ + ripng_route_process(rte, from, &nexthop, ifp); + } } /* Response to request message. */ -static void -ripng_request_process (struct ripng_packet *packet,int size, - struct sockaddr_in6 *from, struct interface *ifp) -{ - caddr_t lim; - struct rte *rte; - struct prefix_ipv6 p; - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_interface *ri; - - /* Does not reponse to the requests on the loopback interfaces */ - if (if_is_loopback (ifp)) - return; - - /* Check RIPng process is enabled on this interface. */ - ri = ifp->info; - if (! ri->running) - return; - - /* When passive interface is specified, suppress responses */ - if (ri->passive) - return; - - /* RIPng peer update. */ - ripng_peer_update (from, packet->version); - - lim = ((caddr_t) packet) + size; - rte = packet->rte; - - /* The Request is processed entry by entry. If there are no - entries, no response is given. */ - if (lim == (caddr_t) rte) - return; - - /* There is one special case. If there is exactly one entry in the - request, and it has a destination prefix of zero, a prefix length - of zero, and a metric of infinity (i.e., 16), then this is a - request to send the entire routing table. In that case, a call - is made to the output process to send the routing table to the - requesting address/port. */ - if (lim == ((caddr_t) (rte + 1)) && - IN6_IS_ADDR_UNSPECIFIED (&rte->addr) && - rte->prefixlen == 0 && - rte->metric == RIPNG_METRIC_INFINITY) - { - /* All route with split horizon */ - ripng_output_process (ifp, from, ripng_all_route); - } - else - { - /* Except for this special case, processing is quite simple. - Examine the list of RTEs in the Request one by one. For each - entry, look up the destination in the router's routing - database and, if there is a route, put that route's metric in - the metric field of the RTE. If there is no explicit route - to the specified destination, put infinity in the metric - field. Once all the entries have been filled in, change the - command from Request to Response and send the datagram back - to the requestor. */ - memset (&p, 0, sizeof (struct prefix_ipv6)); - p.family = AF_INET6; - - for (; ((caddr_t) rte) < lim; rte++) - { - p.prefix = rte->addr; - p.prefixlen = rte->prefixlen; - apply_mask_ipv6 (&p); - - rp = route_node_lookup (ripng->table, (struct prefix *) &p); - - if (rp) - { - rinfo = listgetdata (listhead ((struct list *)rp->info)); - rte->metric = rinfo->metric; - route_unlock_node (rp); - } - else - rte->metric = RIPNG_METRIC_INFINITY; - } - packet->command = RIPNG_RESPONSE; - - ripng_send_packet ((caddr_t) packet, size, from, ifp); - } +static void ripng_request_process(struct ripng_packet *packet, int size, + struct sockaddr_in6 *from, + struct interface *ifp) +{ + caddr_t lim; + struct rte *rte; + struct prefix_ipv6 p; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_interface *ri; + + /* Does not reponse to the requests on the loopback interfaces */ + if (if_is_loopback(ifp)) + return; + + /* Check RIPng process is enabled on this interface. */ + ri = ifp->info; + if (!ri->running) + return; + + /* When passive interface is specified, suppress responses */ + if (ri->passive) + return; + + /* RIPng peer update. */ + ripng_peer_update(from, packet->version); + + lim = ((caddr_t)packet) + size; + rte = packet->rte; + + /* The Request is processed entry by entry. If there are no + entries, no response is given. */ + if (lim == (caddr_t)rte) + return; + + /* There is one special case. If there is exactly one entry in the + request, and it has a destination prefix of zero, a prefix length + of zero, and a metric of infinity (i.e., 16), then this is a + request to send the entire routing table. In that case, a call + is made to the output process to send the routing table to the + requesting address/port. */ + if (lim == ((caddr_t)(rte + 1)) && IN6_IS_ADDR_UNSPECIFIED(&rte->addr) + && rte->prefixlen == 0 && rte->metric == RIPNG_METRIC_INFINITY) { + /* All route with split horizon */ + ripng_output_process(ifp, from, ripng_all_route); + } else { + /* Except for this special case, processing is quite simple. + Examine the list of RTEs in the Request one by one. For each + entry, look up the destination in the router's routing + database and, if there is a route, put that route's metric in + the metric field of the RTE. If there is no explicit route + to the specified destination, put infinity in the metric + field. Once all the entries have been filled in, change the + command from Request to Response and send the datagram back + to the requestor. */ + memset(&p, 0, sizeof(struct prefix_ipv6)); + p.family = AF_INET6; + + for (; ((caddr_t)rte) < lim; rte++) { + p.prefix = rte->addr; + p.prefixlen = rte->prefixlen; + apply_mask_ipv6(&p); + + rp = route_node_lookup(ripng->table, + (struct prefix *)&p); + + if (rp) { + rinfo = listgetdata( + listhead((struct list *)rp->info)); + rte->metric = rinfo->metric; + route_unlock_node(rp); + } else + rte->metric = RIPNG_METRIC_INFINITY; + } + packet->command = RIPNG_RESPONSE; + + ripng_send_packet((caddr_t)packet, size, from, ifp); + } } /* First entry point of reading RIPng packet. */ -static int -ripng_read (struct thread *thread) -{ - int len; - int sock; - struct sockaddr_in6 from; - struct ripng_packet *packet; - ifindex_t ifindex = 0; - struct interface *ifp; - int hoplimit = -1; - - /* Check ripng is active and alive. */ - assert (ripng != NULL); - assert (ripng->sock >= 0); - - /* Fetch thread data and set read pointer to empty for event - managing. `sock' sould be same as ripng->sock. */ - sock = THREAD_FD (thread); - ripng->t_read = NULL; - - /* Add myself to the next event. */ - ripng_event (RIPNG_READ, sock); - - /* Read RIPng packet. */ - len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf), - STREAM_SIZE (ripng->ibuf), &from, &ifindex, - &hoplimit); - if (len < 0) - { - zlog_warn ("RIPng recvfrom failed: %s.", safe_strerror (errno)); - return len; - } +static int ripng_read(struct thread *thread) +{ + int len; + int sock; + struct sockaddr_in6 from; + struct ripng_packet *packet; + ifindex_t ifindex = 0; + struct interface *ifp; + int hoplimit = -1; + + /* Check ripng is active and alive. */ + assert(ripng != NULL); + assert(ripng->sock >= 0); + + /* Fetch thread data and set read pointer to empty for event + managing. `sock' sould be same as ripng->sock. */ + sock = THREAD_FD(thread); + ripng->t_read = NULL; + + /* Add myself to the next event. */ + ripng_event(RIPNG_READ, sock); + + /* Read RIPng packet. */ + len = ripng_recv_packet(sock, STREAM_DATA(ripng->ibuf), + STREAM_SIZE(ripng->ibuf), &from, &ifindex, + &hoplimit); + if (len < 0) { + zlog_warn("RIPng recvfrom failed: %s.", safe_strerror(errno)); + return len; + } - /* Check RTE boundary. RTE size (Packet length - RIPng header size - (4)) must be multiple size of one RTE size (20). */ - if (((len - 4) % 20) != 0) - { - zlog_warn ("RIPng invalid packet size %d from %s", len, - inet6_ntoa (from.sin6_addr)); - ripng_peer_bad_packet (&from); - return 0; - } + /* Check RTE boundary. RTE size (Packet length - RIPng header size + (4)) must be multiple size of one RTE size (20). */ + if (((len - 4) % 20) != 0) { + zlog_warn("RIPng invalid packet size %d from %s", len, + inet6_ntoa(from.sin6_addr)); + ripng_peer_bad_packet(&from); + return 0; + } - packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf); - ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); + packet = (struct ripng_packet *)STREAM_DATA(ripng->ibuf); + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - /* RIPng packet received. */ - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng packet received from %s port %d on %s", - inet6_ntoa (from.sin6_addr), ntohs (from.sin6_port), - ifp ? ifp->name : "unknown"); + /* RIPng packet received. */ + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("RIPng packet received from %s port %d on %s", + inet6_ntoa(from.sin6_addr), ntohs(from.sin6_port), + ifp ? ifp->name : "unknown"); - /* Logging before packet checking. */ - if (IS_RIPNG_DEBUG_RECV) - ripng_packet_dump (packet, len, "RECV"); + /* Logging before packet checking. */ + if (IS_RIPNG_DEBUG_RECV) + ripng_packet_dump(packet, len, "RECV"); - /* Packet comes from unknown interface. */ - if (ifp == NULL) - { - zlog_warn ("RIPng packet comes from unknown interface %d", ifindex); - return 0; - } + /* Packet comes from unknown interface. */ + if (ifp == NULL) { + zlog_warn("RIPng packet comes from unknown interface %d", + ifindex); + return 0; + } - /* Packet version mismatch checking. */ - if (packet->version != ripng->version) - { - zlog_warn ("RIPng packet version %d doesn't fit to my version %d", - packet->version, ripng->version); - ripng_peer_bad_packet (&from); - return 0; - } + /* Packet version mismatch checking. */ + if (packet->version != ripng->version) { + zlog_warn( + "RIPng packet version %d doesn't fit to my version %d", + packet->version, ripng->version); + ripng_peer_bad_packet(&from); + return 0; + } - /* Process RIPng packet. */ - switch (packet->command) - { - case RIPNG_REQUEST: - ripng_request_process (packet, len, &from, ifp); - break; - case RIPNG_RESPONSE: - ripng_response_process (packet, len, &from, ifp, hoplimit); - break; - default: - zlog_warn ("Invalid RIPng command %d", packet->command); - ripng_peer_bad_packet (&from); - break; - } - return 0; + /* Process RIPng packet. */ + switch (packet->command) { + case RIPNG_REQUEST: + ripng_request_process(packet, len, &from, ifp); + break; + case RIPNG_RESPONSE: + ripng_response_process(packet, len, &from, ifp, hoplimit); + break; + default: + zlog_warn("Invalid RIPng command %d", packet->command); + ripng_peer_bad_packet(&from); + break; + } + return 0; } /* Walk down the RIPng routing table then clear changed flag. */ -static void -ripng_clear_changed_flag (void) +static void ripng_clear_changed_flag(void) { - struct route_node *rp; - struct ripng_info *rinfo = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL; + struct route_node *rp; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - UNSET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); - /* This flag can be set only on the first entry. */ - break; - } + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + UNSET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); + /* This flag can be set only on the first entry. + */ + break; + } } /* Regular update of RIPng route. Send all routing formation to RIPng enabled interface. */ -static int -ripng_update (struct thread *t) +static int ripng_update(struct thread *t) { - struct listnode *node; - struct interface *ifp; - struct ripng_interface *ri; + struct listnode *node; + struct interface *ifp; + struct ripng_interface *ri; - /* Clear update timer thread. */ - ripng->t_update = NULL; + /* Clear update timer thread. */ + ripng->t_update = NULL; - /* Logging update event. */ - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng update timer expired!"); + /* Logging update event. */ + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("RIPng update timer expired!"); - /* Supply routes to each interface. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; + /* Supply routes to each interface. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; - if (if_is_loopback (ifp) || ! if_is_up (ifp)) - continue; + if (if_is_loopback(ifp) || !if_is_up(ifp)) + continue; - if (! ri->running) - continue; + if (!ri->running) + continue; - /* When passive interface is specified, suppress announce to the - interface. */ - if (ri->passive) - continue; + /* When passive interface is specified, suppress announce to the + interface. */ + if (ri->passive) + continue; #if RIPNG_ADVANCED - if (ri->ri_send == RIPNG_SEND_OFF) - { - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("[Event] RIPng send to if %d is suppressed by config", - ifp->ifindex); - continue; - } + if (ri->ri_send == RIPNG_SEND_OFF) { + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug( + "[Event] RIPng send to if %d is suppressed by config", + ifp->ifindex); + continue; + } #endif /* RIPNG_ADVANCED */ - ripng_output_process (ifp, NULL, ripng_all_route); - } + ripng_output_process(ifp, NULL, ripng_all_route); + } - /* Triggered updates may be suppressed if a regular update is due by - the time the triggered update would be sent. */ - if (ripng->t_triggered_interval) - { - thread_cancel (ripng->t_triggered_interval); - ripng->t_triggered_interval = NULL; - } - ripng->trigger = 0; + /* Triggered updates may be suppressed if a regular update is due by + the time the triggered update would be sent. */ + if (ripng->t_triggered_interval) { + thread_cancel(ripng->t_triggered_interval); + ripng->t_triggered_interval = NULL; + } + ripng->trigger = 0; - /* Reset flush event. */ - ripng_event (RIPNG_UPDATE_EVENT, 0); + /* Reset flush event. */ + ripng_event(RIPNG_UPDATE_EVENT, 0); - return 0; + return 0; } /* Triggered update interval timer. */ -static int -ripng_triggered_interval (struct thread *t) +static int ripng_triggered_interval(struct thread *t) { - ripng->t_triggered_interval = NULL; + ripng->t_triggered_interval = NULL; - if (ripng->trigger) - { - ripng->trigger = 0; - ripng_triggered_update (t); - } - return 0; -} + if (ripng->trigger) { + ripng->trigger = 0; + ripng_triggered_update(t); + } + return 0; +} /* Execute triggered update. */ -int -ripng_triggered_update (struct thread *t) +int ripng_triggered_update(struct thread *t) { - struct listnode *node; - struct interface *ifp; - struct ripng_interface *ri; - int interval; + struct listnode *node; + struct interface *ifp; + struct ripng_interface *ri; + int interval; - ripng->t_triggered_update = NULL; + ripng->t_triggered_update = NULL; - /* Cancel interval timer. */ - if (ripng->t_triggered_interval) - { - thread_cancel (ripng->t_triggered_interval); - ripng->t_triggered_interval = NULL; - } - ripng->trigger = 0; + /* Cancel interval timer. */ + if (ripng->t_triggered_interval) { + thread_cancel(ripng->t_triggered_interval); + ripng->t_triggered_interval = NULL; + } + ripng->trigger = 0; - /* Logging triggered update. */ - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng triggered update!"); + /* Logging triggered update. */ + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("RIPng triggered update!"); - /* Split Horizon processing is done when generating triggered - updates as well as normal updates (see section 2.6). */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; + /* Split Horizon processing is done when generating triggered + updates as well as normal updates (see section 2.6). */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; - if (if_is_loopback (ifp) || ! if_is_up (ifp)) - continue; + if (if_is_loopback(ifp) || !if_is_up(ifp)) + continue; - if (! ri->running) - continue; + if (!ri->running) + continue; - /* When passive interface is specified, suppress announce to the - interface. */ - if (ri->passive) - continue; + /* When passive interface is specified, suppress announce to the + interface. */ + if (ri->passive) + continue; - ripng_output_process (ifp, NULL, ripng_changed_route); - } + ripng_output_process(ifp, NULL, ripng_changed_route); + } - /* Once all of the triggered updates have been generated, the route - change flags should be cleared. */ - ripng_clear_changed_flag (); + /* Once all of the triggered updates have been generated, the route + change flags should be cleared. */ + ripng_clear_changed_flag(); - /* After a triggered update is sent, a timer should be set for a - random interval between 1 and 5 seconds. If other changes that - would trigger updates occur before the timer expires, a single - update is triggered when the timer expires. */ - interval = (random () % 5) + 1; + /* After a triggered update is sent, a timer should be set for a + random interval between 1 and 5 seconds. If other changes that + would trigger updates occur before the timer expires, a single + update is triggered when the timer expires. */ + interval = (random() % 5) + 1; - ripng->t_triggered_interval = - thread_add_timer (master, ripng_triggered_interval, NULL, interval); + ripng->t_triggered_interval = thread_add_timer( + master, ripng_triggered_interval, NULL, interval); - return 0; + return 0; } /* Write routing table entry to the stream and return next index of the routing table entry in the stream. */ -int -ripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p, - struct in6_addr *nexthop, u_int16_t tag, u_char metric) -{ - /* RIPng packet header. */ - if (num == 0) - { - stream_putc (s, RIPNG_RESPONSE); - stream_putc (s, RIPNG_V1); - stream_putw (s, 0); - } +int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p, + struct in6_addr *nexthop, u_int16_t tag, u_char metric) +{ + /* RIPng packet header. */ + if (num == 0) { + stream_putc(s, RIPNG_RESPONSE); + stream_putc(s, RIPNG_V1); + stream_putw(s, 0); + } - /* Write routing table entry. */ - if (!nexthop) - stream_write (s, (u_char *) &p->prefix, sizeof (struct in6_addr)); - else - stream_write (s, (u_char *) nexthop, sizeof (struct in6_addr)); - stream_putw (s, tag); - if (p) - stream_putc (s, p->prefixlen); - else - stream_putc (s, 0); - stream_putc (s, metric); + /* Write routing table entry. */ + if (!nexthop) + stream_write(s, (u_char *)&p->prefix, sizeof(struct in6_addr)); + else + stream_write(s, (u_char *)nexthop, sizeof(struct in6_addr)); + stream_putw(s, tag); + if (p) + stream_putc(s, p->prefixlen); + else + stream_putc(s, 0); + stream_putc(s, metric); - return ++num; + return ++num; } /* Send RESPONSE message to specified destination. */ -void -ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to, - int route_type) -{ - int ret; - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_interface *ri; - struct ripng_aggregate *aggregate; - struct prefix_ipv6 *p; - struct list * ripng_rte_list; - struct list *list = NULL; - struct listnode *listnode = NULL; - - if (IS_RIPNG_DEBUG_EVENT) { - if (to) - zlog_debug ("RIPng update routes to neighbor %s", - inet6_ntoa(to->sin6_addr)); - else - zlog_debug ("RIPng update routes on interface %s", ifp->name); - } - - /* Get RIPng interface. */ - ri = ifp->info; - - ripng_rte_list = ripng_rte_new(); - - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - { - if ((list = rp->info) != NULL && - (rinfo = listgetdata (listhead (list))) != NULL && - rinfo->suppress == 0) - { - /* If no route-map are applied, the RTE will be these following - * informations. - */ - p = (struct prefix_ipv6 *) &rp->p; - rinfo->metric_out = rinfo->metric; - rinfo->tag_out = rinfo->tag; - memset(&rinfo->nexthop_out, 0, sizeof(rinfo->nexthop_out)); - /* In order to avoid some local loops, - * if the RIPng route has a nexthop via this interface, keep the nexthop, - * otherwise set it to 0. The nexthop should not be propagated - * beyond the local broadcast/multicast area in order - * to avoid an IGP multi-level recursive look-up. - */ - if (rinfo->ifindex == ifp->ifindex) - rinfo->nexthop_out = rinfo->nexthop; - - /* Apply output filters. */ - ret = ripng_filter (RIPNG_FILTER_OUT, p, ri); - if (ret < 0) - continue; - - /* Changed route only output. */ - if (route_type == ripng_changed_route && - (! (rinfo->flags & RIPNG_RTF_CHANGED))) - continue; - - /* Split horizon. */ - if (ri->split_horizon == RIPNG_SPLIT_HORIZON) - { - /* We perform split horizon for RIPng routes. */ - int suppress = 0; - struct ripng_info *tmp_rinfo = NULL; - - for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) - if (tmp_rinfo->type == ZEBRA_ROUTE_RIPNG && - tmp_rinfo->ifindex == ifp->ifindex) - { - suppress = 1; - break; - } - if (suppress) - continue; - } - - /* Preparation for route-map. */ - rinfo->metric_set = 0; - /* nexthop_out, - * metric_out - * and tag_out are already initialized. - */ - - /* Interface route-map */ - if (ri->routemap[RIPNG_FILTER_OUT]) - { - int ret; - - ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], - (struct prefix *) p, RMAP_RIPNG, - rinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("RIPng %s/%d is filtered by route-map out", - inet6_ntoa (p->prefix), p->prefixlen); - continue; - } - - } - - /* Redistribute route-map. */ - if (ripng->route_map[rinfo->type].name) - { - int ret; - - ret = route_map_apply (ripng->route_map[rinfo->type].map, - (struct prefix *) p, RMAP_RIPNG, - rinfo); +void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, + int route_type) +{ + int ret; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_interface *ri; + struct ripng_aggregate *aggregate; + struct prefix_ipv6 *p; + struct list *ripng_rte_list; + struct list *list = NULL; + struct listnode *listnode = NULL; + + if (IS_RIPNG_DEBUG_EVENT) { + if (to) + zlog_debug("RIPng update routes to neighbor %s", + inet6_ntoa(to->sin6_addr)); + else + zlog_debug("RIPng update routes on interface %s", + ifp->name); + } - if (ret == RMAP_DENYMATCH) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("RIPng %s/%d is filtered by route-map", - inet6_ntoa (p->prefix), p->prefixlen); - continue; + /* Get RIPng interface. */ + ri = ifp->info; + + ripng_rte_list = ripng_rte_new(); + + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + if ((list = rp->info) != NULL + && (rinfo = listgetdata(listhead(list))) != NULL + && rinfo->suppress == 0) { + /* If no route-map are applied, the RTE will be these + * following + * informations. + */ + p = (struct prefix_ipv6 *)&rp->p; + rinfo->metric_out = rinfo->metric; + rinfo->tag_out = rinfo->tag; + memset(&rinfo->nexthop_out, 0, + sizeof(rinfo->nexthop_out)); + /* In order to avoid some local loops, + * if the RIPng route has a nexthop via this interface, + * keep the nexthop, + * otherwise set it to 0. The nexthop should not be + * propagated + * beyond the local broadcast/multicast area in order + * to avoid an IGP multi-level recursive look-up. + */ + if (rinfo->ifindex == ifp->ifindex) + rinfo->nexthop_out = rinfo->nexthop; + + /* Apply output filters. */ + ret = ripng_filter(RIPNG_FILTER_OUT, p, ri); + if (ret < 0) + continue; + + /* Changed route only output. */ + if (route_type == ripng_changed_route + && (!(rinfo->flags & RIPNG_RTF_CHANGED))) + continue; + + /* Split horizon. */ + if (ri->split_horizon == RIPNG_SPLIT_HORIZON) { + /* We perform split horizon for RIPng routes. */ + int suppress = 0; + struct ripng_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + tmp_rinfo)) + if (tmp_rinfo->type == ZEBRA_ROUTE_RIPNG + && tmp_rinfo->ifindex + == ifp->ifindex) { + suppress = 1; + break; + } + if (suppress) + continue; + } + + /* Preparation for route-map. */ + rinfo->metric_set = 0; + /* nexthop_out, + * metric_out + * and tag_out are already initialized. + */ + + /* Interface route-map */ + if (ri->routemap[RIPNG_FILTER_OUT]) { + int ret; + + ret = route_map_apply( + ri->routemap[RIPNG_FILTER_OUT], + (struct prefix *)p, RMAP_RIPNG, rinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "RIPng %s/%d is filtered by route-map out", + inet6_ntoa(p->prefix), + p->prefixlen); + continue; + } + } + + /* Redistribute route-map. */ + if (ripng->route_map[rinfo->type].name) { + int ret; + + ret = route_map_apply( + ripng->route_map[rinfo->type].map, + (struct prefix *)p, RMAP_RIPNG, rinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "RIPng %s/%d is filtered by route-map", + inet6_ntoa(p->prefix), + p->prefixlen); + continue; + } + } + + /* When the route-map does not set metric. */ + if (!rinfo->metric_set) { + /* If the redistribute metric is set. */ + if (ripng->route_map[rinfo->type].metric_config + && rinfo->metric != RIPNG_METRIC_INFINITY) { + rinfo->metric_out = + ripng->route_map[rinfo->type] + .metric; + } else { + /* If the route is not connected or + localy generated + one, use default-metric value */ + if (rinfo->type != ZEBRA_ROUTE_RIPNG + && rinfo->type + != ZEBRA_ROUTE_CONNECT + && rinfo->metric + != RIPNG_METRIC_INFINITY) + rinfo->metric_out = + ripng->default_metric; + } + } + + /* Apply offset-list */ + if (rinfo->metric_out != RIPNG_METRIC_INFINITY) + ripng_offset_list_apply_out(p, ifp, + &rinfo->metric_out); + + if (rinfo->metric_out > RIPNG_METRIC_INFINITY) + rinfo->metric_out = RIPNG_METRIC_INFINITY; + + /* Perform split-horizon with poisoned reverse + * for RIPng routes. + **/ + if (ri->split_horizon + == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) { + struct ripng_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + tmp_rinfo)) + if ((tmp_rinfo->type + == ZEBRA_ROUTE_RIPNG) + && tmp_rinfo->ifindex + == ifp->ifindex) + rinfo->metric_out = + RIPNG_METRIC_INFINITY; + } + + /* Add RTE to the list */ + ripng_rte_add(ripng_rte_list, p, rinfo, NULL); } - } - - /* When the route-map does not set metric. */ - if (! rinfo->metric_set) - { - /* If the redistribute metric is set. */ - if (ripng->route_map[rinfo->type].metric_config - && rinfo->metric != RIPNG_METRIC_INFINITY) - { - rinfo->metric_out = ripng->route_map[rinfo->type].metric; - } - else - { - /* If the route is not connected or localy generated - one, use default-metric value */ - if (rinfo->type != ZEBRA_ROUTE_RIPNG - && rinfo->type != ZEBRA_ROUTE_CONNECT - && rinfo->metric != RIPNG_METRIC_INFINITY) - rinfo->metric_out = ripng->default_metric; - } - } - - /* Apply offset-list */ - if (rinfo->metric_out != RIPNG_METRIC_INFINITY) - ripng_offset_list_apply_out (p, ifp, &rinfo->metric_out); - - if (rinfo->metric_out > RIPNG_METRIC_INFINITY) - rinfo->metric_out = RIPNG_METRIC_INFINITY; - - /* Perform split-horizon with poisoned reverse - * for RIPng routes. - **/ - if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) { - struct ripng_info *tmp_rinfo = NULL; - - for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) - if ((tmp_rinfo->type == ZEBRA_ROUTE_RIPNG) && - tmp_rinfo->ifindex == ifp->ifindex) - rinfo->metric_out = RIPNG_METRIC_INFINITY; - } - - /* Add RTE to the list */ - ripng_rte_add(ripng_rte_list, p, rinfo, NULL); - } - - /* Process the aggregated RTE entry */ - if ((aggregate = rp->aggregate) != NULL && - aggregate->count > 0 && - aggregate->suppress == 0) - { - /* If no route-map are applied, the RTE will be these following - * informations. - */ - p = (struct prefix_ipv6 *) &rp->p; - aggregate->metric_set = 0; - aggregate->metric_out = aggregate->metric; - aggregate->tag_out = aggregate->tag; - memset(&aggregate->nexthop_out, 0, sizeof(aggregate->nexthop_out)); - - /* Apply output filters.*/ - ret = ripng_filter (RIPNG_FILTER_OUT, p, ri); - if (ret < 0) - continue; - - /* Interface route-map */ - if (ri->routemap[RIPNG_FILTER_OUT]) - { - int ret; - struct ripng_info newinfo; - - /* let's cast the aggregate structure to ripng_info */ - memset (&newinfo, 0, sizeof (struct ripng_info)); - /* the nexthop is :: */ - newinfo.metric = aggregate->metric; - newinfo.metric_out = aggregate->metric_out; - newinfo.tag = aggregate->tag; - newinfo.tag_out = aggregate->tag_out; - - ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], - (struct prefix *) p, RMAP_RIPNG, - &newinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIPNG_DEBUG_PACKET) - zlog_debug ("RIPng %s/%d is filtered by route-map out", - inet6_ntoa (p->prefix), p->prefixlen); - continue; - } - - aggregate->metric_out = newinfo.metric_out; - aggregate->tag_out = newinfo.tag_out; - if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out)) - aggregate->nexthop_out = newinfo.nexthop_out; - } - - /* There is no redistribute routemap for the aggregated RTE */ - - /* Changed route only output. */ - /* XXX, vincent, in order to increase time convergence, - * it should be announced if a child has changed. - */ - if (route_type == ripng_changed_route) - continue; - /* Apply offset-list */ - if (aggregate->metric_out != RIPNG_METRIC_INFINITY) - ripng_offset_list_apply_out (p, ifp, &aggregate->metric_out); - - if (aggregate->metric_out > RIPNG_METRIC_INFINITY) - aggregate->metric_out = RIPNG_METRIC_INFINITY; - - /* Add RTE to the list */ - ripng_rte_add(ripng_rte_list, p, NULL, aggregate); + /* Process the aggregated RTE entry */ + if ((aggregate = rp->aggregate) != NULL && aggregate->count > 0 + && aggregate->suppress == 0) { + /* If no route-map are applied, the RTE will be these + * following + * informations. + */ + p = (struct prefix_ipv6 *)&rp->p; + aggregate->metric_set = 0; + aggregate->metric_out = aggregate->metric; + aggregate->tag_out = aggregate->tag; + memset(&aggregate->nexthop_out, 0, + sizeof(aggregate->nexthop_out)); + + /* Apply output filters.*/ + ret = ripng_filter(RIPNG_FILTER_OUT, p, ri); + if (ret < 0) + continue; + + /* Interface route-map */ + if (ri->routemap[RIPNG_FILTER_OUT]) { + int ret; + struct ripng_info newinfo; + + /* let's cast the aggregate structure to + * ripng_info */ + memset(&newinfo, 0, sizeof(struct ripng_info)); + /* the nexthop is :: */ + newinfo.metric = aggregate->metric; + newinfo.metric_out = aggregate->metric_out; + newinfo.tag = aggregate->tag; + newinfo.tag_out = aggregate->tag_out; + + ret = route_map_apply( + ri->routemap[RIPNG_FILTER_OUT], + (struct prefix *)p, RMAP_RIPNG, + &newinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIPNG_DEBUG_PACKET) + zlog_debug( + "RIPng %s/%d is filtered by route-map out", + inet6_ntoa(p->prefix), + p->prefixlen); + continue; + } + + aggregate->metric_out = newinfo.metric_out; + aggregate->tag_out = newinfo.tag_out; + if (IN6_IS_ADDR_LINKLOCAL(&newinfo.nexthop_out)) + aggregate->nexthop_out = + newinfo.nexthop_out; + } + + /* There is no redistribute routemap for the aggregated + * RTE */ + + /* Changed route only output. */ + /* XXX, vincent, in order to increase time convergence, + * it should be announced if a child has changed. + */ + if (route_type == ripng_changed_route) + continue; + + /* Apply offset-list */ + if (aggregate->metric_out != RIPNG_METRIC_INFINITY) + ripng_offset_list_apply_out( + p, ifp, &aggregate->metric_out); + + if (aggregate->metric_out > RIPNG_METRIC_INFINITY) + aggregate->metric_out = RIPNG_METRIC_INFINITY; + + /* Add RTE to the list */ + ripng_rte_add(ripng_rte_list, p, NULL, aggregate); + } } - } - - /* Flush the list */ - ripng_rte_send(ripng_rte_list, ifp, to); - ripng_rte_free(ripng_rte_list); + /* Flush the list */ + ripng_rte_send(ripng_rte_list, ifp, to); + ripng_rte_free(ripng_rte_list); } /* Create new RIPng instance and set it to global variable. */ -static int -ripng_create (void) +static int ripng_create(void) { - /* ripng should be NULL. */ - assert (ripng == NULL); + /* ripng should be NULL. */ + assert(ripng == NULL); - /* Allocaste RIPng instance. */ - ripng = XCALLOC (MTYPE_RIPNG, sizeof (struct ripng)); + /* Allocaste RIPng instance. */ + ripng = XCALLOC(MTYPE_RIPNG, sizeof(struct ripng)); - /* Default version and timer values. */ - ripng->version = RIPNG_V1; - ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; - ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; - ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; - ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; - - /* Make buffer. */ - ripng->ibuf = stream_new (RIPNG_MAX_PACKET_SIZE * 5); - ripng->obuf = stream_new (RIPNG_MAX_PACKET_SIZE); + /* Default version and timer values. */ + ripng->version = RIPNG_V1; + ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; + ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; + ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; + ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; - /* Initialize RIPng routig table. */ - ripng->table = route_table_init (); - ripng->route = route_table_init (); - ripng->aggregate = route_table_init (); - - /* Make socket. */ - ripng->sock = ripng_make_socket (); - if (ripng->sock < 0) - return ripng->sock; + /* Make buffer. */ + ripng->ibuf = stream_new(RIPNG_MAX_PACKET_SIZE * 5); + ripng->obuf = stream_new(RIPNG_MAX_PACKET_SIZE); - /* Threads. */ - ripng_event (RIPNG_READ, ripng->sock); - ripng_event (RIPNG_UPDATE_EVENT, 1); + /* Initialize RIPng routig table. */ + ripng->table = route_table_init(); + ripng->route = route_table_init(); + ripng->aggregate = route_table_init(); - return 0; + /* Make socket. */ + ripng->sock = ripng_make_socket(); + if (ripng->sock < 0) + return ripng->sock; + + /* Threads. */ + ripng_event(RIPNG_READ, ripng->sock); + ripng_event(RIPNG_UPDATE_EVENT, 1); + + return 0; } /* Send RIPng request to the interface. */ -int -ripng_request (struct interface *ifp) +int ripng_request(struct interface *ifp) { - struct rte *rte; - struct ripng_packet ripng_packet; + struct rte *rte; + struct ripng_packet ripng_packet; - /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */ - if (if_is_loopback(ifp)) - return 0; + /* In default ripd doesn't send RIP_REQUEST to the loopback interface. + */ + if (if_is_loopback(ifp)) + return 0; - /* If interface is down, don't send RIP packet. */ - if (! if_is_up (ifp)) - return 0; + /* If interface is down, don't send RIP packet. */ + if (!if_is_up(ifp)) + return 0; - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("RIPng send request to %s", ifp->name); + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug("RIPng send request to %s", ifp->name); - memset (&ripng_packet, 0, sizeof (ripng_packet)); - ripng_packet.command = RIPNG_REQUEST; - ripng_packet.version = RIPNG_V1; - rte = ripng_packet.rte; - rte->metric = RIPNG_METRIC_INFINITY; + memset(&ripng_packet, 0, sizeof(ripng_packet)); + ripng_packet.command = RIPNG_REQUEST; + ripng_packet.version = RIPNG_V1; + rte = ripng_packet.rte; + rte->metric = RIPNG_METRIC_INFINITY; - return ripng_send_packet ((caddr_t) &ripng_packet, sizeof (ripng_packet), - NULL, ifp); + return ripng_send_packet((caddr_t)&ripng_packet, sizeof(ripng_packet), + NULL, ifp); } -static int -ripng_update_jitter (int time) +static int ripng_update_jitter(int time) { - return ((random () % (time + 1)) - (time / 2)); + return ((random() % (time + 1)) - (time / 2)); } -void -ripng_event (enum ripng_event event, int sock) +void ripng_event(enum ripng_event event, int sock) { - int jitter = 0; + int jitter = 0; - switch (event) - { - case RIPNG_READ: - if (!ripng->t_read) - ripng->t_read = thread_add_read (master, ripng_read, NULL, sock); - break; - case RIPNG_UPDATE_EVENT: - if (ripng->t_update) - { - thread_cancel (ripng->t_update); - ripng->t_update = NULL; - } - /* Update timer jitter. */ - jitter = ripng_update_jitter (ripng->update_time); - - ripng->t_update = - thread_add_timer (master, ripng_update, NULL, - sock ? 2 : ripng->update_time + jitter); - break; - case RIPNG_TRIGGERED_UPDATE: - if (ripng->t_triggered_interval) - ripng->trigger = 1; - else if (! ripng->t_triggered_update) - ripng->t_triggered_update = - thread_add_event (master, ripng_triggered_update, NULL, 0); - break; - default: - break; - } + switch (event) { + case RIPNG_READ: + if (!ripng->t_read) + ripng->t_read = + thread_add_read(master, ripng_read, NULL, sock); + break; + case RIPNG_UPDATE_EVENT: + if (ripng->t_update) { + thread_cancel(ripng->t_update); + ripng->t_update = NULL; + } + /* Update timer jitter. */ + jitter = ripng_update_jitter(ripng->update_time); + + ripng->t_update = thread_add_timer( + master, ripng_update, NULL, + sock ? 2 : ripng->update_time + jitter); + break; + case RIPNG_TRIGGERED_UPDATE: + if (ripng->t_triggered_interval) + ripng->trigger = 1; + else if (!ripng->t_triggered_update) + ripng->t_triggered_update = thread_add_event( + master, ripng_triggered_update, NULL, 0); + break; + default: + break; + } } /* Print out routes update time. */ -static void -ripng_vty_out_uptime (struct vty *vty, struct ripng_info *rinfo) +static void ripng_vty_out_uptime(struct vty *vty, struct ripng_info *rinfo) { - time_t clock; - struct tm *tm; + time_t clock; + struct tm *tm; #define TIME_BUF 25 - char timebuf [TIME_BUF]; - struct thread *thread; - - if ((thread = rinfo->t_timeout) != NULL) - { - clock = thread_timer_remain_second (thread); - tm = gmtime (&clock); - strftime (timebuf, TIME_BUF, "%M:%S", tm); - vty_out (vty, "%5s", timebuf); - } - else if ((thread = rinfo->t_garbage_collect) != NULL) - { - clock = thread_timer_remain_second (thread); - tm = gmtime (&clock); - strftime (timebuf, TIME_BUF, "%M:%S", tm); - vty_out (vty, "%5s", timebuf); - } + char timebuf[TIME_BUF]; + struct thread *thread; + + if ((thread = rinfo->t_timeout) != NULL) { + clock = thread_timer_remain_second(thread); + tm = gmtime(&clock); + strftime(timebuf, TIME_BUF, "%M:%S", tm); + vty_out(vty, "%5s", timebuf); + } else if ((thread = rinfo->t_garbage_collect) != NULL) { + clock = thread_timer_remain_second(thread); + tm = gmtime(&clock); + strftime(timebuf, TIME_BUF, "%M:%S", tm); + vty_out(vty, "%5s", timebuf); + } } -static char * -ripng_route_subtype_print (struct ripng_info *rinfo) -{ - static char str[3]; - memset(str, 0, 3); - - if (rinfo->suppress) - strcat(str, "S"); +static char *ripng_route_subtype_print(struct ripng_info *rinfo) +{ + static char str[3]; + memset(str, 0, 3); + + if (rinfo->suppress) + strcat(str, "S"); + + switch (rinfo->sub_type) { + case RIPNG_ROUTE_RTE: + strcat(str, "n"); + break; + case RIPNG_ROUTE_STATIC: + strcat(str, "s"); + break; + case RIPNG_ROUTE_DEFAULT: + strcat(str, "d"); + break; + case RIPNG_ROUTE_REDISTRIBUTE: + strcat(str, "r"); + break; + case RIPNG_ROUTE_INTERFACE: + strcat(str, "i"); + break; + default: + strcat(str, "?"); + break; + } - switch (rinfo->sub_type) - { - case RIPNG_ROUTE_RTE: - strcat(str, "n"); - break; - case RIPNG_ROUTE_STATIC: - strcat(str, "s"); - break; - case RIPNG_ROUTE_DEFAULT: - strcat(str, "d"); - break; - case RIPNG_ROUTE_REDISTRIBUTE: - strcat(str, "r"); - break; - case RIPNG_ROUTE_INTERFACE: - strcat(str, "i"); - break; - default: - strcat(str, "?"); - break; - } - - return str; + return str; } DEFUN (show_ipv6_ripng, @@ -1994,109 +1948,109 @@ DEFUN (show_ipv6_ripng, IPV6_STR "Show RIPng routes\n") { - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_aggregate *aggregate; - struct prefix_ipv6 *p; - struct list *list = NULL; - struct listnode *listnode = NULL; - int len; - - if (! ripng) - return CMD_SUCCESS; - - /* Header of display. */ - vty_out (vty, "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s" - "Sub-codes:%s" - " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s" - " (i) - interface, (a/S) - aggregated/Suppressed%s%s" - " Network Next Hop Via Metric Tag Time%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - { - if ((aggregate = rp->aggregate) != NULL) - { - p = (struct prefix_ipv6 *) &rp->p; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_aggregate *aggregate; + struct prefix_ipv6 *p; + struct list *list = NULL; + struct listnode *listnode = NULL; + int len; + + if (!ripng) + return CMD_SUCCESS; + + /* Header of display. */ + vty_out(vty, + "Codes: R - RIPng, C - connected, S - Static, O - OSPF, B - BGP%s" + "Sub-codes:%s" + " (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s" + " (i) - interface, (a/S) - aggregated/Suppressed%s%s" + " Network Next Hop Via Metric Tag Time%s", + VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, + VTY_NEWLINE); + + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + if ((aggregate = rp->aggregate) != NULL) { + p = (struct prefix_ipv6 *)&rp->p; #ifdef DEBUG - vty_out (vty, "R(a) %d/%d %s/%d ", - aggregate->count, aggregate->suppress, - inet6_ntoa (p->prefix), p->prefixlen); + vty_out(vty, "R(a) %d/%d %s/%d ", aggregate->count, + aggregate->suppress, inet6_ntoa(p->prefix), + p->prefixlen); #else - vty_out (vty, "R(a) %s/%d ", - inet6_ntoa (p->prefix), p->prefixlen); + vty_out(vty, "R(a) %s/%d ", inet6_ntoa(p->prefix), + p->prefixlen); #endif /* DEBUG */ - vty_out (vty, "%s", VTY_NEWLINE); - vty_out (vty, "%*s", 18, " "); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%*s", 18, " "); - vty_out (vty, "%*s", 28, " "); - vty_out (vty, "self %2d %3"ROUTE_TAG_PRI"%s", aggregate->metric, - (route_tag_t)aggregate->tag, - VTY_NEWLINE); - } + vty_out(vty, "%*s", 28, " "); + vty_out(vty, "self %2d %3" ROUTE_TAG_PRI "%s", + aggregate->metric, (route_tag_t)aggregate->tag, + VTY_NEWLINE); + } - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - p = (struct prefix_ipv6 *) &rp->p; + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + p = (struct prefix_ipv6 *)&rp->p; #ifdef DEBUG - vty_out (vty, "%c(%s) 0/%d %s/%d ", - zebra_route_char(rinfo->type), - ripng_route_subtype_print(rinfo), - rinfo->suppress, - inet6_ntoa (p->prefix), p->prefixlen); + vty_out(vty, "%c(%s) 0/%d %s/%d ", + zebra_route_char(rinfo->type), + ripng_route_subtype_print(rinfo), + rinfo->suppress, inet6_ntoa(p->prefix), + p->prefixlen); #else - vty_out (vty, "%c(%s) %s/%d ", - zebra_route_char(rinfo->type), - ripng_route_subtype_print(rinfo), - inet6_ntoa (p->prefix), p->prefixlen); + vty_out(vty, "%c(%s) %s/%d ", + zebra_route_char(rinfo->type), + ripng_route_subtype_print(rinfo), + inet6_ntoa(p->prefix), p->prefixlen); #endif /* DEBUG */ - vty_out (vty, "%s", VTY_NEWLINE); - vty_out (vty, "%*s", 18, " "); - len = vty_out (vty, "%s", inet6_ntoa (rinfo->nexthop)); - - len = 28 - len; - if (len > 0) - len = vty_out (vty, "%*s", len, " "); - - /* from */ - if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && - (rinfo->sub_type == RIPNG_ROUTE_RTE)) - { - len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); - } else if (rinfo->metric == RIPNG_METRIC_INFINITY) - { - len = vty_out (vty, "kill"); - } else - len = vty_out (vty, "self"); - - len = 9 - len; - if (len > 0) - vty_out (vty, "%*s", len, " "); - - vty_out (vty, " %2d %3"ROUTE_TAG_PRI" ", - rinfo->metric, (route_tag_t)rinfo->tag); - - /* time */ - if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && - (rinfo->sub_type == RIPNG_ROUTE_RTE)) - { - /* RTE from remote RIP routers */ - ripng_vty_out_uptime (vty, rinfo); - } else if (rinfo->metric == RIPNG_METRIC_INFINITY) - { - /* poisonous reversed routes (gc) */ - ripng_vty_out_uptime (vty, rinfo); - } - - vty_out (vty, "%s", VTY_NEWLINE); + vty_out(vty, "%s", VTY_NEWLINE); + vty_out(vty, "%*s", 18, " "); + len = vty_out(vty, "%s", + inet6_ntoa(rinfo->nexthop)); + + len = 28 - len; + if (len > 0) + len = vty_out(vty, "%*s", len, " "); + + /* from */ + if ((rinfo->type == ZEBRA_ROUTE_RIPNG) + && (rinfo->sub_type == RIPNG_ROUTE_RTE)) { + len = vty_out( + vty, "%s", + ifindex2ifname(rinfo->ifindex, + VRF_DEFAULT)); + } else if (rinfo->metric + == RIPNG_METRIC_INFINITY) { + len = vty_out(vty, "kill"); + } else + len = vty_out(vty, "self"); + + len = 9 - len; + if (len > 0) + vty_out(vty, "%*s", len, " "); + + vty_out(vty, " %2d %3" ROUTE_TAG_PRI " ", + rinfo->metric, (route_tag_t)rinfo->tag); + + /* time */ + if ((rinfo->type == ZEBRA_ROUTE_RIPNG) + && (rinfo->sub_type == RIPNG_ROUTE_RTE)) { + /* RTE from remote RIP routers */ + ripng_vty_out_uptime(vty, rinfo); + } else if (rinfo->metric + == RIPNG_METRIC_INFINITY) { + /* poisonous reversed routes (gc) */ + ripng_vty_out_uptime(vty, rinfo); + } + + vty_out(vty, "%s", VTY_NEWLINE); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_ipv6_ripng_status, @@ -2107,64 +2061,61 @@ DEFUN (show_ipv6_ripng_status, "Show RIPng routes\n" "IPv6 routing protocol process parameters and statistics\n") { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - if (! ripng) - return CMD_SUCCESS; + if (!ripng) + return CMD_SUCCESS; - vty_out (vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE); - vty_out (vty, " Sending updates every %ld seconds with +/-50%%,", - ripng->update_time); - vty_out (vty, " next due in %lu seconds%s", - thread_timer_remain_second (ripng->t_update), - VTY_NEWLINE); - vty_out (vty, " Timeout after %ld seconds,", ripng->timeout_time); - vty_out (vty, " garbage collect after %ld seconds%s", ripng->garbage_time, - VTY_NEWLINE); + vty_out(vty, "Routing Protocol is \"RIPng\"%s", VTY_NEWLINE); + vty_out(vty, " Sending updates every %ld seconds with +/-50%%,", + ripng->update_time); + vty_out(vty, " next due in %lu seconds%s", + thread_timer_remain_second(ripng->t_update), VTY_NEWLINE); + vty_out(vty, " Timeout after %ld seconds,", ripng->timeout_time); + vty_out(vty, " garbage collect after %ld seconds%s", + ripng->garbage_time, VTY_NEWLINE); - /* Filtering status show. */ - config_show_distribute (vty); + /* Filtering status show. */ + config_show_distribute(vty); - /* Default metric information. */ - vty_out (vty, " Default redistribution metric is %d%s", - ripng->default_metric, VTY_NEWLINE); + /* Default metric information. */ + vty_out(vty, " Default redistribution metric is %d%s", + ripng->default_metric, VTY_NEWLINE); - /* Redistribute information. */ - vty_out (vty, " Redistributing:"); - ripng_redistribute_write (vty, 0); - vty_out (vty, "%s", VTY_NEWLINE); + /* Redistribute information. */ + vty_out(vty, " Redistributing:"); + ripng_redistribute_write(vty, 0); + vty_out(vty, "%s", VTY_NEWLINE); - vty_out (vty, " Default version control: send version %d,", ripng->version); - vty_out (vty, " receive version %d %s", ripng->version, - VTY_NEWLINE); + vty_out(vty, " Default version control: send version %d,", + ripng->version); + vty_out(vty, " receive version %d %s", ripng->version, VTY_NEWLINE); - vty_out (vty, " Interface Send Recv%s", VTY_NEWLINE); + vty_out(vty, " Interface Send Recv%s", VTY_NEWLINE); - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct ripng_interface *ri; - - ri = ifp->info; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct ripng_interface *ri; - if (ri->enable_network || ri->enable_interface) - { + ri = ifp->info; - vty_out (vty, " %-17s%-3d %-3d%s", ifp->name, - ripng->version, - ripng->version, - VTY_NEWLINE); + if (ri->enable_network || ri->enable_interface) { + + vty_out(vty, " %-17s%-3d %-3d%s", ifp->name, + ripng->version, ripng->version, VTY_NEWLINE); + } } - } - vty_out (vty, " Routing for Networks:%s", VTY_NEWLINE); - ripng_network_write (vty, 0); + vty_out(vty, " Routing for Networks:%s", VTY_NEWLINE); + ripng_network_write(vty, 0); - vty_out (vty, " Routing Information Sources:%s", VTY_NEWLINE); - vty_out (vty, " Gateway BadPackets BadRoutes Distance Last Update%s", VTY_NEWLINE); - ripng_peer_display (vty); + vty_out(vty, " Routing Information Sources:%s", VTY_NEWLINE); + vty_out(vty, + " Gateway BadPackets BadRoutes Distance Last Update%s", + VTY_NEWLINE); + ripng_peer_display(vty); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (clear_ipv6_rip, @@ -2174,45 +2125,41 @@ DEFUN (clear_ipv6_rip, IPV6_STR "Clear IPv6 RIP database") { - struct route_node *rp; - struct ripng_info *rinfo; - struct list *list; - struct listnode *listnode; + struct route_node *rp; + struct ripng_info *rinfo; + struct list *list; + struct listnode *listnode; - /* Clear received RIPng routes */ - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - { - list = rp->info; - if (list == NULL) - continue; + /* Clear received RIPng routes */ + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + list = rp->info; + if (list == NULL) + continue; - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - if (! ripng_route_rte (rinfo)) - continue; + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + if (!ripng_route_rte(rinfo)) + continue; - if (CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) - ripng_zebra_ipv6_delete (rp); - break; - } + if (CHECK_FLAG(rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete(rp); + break; + } - if (rinfo) - { - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - listnode_delete (list, rinfo); - ripng_info_free (rinfo); - } + if (rinfo) { + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_OFF(rinfo->t_garbage_collect); + listnode_delete(list, rinfo); + ripng_info_free(rinfo); + } - if (list_isempty (list)) - { - list_free (list); - rp->info = NULL; - route_unlock_node (rp); + if (list_isempty(list)) { + list_free(list); + rp->info = NULL; + route_unlock_node(rp); + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN_NOSH (router_ripng, @@ -2221,23 +2168,21 @@ DEFUN_NOSH (router_ripng, "Enable a routing process\n" "Make RIPng instance command\n") { - int ret; + int ret; - vty->node = RIPNG_NODE; + vty->node = RIPNG_NODE; - if (!ripng) - { - ret = ripng_create (); + if (!ripng) { + ret = ripng_create(); - /* Notice to user we couldn't create RIPng. */ - if (ret < 0) - { - zlog_warn ("can't create RIPng"); - return CMD_WARNING; + /* Notice to user we couldn't create RIPng. */ + if (ret < 0) { + zlog_warn("can't create RIPng"); + return CMD_WARNING; + } } - } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_router_ripng, @@ -2247,9 +2192,9 @@ DEFUN (no_router_ripng, "Enable a routing process\n" "Make RIPng instance command\n") { - if(ripng) - ripng_clean(); - return CMD_SUCCESS; + if (ripng) + ripng_clean(); + return CMD_SUCCESS; } DEFUN (ripng_route, @@ -2258,31 +2203,32 @@ DEFUN (ripng_route, "Static route setup\n" "Set static RIPng route announcement\n") { - int idx_ipv6addr = 1; - int ret; - struct prefix_ipv6 p; - struct route_node *rp; - - ret = str2prefix_ipv6 (argv[idx_ipv6addr]->arg, (struct prefix_ipv6 *)&p); - if (ret <= 0) - { - vty_out (vty, "Malformed address%s", VTY_NEWLINE); - return CMD_WARNING; - } - apply_mask_ipv6 (&p); + int idx_ipv6addr = 1; + int ret; + struct prefix_ipv6 p; + struct route_node *rp; - rp = route_node_get (ripng->route, (struct prefix *) &p); - if (rp->info) - { - vty_out (vty, "There is already same static route.%s", VTY_NEWLINE); - route_unlock_node (rp); - return CMD_WARNING; - } - rp->info = (void *)1; + ret = str2prefix_ipv6(argv[idx_ipv6addr]->arg, + (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, "Malformed address%s", VTY_NEWLINE); + return CMD_WARNING; + } + apply_mask_ipv6(&p); + + rp = route_node_get(ripng->route, (struct prefix *)&p); + if (rp->info) { + vty_out(vty, "There is already same static route.%s", + VTY_NEWLINE); + route_unlock_node(rp); + return CMD_WARNING; + } + rp->info = (void *)1; - ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, NULL, 0); + ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0, + NULL, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ripng_route, @@ -2292,33 +2238,32 @@ DEFUN (no_ripng_route, "Static route setup\n" "Delete static RIPng route announcement\n") { - int idx_ipv6addr = 2; - int ret; - struct prefix_ipv6 p; - struct route_node *rp; + int idx_ipv6addr = 2; + int ret; + struct prefix_ipv6 p; + struct route_node *rp; - ret = str2prefix_ipv6 (argv[idx_ipv6addr]->arg, (struct prefix_ipv6 *)&p); - if (ret <= 0) - { - vty_out (vty, "Malformed address%s", VTY_NEWLINE); - return CMD_WARNING; - } - apply_mask_ipv6 (&p); + ret = str2prefix_ipv6(argv[idx_ipv6addr]->arg, + (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, "Malformed address%s", VTY_NEWLINE); + return CMD_WARNING; + } + apply_mask_ipv6(&p); - rp = route_node_lookup (ripng->route, (struct prefix *) &p); - if (! rp) - { - vty_out (vty, "Can't find static route.%s", VTY_NEWLINE); - return CMD_WARNING; - } + rp = route_node_lookup(ripng->route, (struct prefix *)&p); + if (!rp) { + vty_out(vty, "Can't find static route.%s", VTY_NEWLINE); + return CMD_WARNING; + } - ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0); - route_unlock_node (rp); + ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p, 0); + route_unlock_node(rp); - rp->info = NULL; - route_unlock_node (rp); + rp->info = NULL; + route_unlock_node(rp); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ripng_aggregate_address, @@ -2327,31 +2272,31 @@ DEFUN (ripng_aggregate_address, "Set aggregate RIPng route announcement\n" "Aggregate network\n") { - int idx_ipv6_prefixlen = 1; - int ret; - struct prefix p; - struct route_node *node; + int idx_ipv6_prefixlen = 1; + int ret; + struct prefix p; + struct route_node *node; - ret = str2prefix_ipv6 (argv[idx_ipv6_prefixlen]->arg, (struct prefix_ipv6 *)&p); - if (ret <= 0) - { - vty_out (vty, "Malformed address%s", VTY_NEWLINE); - return CMD_WARNING; - } + ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, + (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, "Malformed address%s", VTY_NEWLINE); + return CMD_WARNING; + } - /* Check aggregate alredy exist or not. */ - node = route_node_get (ripng->aggregate, &p); - if (node->info) - { - vty_out (vty, "There is already same aggregate route.%s", VTY_NEWLINE); - route_unlock_node (node); - return CMD_WARNING; - } - node->info = (void *)1; + /* Check aggregate alredy exist or not. */ + node = route_node_get(ripng->aggregate, &p); + if (node->info) { + vty_out(vty, "There is already same aggregate route.%s", + VTY_NEWLINE); + route_unlock_node(node); + return CMD_WARNING; + } + node->info = (void *)1; - ripng_aggregate_add (&p); + ripng_aggregate_add(&p); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ripng_aggregate_address, @@ -2361,31 +2306,30 @@ DEFUN (no_ripng_aggregate_address, "Delete aggregate RIPng route announcement\n" "Aggregate network") { - int idx_ipv6_prefixlen = 2; - int ret; - struct prefix p; - struct route_node *rn; + int idx_ipv6_prefixlen = 2; + int ret; + struct prefix p; + struct route_node *rn; - ret = str2prefix_ipv6 (argv[idx_ipv6_prefixlen]->arg, (struct prefix_ipv6 *) &p); - if (ret <= 0) - { - vty_out (vty, "Malformed address%s", VTY_NEWLINE); - return CMD_WARNING; - } + ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, + (struct prefix_ipv6 *)&p); + if (ret <= 0) { + vty_out(vty, "Malformed address%s", VTY_NEWLINE); + return CMD_WARNING; + } - rn = route_node_lookup (ripng->aggregate, &p); - if (! rn) - { - vty_out (vty, "Can't find aggregate route.%s", VTY_NEWLINE); - return CMD_WARNING; - } - route_unlock_node (rn); - rn->info = NULL; - route_unlock_node (rn); + rn = route_node_lookup(ripng->aggregate, &p); + if (!rn) { + vty_out(vty, "Can't find aggregate route.%s", VTY_NEWLINE); + return CMD_WARNING; + } + route_unlock_node(rn); + rn->info = NULL; + route_unlock_node(rn); - ripng_aggregate_delete (&p); + ripng_aggregate_delete(&p); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ripng_default_metric, @@ -2394,12 +2338,11 @@ DEFUN (ripng_default_metric, "Set a metric of redistribute routes\n" "Default metric\n") { - int idx_number = 1; - if (ripng) - { - ripng->default_metric = atoi (argv[idx_number]->arg); - } - return CMD_SUCCESS; + int idx_number = 1; + if (ripng) { + ripng->default_metric = atoi(argv[idx_number]->arg); + } + return CMD_SUCCESS; } DEFUN (no_ripng_default_metric, @@ -2409,11 +2352,10 @@ DEFUN (no_ripng_default_metric, "Set a metric of redistribute routes\n" "Default metric\n") { - if (ripng) - { - ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; - } - return CMD_SUCCESS; + if (ripng) { + ripng->default_metric = RIPNG_DEFAULT_METRIC_DEFAULT; + } + return CMD_SUCCESS; } @@ -2529,26 +2471,29 @@ DEFUN (ripng_timers, "Routing information timeout timer. Default is 180.\n" "Garbage collection timer. Default is 120.\n") { - int idx_number = 2; - int idx_number_2 = 3; - int idx_number_3 = 4; - unsigned long update; - unsigned long timeout; - unsigned long garbage; + int idx_number = 2; + int idx_number_2 = 3; + int idx_number_3 = 4; + unsigned long update; + unsigned long timeout; + unsigned long garbage; - VTY_GET_INTEGER_RANGE("update timer", update, argv[idx_number]->arg, 0, 65535); - VTY_GET_INTEGER_RANGE("timeout timer", timeout, argv[idx_number_2]->arg, 0, 65535); - VTY_GET_INTEGER_RANGE("garbage timer", garbage, argv[idx_number_3]->arg, 0, 65535); + VTY_GET_INTEGER_RANGE("update timer", update, argv[idx_number]->arg, 0, + 65535); + VTY_GET_INTEGER_RANGE("timeout timer", timeout, argv[idx_number_2]->arg, + 0, 65535); + VTY_GET_INTEGER_RANGE("garbage timer", garbage, argv[idx_number_3]->arg, + 0, 65535); - /* Set each timer value. */ - ripng->update_time = update; - ripng->timeout_time = timeout; - ripng->garbage_time = garbage; + /* Set each timer value. */ + ripng->update_time = update; + ripng->timeout_time = timeout; + ripng->garbage_time = garbage; - /* Reset update timer thread. */ - ripng_event (RIPNG_UPDATE_EVENT, 0); + /* Reset update timer thread. */ + ripng_event(RIPNG_UPDATE_EVENT, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ripng_timers, @@ -2561,15 +2506,15 @@ DEFUN (no_ripng_timers, "Routing information timeout timer. Default is 180.\n" "Garbage collection timer. Default is 120.\n") { - /* Set each timer value to the default. */ - ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; - ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; - ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; + /* Set each timer value to the default. */ + ripng->update_time = RIPNG_UPDATE_TIMER_DEFAULT; + ripng->timeout_time = RIPNG_TIMEOUT_TIMER_DEFAULT; + ripng->garbage_time = RIPNG_GARBAGE_TIMER_DEFAULT; - /* Reset update timer thread. */ - ripng_event (RIPNG_UPDATE_EVENT, 0); + /* Reset update timer thread. */ + ripng_event(RIPNG_UPDATE_EVENT, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } #if 0 @@ -2608,16 +2553,17 @@ DEFUN (ripng_default_information_originate, "Default route information\n" "Distribute default route\n") { - struct prefix_ipv6 p; + struct prefix_ipv6 p; - if (! ripng ->default_information) { - ripng->default_information = 1; + if (!ripng->default_information) { + ripng->default_information = 1; - str2prefix_ipv6 ("::/0", &p); - ripng_redistribute_add (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0); - } + str2prefix_ipv6("::/0", &p); + ripng_redistribute_add(ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, + &p, 0, NULL, 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ripng_default_information_originate, @@ -2627,56 +2573,55 @@ DEFUN (no_ripng_default_information_originate, "Default route information\n" "Distribute default route\n") { - struct prefix_ipv6 p; + struct prefix_ipv6 p; - if (ripng->default_information) { - ripng->default_information = 0; + if (ripng->default_information) { + ripng->default_information = 0; - str2prefix_ipv6 ("::/0", &p); - ripng_redistribute_delete (ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_DEFAULT, &p, 0); - } + str2prefix_ipv6("::/0", &p); + ripng_redistribute_delete(ZEBRA_ROUTE_RIPNG, + RIPNG_ROUTE_DEFAULT, &p, 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Update ECMP routes to zebra when ECMP is disabled. */ -static void -ripng_ecmp_disable (void) -{ - struct route_node *rp; - struct ripng_info *rinfo, *tmp_rinfo; - struct list *list; - struct listnode *node, *nextnode; - - if (!ripng) - return; - - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL && listcount (list) > 1) - { - rinfo = listgetdata (listhead (list)); - if (!ripng_route_rte (rinfo)) - continue; - - /* Drop all other entries, except the first one. */ - for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) - if (tmp_rinfo != rinfo) - { - RIPNG_TIMER_OFF (tmp_rinfo->t_timeout); - RIPNG_TIMER_OFF (tmp_rinfo->t_garbage_collect); - list_delete_node (list, node); - ripng_info_free (tmp_rinfo); - } - - /* Update zebra. */ - ripng_zebra_ipv6_add (rp); - - /* Set the route change flag. */ - SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); - - /* Signal the output process to trigger an update. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - } +static void ripng_ecmp_disable(void) +{ + struct route_node *rp; + struct ripng_info *rinfo, *tmp_rinfo; + struct list *list; + struct listnode *node, *nextnode; + + if (!ripng) + return; + + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL && listcount(list) > 1) { + rinfo = listgetdata(listhead(list)); + if (!ripng_route_rte(rinfo)) + continue; + + /* Drop all other entries, except the first one. */ + for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) { + RIPNG_TIMER_OFF(tmp_rinfo->t_timeout); + RIPNG_TIMER_OFF( + tmp_rinfo->t_garbage_collect); + list_delete_node(list, node); + ripng_info_free(tmp_rinfo); + } + + /* Update zebra. */ + ripng_zebra_ipv6_add(rp); + + /* Set the route change flag. */ + SET_FLAG(rinfo->flags, RIPNG_RTF_CHANGED); + + /* Signal the output process to trigger an update. */ + ripng_event(RIPNG_TRIGGERED_UPDATE, 0); + } } DEFUN (ripng_allow_ecmp, @@ -2684,15 +2629,14 @@ DEFUN (ripng_allow_ecmp, "allow-ecmp", "Allow Equal Cost MultiPath\n") { - if (ripng->ecmp) - { - vty_out (vty, "ECMP is already enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } + if (ripng->ecmp) { + vty_out(vty, "ECMP is already enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } - ripng->ecmp = 1; - zlog_info ("ECMP is enabled."); - return CMD_SUCCESS; + ripng->ecmp = 1; + zlog_info("ECMP is enabled."); + return CMD_SUCCESS; } DEFUN (no_ripng_allow_ecmp, @@ -2701,79 +2645,74 @@ DEFUN (no_ripng_allow_ecmp, NO_STR "Allow Equal Cost MultiPath\n") { - if (!ripng->ecmp) - { - vty_out (vty, "ECMP is already disabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } + if (!ripng->ecmp) { + vty_out(vty, "ECMP is already disabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } - ripng->ecmp = 0; - zlog_info ("ECMP is disabled."); - ripng_ecmp_disable (); - return CMD_SUCCESS; + ripng->ecmp = 0; + zlog_info("ECMP is disabled."); + ripng_ecmp_disable(); + return CMD_SUCCESS; } /* RIPng configuration write function. */ -static int -ripng_config_write (struct vty *vty) +static int ripng_config_write(struct vty *vty) { - int ripng_network_write (struct vty *, int); - void ripng_redistribute_write (struct vty *, int); - int write = 0; - struct route_node *rp; + int ripng_network_write(struct vty *, int); + void ripng_redistribute_write(struct vty *, int); + int write = 0; + struct route_node *rp; - if (ripng) - { + if (ripng) { - /* RIPng router. */ - vty_out (vty, "router ripng%s", VTY_NEWLINE); - - if (ripng->default_information) - vty_out (vty, " default-information originate%s", VTY_NEWLINE); - - ripng_network_write (vty, 1); - - /* RIPng default metric configuration */ - if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT) - vty_out (vty, " default-metric %d%s", - ripng->default_metric, VTY_NEWLINE); - - ripng_redistribute_write (vty, 1); - - /* RIP offset-list configuration. */ - config_write_ripng_offset_list (vty); - - /* RIPng aggregate routes. */ - for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp)) - if (rp->info != NULL) - vty_out (vty, " aggregate-address %s/%d%s", - inet6_ntoa (rp->p.u.prefix6), - rp->p.prefixlen, - - VTY_NEWLINE); - - /* ECMP configuration. */ - if (ripng->ecmp) - vty_out (vty, " allow-ecmp%s", VTY_NEWLINE); - - /* RIPng static routes. */ - for (rp = route_top (ripng->route); rp; rp = route_next (rp)) - if (rp->info != NULL) - vty_out (vty, " route %s/%d%s", inet6_ntoa (rp->p.u.prefix6), - rp->p.prefixlen, - VTY_NEWLINE); - - /* RIPng timers configuration. */ - if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT || - ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT || - ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT) - { - vty_out (vty, " timers basic %ld %ld %ld%s", - ripng->update_time, - ripng->timeout_time, - ripng->garbage_time, - VTY_NEWLINE); - } + /* RIPng router. */ + vty_out(vty, "router ripng%s", VTY_NEWLINE); + + if (ripng->default_information) + vty_out(vty, " default-information originate%s", + VTY_NEWLINE); + + ripng_network_write(vty, 1); + + /* RIPng default metric configuration */ + if (ripng->default_metric != RIPNG_DEFAULT_METRIC_DEFAULT) + vty_out(vty, " default-metric %d%s", + ripng->default_metric, VTY_NEWLINE); + + ripng_redistribute_write(vty, 1); + + /* RIP offset-list configuration. */ + config_write_ripng_offset_list(vty); + + /* RIPng aggregate routes. */ + for (rp = route_top(ripng->aggregate); rp; rp = route_next(rp)) + if (rp->info != NULL) + vty_out(vty, " aggregate-address %s/%d%s", + inet6_ntoa(rp->p.u.prefix6), + rp->p.prefixlen, + + VTY_NEWLINE); + + /* ECMP configuration. */ + if (ripng->ecmp) + vty_out(vty, " allow-ecmp%s", VTY_NEWLINE); + + /* RIPng static routes. */ + for (rp = route_top(ripng->route); rp; rp = route_next(rp)) + if (rp->info != NULL) + vty_out(vty, " route %s/%d%s", + inet6_ntoa(rp->p.u.prefix6), + rp->p.prefixlen, VTY_NEWLINE); + + /* RIPng timers configuration. */ + if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT + || ripng->timeout_time != RIPNG_TIMEOUT_TIMER_DEFAULT + || ripng->garbage_time != RIPNG_GARBAGE_TIMER_DEFAULT) { + vty_out(vty, " timers basic %ld %ld %ld%s", + ripng->update_time, ripng->timeout_time, + ripng->garbage_time, VTY_NEWLINE); + } #if 0 if (ripng->update_time != RIPNG_UPDATE_TIMER_DEFAULT) vty_out (vty, " update-timer %d%s", ripng->update_time, @@ -2786,326 +2725,301 @@ ripng_config_write (struct vty *vty) VTY_NEWLINE); #endif /* 0 */ - write += config_write_distribute (vty); + write += config_write_distribute(vty); - write += config_write_if_rmap (vty); + write += config_write_if_rmap(vty); - write++; - } - return write; + write++; + } + return write; } /* RIPng node structure. */ -static struct cmd_node cmd_ripng_node = -{ - RIPNG_NODE, - "%s(config-router)# ", - 1, +static struct cmd_node cmd_ripng_node = { + RIPNG_NODE, "%s(config-router)# ", 1, }; -static void -ripng_distribute_update (struct distribute *dist) -{ - struct interface *ifp; - struct ripng_interface *ri; - struct access_list *alist; - struct prefix_list *plist; - - if (! dist->ifname) - return; - - ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; - - ri = ifp->info; - - if (dist->list[DISTRIBUTE_V6_IN]) - { - alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_V6_IN]); - if (alist) - ri->list[RIPNG_FILTER_IN] = alist; - else - ri->list[RIPNG_FILTER_IN] = NULL; - } - else - ri->list[RIPNG_FILTER_IN] = NULL; - - if (dist->list[DISTRIBUTE_V6_OUT]) - { - alist = access_list_lookup (AFI_IP6, dist->list[DISTRIBUTE_V6_OUT]); - if (alist) - ri->list[RIPNG_FILTER_OUT] = alist; - else - ri->list[RIPNG_FILTER_OUT] = NULL; - } - else - ri->list[RIPNG_FILTER_OUT] = NULL; - - if (dist->prefix[DISTRIBUTE_V6_IN]) - { - plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_V6_IN]); - if (plist) - ri->prefix[RIPNG_FILTER_IN] = plist; - else - ri->prefix[RIPNG_FILTER_IN] = NULL; - } - else - ri->prefix[RIPNG_FILTER_IN] = NULL; - - if (dist->prefix[DISTRIBUTE_V6_OUT]) - { - plist = prefix_list_lookup (AFI_IP6, dist->prefix[DISTRIBUTE_V6_OUT]); - if (plist) - ri->prefix[RIPNG_FILTER_OUT] = plist; - else - ri->prefix[RIPNG_FILTER_OUT] = NULL; - } - else - ri->prefix[RIPNG_FILTER_OUT] = NULL; -} - -void -ripng_distribute_update_interface (struct interface *ifp) -{ - struct distribute *dist; - - dist = distribute_lookup (ifp->name); - if (dist) - ripng_distribute_update (dist); +static void ripng_distribute_update(struct distribute *dist) +{ + struct interface *ifp; + struct ripng_interface *ri; + struct access_list *alist; + struct prefix_list *plist; + + if (!dist->ifname) + return; + + ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; + + ri = ifp->info; + + if (dist->list[DISTRIBUTE_V6_IN]) { + alist = access_list_lookup(AFI_IP6, + dist->list[DISTRIBUTE_V6_IN]); + if (alist) + ri->list[RIPNG_FILTER_IN] = alist; + else + ri->list[RIPNG_FILTER_IN] = NULL; + } else + ri->list[RIPNG_FILTER_IN] = NULL; + + if (dist->list[DISTRIBUTE_V6_OUT]) { + alist = access_list_lookup(AFI_IP6, + dist->list[DISTRIBUTE_V6_OUT]); + if (alist) + ri->list[RIPNG_FILTER_OUT] = alist; + else + ri->list[RIPNG_FILTER_OUT] = NULL; + } else + ri->list[RIPNG_FILTER_OUT] = NULL; + + if (dist->prefix[DISTRIBUTE_V6_IN]) { + plist = prefix_list_lookup(AFI_IP6, + dist->prefix[DISTRIBUTE_V6_IN]); + if (plist) + ri->prefix[RIPNG_FILTER_IN] = plist; + else + ri->prefix[RIPNG_FILTER_IN] = NULL; + } else + ri->prefix[RIPNG_FILTER_IN] = NULL; + + if (dist->prefix[DISTRIBUTE_V6_OUT]) { + plist = prefix_list_lookup(AFI_IP6, + dist->prefix[DISTRIBUTE_V6_OUT]); + if (plist) + ri->prefix[RIPNG_FILTER_OUT] = plist; + else + ri->prefix[RIPNG_FILTER_OUT] = NULL; + } else + ri->prefix[RIPNG_FILTER_OUT] = NULL; +} + +void ripng_distribute_update_interface(struct interface *ifp) +{ + struct distribute *dist; + + dist = distribute_lookup(ifp->name); + if (dist) + ripng_distribute_update(dist); } /* Update all interface's distribute list. */ -static void -ripng_distribute_update_all (struct prefix_list *notused) +static void ripng_distribute_update_all(struct prefix_list *notused) { - struct interface *ifp; - struct listnode *node; + struct interface *ifp; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - ripng_distribute_update_interface (ifp); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + ripng_distribute_update_interface(ifp); } -static void -ripng_distribute_update_all_wrapper (struct access_list *notused) +static void ripng_distribute_update_all_wrapper(struct access_list *notused) { - ripng_distribute_update_all(NULL); + ripng_distribute_update_all(NULL); } /* delete all the added ripng routes. */ -void -ripng_clean() -{ - int i; - struct route_node *rp; - struct ripng_info *rinfo; - struct ripng_aggregate *aggregate; - struct list *list = NULL; - struct listnode *listnode = NULL; - - if (ripng) { - /* Clear RIPng routes */ - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - { - if ((list = rp->info) != NULL) - { - rinfo = listgetdata (listhead (list)); - if (ripng_route_rte (rinfo)) - ripng_zebra_ipv6_delete (rp); - - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - ripng_info_free (rinfo); - } - list_delete (list); - rp->info = NULL; - route_unlock_node (rp); - } - - if ((aggregate = rp->aggregate) != NULL) - { - ripng_aggregate_free (aggregate); - rp->aggregate = NULL; - route_unlock_node (rp); - } - } +void ripng_clean() +{ + int i; + struct route_node *rp; + struct ripng_info *rinfo; + struct ripng_aggregate *aggregate; + struct list *list = NULL; + struct listnode *listnode = NULL; + + if (ripng) { + /* Clear RIPng routes */ + for (rp = route_top(ripng->table); rp; rp = route_next(rp)) { + if ((list = rp->info) != NULL) { + rinfo = listgetdata(listhead(list)); + if (ripng_route_rte(rinfo)) + ripng_zebra_ipv6_delete(rp); + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + rinfo)) { + RIPNG_TIMER_OFF(rinfo->t_timeout); + RIPNG_TIMER_OFF( + rinfo->t_garbage_collect); + ripng_info_free(rinfo); + } + list_delete(list); + rp->info = NULL; + route_unlock_node(rp); + } + + if ((aggregate = rp->aggregate) != NULL) { + ripng_aggregate_free(aggregate); + rp->aggregate = NULL; + route_unlock_node(rp); + } + } - /* Cancel the RIPng timers */ - RIPNG_TIMER_OFF (ripng->t_update); - RIPNG_TIMER_OFF (ripng->t_triggered_update); - RIPNG_TIMER_OFF (ripng->t_triggered_interval); + /* Cancel the RIPng timers */ + RIPNG_TIMER_OFF(ripng->t_update); + RIPNG_TIMER_OFF(ripng->t_triggered_update); + RIPNG_TIMER_OFF(ripng->t_triggered_interval); - /* Cancel the read thread */ - if (ripng->t_read) { - thread_cancel (ripng->t_read); - ripng->t_read = NULL; - } + /* Cancel the read thread */ + if (ripng->t_read) { + thread_cancel(ripng->t_read); + ripng->t_read = NULL; + } - /* Close the RIPng socket */ - if (ripng->sock >= 0) { - close(ripng->sock); - ripng->sock = -1; - } + /* Close the RIPng socket */ + if (ripng->sock >= 0) { + close(ripng->sock); + ripng->sock = -1; + } - /* Static RIPng route configuration. */ - for (rp = route_top (ripng->route); rp; rp = route_next (rp)) - if (rp->info) { - rp->info = NULL; - route_unlock_node (rp); - } + /* Static RIPng route configuration. */ + for (rp = route_top(ripng->route); rp; rp = route_next(rp)) + if (rp->info) { + rp->info = NULL; + route_unlock_node(rp); + } - /* RIPng aggregated prefixes */ - for (rp = route_top (ripng->aggregate); rp; rp = route_next (rp)) - if (rp->info) { - rp->info = NULL; - route_unlock_node (rp); - } + /* RIPng aggregated prefixes */ + for (rp = route_top(ripng->aggregate); rp; rp = route_next(rp)) + if (rp->info) { + rp->info = NULL; + route_unlock_node(rp); + } - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (ripng->route_map[i].name) - free (ripng->route_map[i].name); + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (ripng->route_map[i].name) + free(ripng->route_map[i].name); - XFREE (MTYPE_ROUTE_TABLE, ripng->table); - XFREE (MTYPE_ROUTE_TABLE, ripng->route); - XFREE (MTYPE_ROUTE_TABLE, ripng->aggregate); + XFREE(MTYPE_ROUTE_TABLE, ripng->table); + XFREE(MTYPE_ROUTE_TABLE, ripng->route); + XFREE(MTYPE_ROUTE_TABLE, ripng->aggregate); - stream_free (ripng->ibuf); - stream_free (ripng->obuf); + stream_free(ripng->ibuf); + stream_free(ripng->obuf); - XFREE (MTYPE_RIPNG, ripng); - ripng = NULL; - } /* if (ripng) */ + XFREE(MTYPE_RIPNG, ripng); + ripng = NULL; + } /* if (ripng) */ - ripng_clean_network(); - ripng_passive_interface_clean (); - ripng_offset_clean (); - ripng_interface_clean (); - ripng_redistribute_clean (); + ripng_clean_network(); + ripng_passive_interface_clean(); + ripng_offset_clean(); + ripng_interface_clean(); + ripng_redistribute_clean(); } /* Reset all values to the default settings. */ -void -ripng_reset () +void ripng_reset() { - /* Call ripd related reset functions. */ - ripng_debug_reset (); - ripng_route_map_reset (); + /* Call ripd related reset functions. */ + ripng_debug_reset(); + ripng_route_map_reset(); - /* Call library reset functions. */ - vty_reset (); - access_list_reset (); - prefix_list_reset (); + /* Call library reset functions. */ + vty_reset(); + access_list_reset(); + prefix_list_reset(); - distribute_list_reset (); + distribute_list_reset(); - ripng_interface_reset (); + ripng_interface_reset(); - ripng_zclient_reset (); + ripng_zclient_reset(); } -static void -ripng_if_rmap_update (struct if_rmap *if_rmap) +static void ripng_if_rmap_update(struct if_rmap *if_rmap) { - struct interface *ifp; - struct ripng_interface *ri; - struct route_map *rmap; + struct interface *ifp; + struct ripng_interface *ri; + struct route_map *rmap; - ifp = if_lookup_by_name (if_rmap->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; + ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; - ri = ifp->info; + ri = ifp->info; - if (if_rmap->routemap[IF_RMAP_IN]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]); - if (rmap) - ri->routemap[IF_RMAP_IN] = rmap; - else - ri->routemap[IF_RMAP_IN] = NULL; - } - else - ri->routemap[RIPNG_FILTER_IN] = NULL; + if (if_rmap->routemap[IF_RMAP_IN]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]); + if (rmap) + ri->routemap[IF_RMAP_IN] = rmap; + else + ri->routemap[IF_RMAP_IN] = NULL; + } else + ri->routemap[RIPNG_FILTER_IN] = NULL; - if (if_rmap->routemap[IF_RMAP_OUT]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]); - if (rmap) - ri->routemap[IF_RMAP_OUT] = rmap; - else - ri->routemap[IF_RMAP_OUT] = NULL; - } - else - ri->routemap[RIPNG_FILTER_OUT] = NULL; + if (if_rmap->routemap[IF_RMAP_OUT]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]); + if (rmap) + ri->routemap[IF_RMAP_OUT] = rmap; + else + ri->routemap[IF_RMAP_OUT] = NULL; + } else + ri->routemap[RIPNG_FILTER_OUT] = NULL; } -void -ripng_if_rmap_update_interface (struct interface *ifp) +void ripng_if_rmap_update_interface(struct interface *ifp) { - struct if_rmap *if_rmap; + struct if_rmap *if_rmap; - if_rmap = if_rmap_lookup (ifp->name); - if (if_rmap) - ripng_if_rmap_update (if_rmap); + if_rmap = if_rmap_lookup(ifp->name); + if (if_rmap) + ripng_if_rmap_update(if_rmap); } -static void -ripng_routemap_update_redistribute (void) +static void ripng_routemap_update_redistribute(void) { - int i; + int i; - if (ripng) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (ripng->route_map[i].name) - ripng->route_map[i].map = - route_map_lookup_by_name (ripng->route_map[i].name); + if (ripng) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (ripng->route_map[i].name) + ripng->route_map[i].map = + route_map_lookup_by_name( + ripng->route_map[i].name); + } } - } } -static void -ripng_routemap_update (const char *unused) +static void ripng_routemap_update(const char *unused) { - struct interface *ifp; - struct listnode *node; + struct interface *ifp; + struct listnode *node; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - ripng_if_rmap_update_interface (ifp); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + ripng_if_rmap_update_interface(ifp); - ripng_routemap_update_redistribute (); + ripng_routemap_update_redistribute(); } /* Initialize ripng structure and set commands. */ -void -ripng_init () +void ripng_init() { - /* Install RIPNG_NODE. */ - install_node (&cmd_ripng_node, ripng_config_write); + /* Install RIPNG_NODE. */ + install_node(&cmd_ripng_node, ripng_config_write); - /* Install ripng commands. */ - install_element (VIEW_NODE, &show_ipv6_ripng_cmd); - install_element (VIEW_NODE, &show_ipv6_ripng_status_cmd); + /* Install ripng commands. */ + install_element(VIEW_NODE, &show_ipv6_ripng_cmd); + install_element(VIEW_NODE, &show_ipv6_ripng_status_cmd); - install_element (ENABLE_NODE, &clear_ipv6_rip_cmd); + install_element(ENABLE_NODE, &clear_ipv6_rip_cmd); - install_element (CONFIG_NODE, &router_ripng_cmd); - install_element (CONFIG_NODE, &no_router_ripng_cmd); + install_element(CONFIG_NODE, &router_ripng_cmd); + install_element(CONFIG_NODE, &no_router_ripng_cmd); - install_default (RIPNG_NODE); - install_element (RIPNG_NODE, &ripng_route_cmd); - install_element (RIPNG_NODE, &no_ripng_route_cmd); - install_element (RIPNG_NODE, &ripng_aggregate_address_cmd); - install_element (RIPNG_NODE, &no_ripng_aggregate_address_cmd); + install_default(RIPNG_NODE); + install_element(RIPNG_NODE, &ripng_route_cmd); + install_element(RIPNG_NODE, &no_ripng_route_cmd); + install_element(RIPNG_NODE, &ripng_aggregate_address_cmd); + install_element(RIPNG_NODE, &no_ripng_aggregate_address_cmd); - install_element (RIPNG_NODE, &ripng_default_metric_cmd); - install_element (RIPNG_NODE, &no_ripng_default_metric_cmd); + install_element(RIPNG_NODE, &ripng_default_metric_cmd); + install_element(RIPNG_NODE, &no_ripng_default_metric_cmd); - install_element (RIPNG_NODE, &ripng_timers_cmd); - install_element (RIPNG_NODE, &no_ripng_timers_cmd); + install_element(RIPNG_NODE, &ripng_timers_cmd); + install_element(RIPNG_NODE, &no_ripng_timers_cmd); #if 0 install_element (VIEW_NODE, &show_ipv6_protocols_cmd); install_element (RIPNG_NODE, &ripng_update_timer_cmd); @@ -3116,38 +3030,39 @@ ripng_init () install_element (RIPNG_NODE, &no_ripng_garbage_timer_cmd); #endif /* 0 */ - install_element (RIPNG_NODE, &ripng_default_information_originate_cmd); - install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd); + install_element(RIPNG_NODE, &ripng_default_information_originate_cmd); + install_element(RIPNG_NODE, + &no_ripng_default_information_originate_cmd); - install_element (RIPNG_NODE, &ripng_allow_ecmp_cmd); - install_element (RIPNG_NODE, &no_ripng_allow_ecmp_cmd); + install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd); + install_element(RIPNG_NODE, &no_ripng_allow_ecmp_cmd); - ripng_if_init (); - ripng_debug_init (); + ripng_if_init(); + ripng_debug_init(); - /* Access list install. */ - access_list_init (); - access_list_add_hook (ripng_distribute_update_all_wrapper); - access_list_delete_hook (ripng_distribute_update_all_wrapper); + /* Access list install. */ + access_list_init(); + access_list_add_hook(ripng_distribute_update_all_wrapper); + access_list_delete_hook(ripng_distribute_update_all_wrapper); - /* Prefix list initialize.*/ - prefix_list_init (); - prefix_list_add_hook (ripng_distribute_update_all); - prefix_list_delete_hook (ripng_distribute_update_all); + /* Prefix list initialize.*/ + prefix_list_init(); + prefix_list_add_hook(ripng_distribute_update_all); + prefix_list_delete_hook(ripng_distribute_update_all); - /* Distribute list install. */ - distribute_list_init (RIPNG_NODE); - distribute_list_add_hook (ripng_distribute_update); - distribute_list_delete_hook (ripng_distribute_update); + /* Distribute list install. */ + distribute_list_init(RIPNG_NODE); + distribute_list_add_hook(ripng_distribute_update); + distribute_list_delete_hook(ripng_distribute_update); - /* Route-map for interface. */ - ripng_route_map_init (); - ripng_offset_init (); + /* Route-map for interface. */ + ripng_route_map_init(); + ripng_offset_init(); - route_map_add_hook (ripng_routemap_update); - route_map_delete_hook (ripng_routemap_update); + route_map_add_hook(ripng_routemap_update); + route_map_delete_hook(ripng_routemap_update); - if_rmap_init (RIPNG_NODE); - if_rmap_hook_add (ripng_if_rmap_update); - if_rmap_hook_delete (ripng_if_rmap_update); + if_rmap_init(RIPNG_NODE); + if_rmap_hook_add(ripng_if_rmap_update); + if_rmap_hook_delete(ripng_if_rmap_update); } |
