Annotation of embedaddon/quagga/ripngd/ripngd.c, revision 1.1.1.3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>