~ubuntu-branches/ubuntu/breezy/quagga/breezy-security

« back to all changes in this revision

Viewing changes to ripngd/ripngd.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-05-20 13:16:12 UTC
  • Revision ID: james.westby@ubuntu.com-20050520131612-pr6paalox60o3x3n
Tags: upstream-0.99.1
ImportĀ upstreamĀ versionĀ 0.99.1

Show diffs side-by-side

added added

removed removed

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