1/*
2 * Copyright (C) 1999 Yasuhiro Ohara
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
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include "ospf6d.h"
23
24#include "if.h"
25#include "log.h"
26#include "command.h"
27
28#include "ospf6_lsdb.h"
29
30#include "ospf6_top.h"
31#include "ospf6_area.h"
32#include "ospf6_interface.h"
33
34char *ospf6_interface_state_string[] =
35{
36  "None", "Down", "Loopback", "Waiting", "PointToPoint",
37  "DROther", "BDR", "DR", NULL
38};
39
40static void
41ospf6_interface_foreach_neighbor (struct ospf6_interface *o6i,
42                                  void *arg, int val,
43                                  void (*func) (void *, int, void *))
44{
45  listnode node;
46  struct ospf6_neighbor *nei;
47
48  for (node = listhead (o6i->neighbor_list); node; nextnode (node))
49    {
50      nei = (struct ospf6_neighbor *) getdata (node);
51      (*func) (arg, val, nei);
52    }
53}
54
55static int
56ospf6_interface_maxage_remover (struct thread *t)
57{
58  int count;
59  struct ospf6_interface *o6i = (struct ospf6_interface *) THREAD_ARG (t);
60
61  o6i->maxage_remover = (struct thread *) NULL;
62
63  count = 0;
64  o6i->foreach_nei (o6i, &count, NBS_EXCHANGE, ospf6_count_state);
65  o6i->foreach_nei (o6i, &count, NBS_LOADING, ospf6_count_state);
66  if (count != 0)
67    return 0;
68
69  ospf6_lsdb_remove_maxage (o6i->lsdb);
70  return 0;
71}
72
73void
74ospf6_interface_schedule_maxage_remover (void *arg, int val, void *obj)
75{
76  struct ospf6_interface *o6i = (struct ospf6_interface *) obj;
77
78  if (o6i->maxage_remover != NULL)
79    return;
80
81  o6i->maxage_remover =
82    thread_add_event (master, ospf6_interface_maxage_remover, o6i, 0);
83}
84
85/* Create new ospf6 interface structure */
86struct ospf6_interface *
87ospf6_interface_create (struct interface *ifp)
88{
89  struct ospf6_interface *o6i;
90
91  o6i = (struct ospf6_interface *)
92    XMALLOC (MTYPE_OSPF6_IF, sizeof (struct ospf6_interface));
93
94  if (o6i)
95    memset (o6i, 0, sizeof (struct ospf6_interface));
96  else
97    {
98      zlog_err ("Can't malloc ospf6_interface for ifindex %d", ifp->ifindex);
99      return (struct ospf6_interface *) NULL;
100    }
101
102  o6i->instance_id = 0;
103  o6i->if_id = ifp->ifindex;
104  o6i->lladdr = (struct in6_addr *) NULL;
105  o6i->area = (struct ospf6_area *) NULL;
106  o6i->state = IFS_DOWN;
107  o6i->flag = 0;
108  o6i->neighbor_list = list_new ();
109
110  o6i->ack_list = ospf6_lsdb_create ();
111  o6i->lsdb = ospf6_lsdb_create ();
112
113  o6i->transdelay = 1;
114  o6i->priority = 1;
115  o6i->hello_interval = 10;
116  o6i->dead_interval = 40;
117  o6i->rxmt_interval = 5;
118  o6i->cost = 1;
119  o6i->ifmtu = 1280;
120
121  o6i->foreach_nei = ospf6_interface_foreach_neighbor;
122
123  /* link both */
124  o6i->interface = ifp;
125  ifp->info = o6i;
126
127  CALL_ADD_HOOK (&interface_hook, o6i);
128
129  return o6i;
130}
131
132void
133ospf6_interface_delete (struct ospf6_interface *o6i)
134{
135  listnode n;
136  struct ospf6_neighbor *o6n;
137
138  CALL_REMOVE_HOOK (&interface_hook, o6i);
139
140  for (n = listhead (o6i->neighbor_list); n; nextnode (n))
141    {
142      o6n = (struct ospf6_neighbor *) getdata (n);
143      ospf6_neighbor_delete (o6n);
144    }
145  list_delete (o6i->neighbor_list);
146
147  if (o6i->thread_send_hello)
148    {
149      thread_cancel (o6i->thread_send_hello);
150      o6i->thread_send_hello = NULL;
151    }
152  if (o6i->thread_send_lsack_delayed)
153    {
154      thread_cancel (o6i->thread_send_lsack_delayed);
155      o6i->thread_send_lsack_delayed = NULL;
156    }
157
158  ospf6_lsdb_delete (o6i->ack_list);
159  ospf6_lsdb_remove_all (o6i->lsdb);
160  ospf6_lsdb_delete (o6i->lsdb);
161
162  /* cut link */
163  o6i->interface->info = NULL;
164
165  /* plist_name */
166  if (o6i->plist_name)
167    XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name);
168
169  XFREE (MTYPE_OSPF6_IF, o6i);
170}
171
172static struct in6_addr *
173ospf6_interface_update_linklocal_address (struct interface *ifp)
174{
175  listnode n;
176  struct connected *c;
177  struct in6_addr *l = (struct in6_addr *) NULL;
178
179  /* for each connected address */
180  for (n = listhead (ifp->connected); n; nextnode (n))
181    {
182      c = (struct connected *) getdata (n);
183
184      /* if family not AF_INET6, ignore */
185      if (c->address->family != AF_INET6)
186        continue;
187
188      /* linklocal scope check */
189      if (IN6_IS_ADDR_LINKLOCAL (&c->address->u.prefix6))
190        l = &c->address->u.prefix6;
191    }
192  return l;
193}
194
195void
196ospf6_interface_if_add (struct interface *ifp)
197{
198  struct ospf6_interface *o6i;
199
200  o6i = (struct ospf6_interface *) ifp->info;
201  if (!o6i)
202    return;
203
204  o6i->if_id = ifp->ifindex;
205
206  ospf6_interface_address_update (ifp);
207
208  /* interface start */
209  if (o6i->area)
210    thread_add_event (master, interface_up, o6i, 0);
211}
212
213void
214ospf6_interface_if_del (struct interface *ifp)
215{
216  struct ospf6_interface *o6i;
217
218  o6i = (struct ospf6_interface *) ifp->info;
219  if (!o6i)
220    return;
221
222  /* interface stop */
223  if (o6i->area)
224    thread_execute (master, interface_down, o6i, 0);
225
226  listnode_delete (o6i->area->if_list, o6i);
227  o6i->area = (struct ospf6_area *) NULL;
228
229  /* cut link */
230  o6i->interface = NULL;
231  ifp->info = NULL;
232
233  ospf6_interface_delete (o6i);
234}
235
236void
237ospf6_interface_state_update (struct interface *ifp)
238{
239  struct ospf6_interface *o6i;
240
241  o6i = (struct ospf6_interface *) ifp->info;
242  if (! o6i)
243    return;
244  if (! o6i->area)
245    return;
246
247  if (if_is_up (ifp))
248    thread_add_event (master, interface_up, o6i, 0);
249  else
250    thread_add_event (master, interface_down, o6i, 0);
251
252  return;
253}
254
255void
256ospf6_interface_address_update (struct interface *ifp)
257{
258  struct ospf6_interface *o6i;
259
260  o6i = (struct ospf6_interface *) ifp->info;
261  if (! o6i)
262    return;
263
264  /* reset linklocal pointer */
265  o6i->lladdr = ospf6_interface_update_linklocal_address (ifp);
266
267  /* if area is null, can't make link-lsa */
268  if (! o6i->area)
269    return;
270
271  /* create new Link-LSA */
272  CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
273
274  CALL_CHANGE_HOOK (&interface_hook, o6i);
275}
276
277struct ospf6_interface *
278ospf6_interface_lookup_by_index (int ifindex)
279{
280  struct ospf6_interface *o6i;
281  struct interface *ifp;
282
283  ifp = if_lookup_by_index (ifindex);
284
285  if (! ifp)
286    return (struct ospf6_interface *) NULL;
287
288  o6i = (struct ospf6_interface *) ifp->info;
289  return o6i;
290}
291
292struct ospf6_interface *
293ospf6_interface_lookup_by_name (char *ifname)
294{
295  struct ospf6_interface *o6i;
296  struct interface *ifp;
297
298  ifp = if_lookup_by_name (ifname);
299
300  if (! ifp)
301    return (struct ospf6_interface *) NULL;
302
303  o6i = (struct ospf6_interface *) ifp->info;
304  return o6i;
305}
306
307int
308ospf6_interface_count_neighbor_in_state (u_char state,
309                                         struct ospf6_interface *o6i)
310{
311  listnode n;
312  struct ospf6_neighbor *o6n;
313  int count = 0;
314
315  for (n = listhead (o6i->neighbor_list); n; nextnode (n))
316    {
317      o6n = (struct ospf6_neighbor *) getdata (n);
318      if (o6n->state == state)
319        count++;
320    }
321  return count;
322}
323
324int
325ospf6_interface_count_full_neighbor (struct ospf6_interface *o6i)
326{
327  listnode n;
328  struct ospf6_neighbor *o6n;
329  int count = 0;
330
331  for (n = listhead (o6i->neighbor_list); n; nextnode (n))
332    {
333      o6n = (struct ospf6_neighbor *) getdata (n);
334      if (o6n->state == NBS_FULL)
335        count++;
336    }
337  return count;
338}
339
340int
341ospf6_interface_is_enabled (unsigned int ifindex)
342{
343  struct ospf6_interface *o6i;
344
345  o6i = ospf6_interface_lookup_by_index (ifindex);
346  if (! o6i)
347    return 0;
348
349  if (! o6i->area)
350    return 0;
351
352  if (o6i->state <= IFS_DOWN)
353    return 0;
354
355  return 1;
356}
357
358void
359ospf6_interface_delayed_ack_add (struct ospf6_lsa *lsa,
360                                 struct ospf6_interface *o6i)
361{
362  struct ospf6_lsa *summary;
363  summary = ospf6_lsa_summary_create (lsa->header);
364  ospf6_lsdb_add (summary, o6i->ack_list);
365}
366
367void
368ospf6_interface_delayed_ack_remove (struct ospf6_lsa *lsa,
369                                    struct ospf6_interface *o6i)
370{
371  struct ospf6_lsa *summary;
372  summary = ospf6_lsdb_lookup_lsdb (lsa->header->type, lsa->header->id,
373                                    lsa->header->adv_router, o6i->ack_list);
374  ospf6_lsdb_remove (summary, o6i->ack_list);
375}
376
377/* show specified interface structure */
378int
379ospf6_interface_show (struct vty *vty, struct interface *iface)
380{
381  struct ospf6_interface *ospf6_interface;
382  struct connected *c;
383  struct prefix *p;
384  listnode i;
385  char strbuf[64], dr[32], bdr[32];
386  char *updown[3] = {"down", "up", NULL};
387  char *type;
388
389  /* check physical interface type */
390  if (if_is_loopback (iface))
391    type = "LOOPBACK";
392  else if (if_is_broadcast (iface))
393    type = "BROADCAST";
394  else if (if_is_pointopoint (iface))
395    type = "POINTOPOINT";
396  else
397    type = "UNKNOWN";
398
399  vty_out (vty, "%s is %s, type %s%s",
400           iface->name, updown[if_is_up (iface)], type,
401	   VTY_NEWLINE);
402  vty_out (vty, "  Interface ID: %d%s", iface->ifindex, VTY_NEWLINE);
403
404  if (iface->info == NULL)
405    {
406      vty_out (vty, "   OSPF not enabled on this interface%s", VTY_NEWLINE);
407      return 0;
408    }
409  else
410    ospf6_interface = (struct ospf6_interface *) iface->info;
411
412  vty_out (vty, "  Internet Address:%s", VTY_NEWLINE);
413  for (i = listhead (iface->connected); i; nextnode (i))
414    {
415      c = (struct connected *)getdata (i);
416      p = c->address;
417      prefix2str (p, strbuf, sizeof (strbuf));
418      switch (p->family)
419        {
420        case AF_INET:
421          vty_out (vty, "   inet : %s%s", strbuf,
422		   VTY_NEWLINE);
423          break;
424        case AF_INET6:
425          vty_out (vty, "   inet6: %s%s", strbuf,
426		   VTY_NEWLINE);
427          break;
428        default:
429          vty_out (vty, "   ???  : %s%s", strbuf,
430		   VTY_NEWLINE);
431          break;
432        }
433    }
434
435  if (ospf6_interface->area)
436    {
437      inet_ntop (AF_INET, &ospf6_interface->area->ospf6->router_id,
438                 strbuf, sizeof (strbuf));
439      vty_out (vty, "  Instance ID %d, Router ID %s%s",
440	       ospf6_interface->instance_id, strbuf,
441	       VTY_NEWLINE);
442      inet_ntop (AF_INET, &ospf6_interface->area->area_id,
443                 strbuf, sizeof (strbuf));
444      vty_out (vty, "  Area ID %s, Cost %hu%s", strbuf,
445	       ospf6_interface->cost, VTY_NEWLINE);
446    }
447  else
448    vty_out (vty, "  Not Attached to Area%s", VTY_NEWLINE);
449
450  vty_out (vty, "  State %s, Transmit Delay %d sec, Priority %d%s",
451           ospf6_interface_state_string[ospf6_interface->state],
452           ospf6_interface->transdelay,
453           ospf6_interface->priority,
454	   VTY_NEWLINE);
455  vty_out (vty, "  Timer intervals configured:%s", VTY_NEWLINE);
456  vty_out (vty, "   Hello %d, Dead %d, Retransmit %d%s",
457           ospf6_interface->hello_interval,
458           ospf6_interface->dead_interval,
459           ospf6_interface->rxmt_interval,
460	   VTY_NEWLINE);
461
462  inet_ntop (AF_INET, &ospf6_interface->dr, dr, sizeof (dr));
463  inet_ntop (AF_INET, &ospf6_interface->bdr, bdr, sizeof (bdr));
464  vty_out (vty, "  DR:%s BDR:%s%s", dr, bdr, VTY_NEWLINE);
465
466  vty_out (vty, "  Number of I/F scoped LSAs is %u%s",
467                ospf6_interface->lsdb->count, VTY_NEWLINE);
468  vty_out (vty, "  %-16s %5d times, %-16s %5d times%s",
469                "DRElection", ospf6_interface->ospf6_stat_dr_election,
470                "DelayedLSAck", ospf6_interface->ospf6_stat_delayed_lsack,
471                VTY_NEWLINE);
472
473  return 0;
474}
475
476void
477ospf6_interface_statistics_show (struct vty *vty, struct ospf6_interface *o6i)
478{
479  struct timeval now, uptime;
480  u_long recv_total, send_total;
481  u_long bps_total_avg, bps_tx_avg, bps_rx_avg;
482  int i;
483
484  gettimeofday (&now, (struct timezone *) NULL);
485  ospf6_timeval_sub (&now, &ospf6->starttime, &uptime);
486
487  recv_total = send_total = 0;
488  for (i = 0; i < OSPF6_MESSAGE_TYPE_MAX; i++)
489    {
490      recv_total += o6i->message_stat[i].recv_octet;
491      send_total += o6i->message_stat[i].send_octet;
492    }
493  bps_total_avg = (recv_total + send_total) * 8 / uptime.tv_sec;
494  bps_tx_avg = send_total * 8 / uptime.tv_sec;
495  bps_rx_avg = recv_total * 8 / uptime.tv_sec;
496
497  vty_out (vty, "     Statistics of interface %s%s",
498           o6i->interface->name, VTY_NEWLINE);
499  vty_out (vty, "         Number of Neighbor: %d%s",
500           listcount (o6i->neighbor_list), VTY_NEWLINE);
501
502  vty_out (vty, "         %-8s %6s %6s %8s %8s%s",
503           "Type", "tx", "rx", "tx-byte", "rx-byte", VTY_NEWLINE);
504  for (i = 0; i < OSPF6_MESSAGE_TYPE_MAX; i++)
505    {
506      vty_out (vty, "         %-8s %6d %6d %8d %8d%s",
507               ospf6_message_type_string[i],
508               o6i->message_stat[i].send,
509               o6i->message_stat[i].recv,
510               o6i->message_stat[i].send_octet,
511               o6i->message_stat[i].recv_octet,
512               VTY_NEWLINE);
513    }
514
515  vty_out (vty, "         Average Link bandwidth: %ldbps"
516                " (Tx: %ldbps Rx: %ldbps)%s",
517           bps_total_avg, bps_tx_avg, bps_rx_avg, VTY_NEWLINE);
518}
519
520/* show interface */
521DEFUN (show_ipv6_ospf6_interface,
522       show_ipv6_ospf6_interface_ifname_cmd,
523       "show ipv6 ospf6 interface IFNAME",
524       SHOW_STR
525       IP6_STR
526       OSPF6_STR
527       INTERFACE_STR
528       IFNAME_STR
529       )
530{
531  struct interface *ifp;
532  listnode i;
533
534  if (argc)
535    {
536      ifp = if_lookup_by_name (argv[0]);
537      if (!ifp)
538        {
539          vty_out (vty, "No such Interface: %s%s", argv[0],
540		   VTY_NEWLINE);
541          return CMD_WARNING;
542        }
543      ospf6_interface_show (vty, ifp);
544    }
545  else
546    {
547      for (i = listhead (iflist); i; nextnode (i))
548        {
549          ifp = (struct interface *)getdata (i);
550          ospf6_interface_show (vty, ifp);
551        }
552    }
553  return CMD_SUCCESS;
554}
555
556ALIAS (show_ipv6_ospf6_interface,
557       show_ipv6_ospf6_interface_cmd,
558       "show ipv6 ospf6 interface",
559       SHOW_STR
560       IP6_STR
561       OSPF6_STR
562       INTERFACE_STR
563       )
564
565/* interface variable set command */
566DEFUN (ipv6_ospf6_cost,
567       ipv6_ospf6_cost_cmd,
568       "ipv6 ospf6 cost COST",
569       IP6_STR
570       OSPF6_STR
571       "Interface cost\n"
572       "<1-65535> Cost\n"
573       )
574{
575  struct ospf6_interface *o6i;
576  struct interface *ifp;
577
578  ifp = (struct interface *)vty->index;
579  assert (ifp);
580
581  o6i = (struct ospf6_interface *)ifp->info;
582  if (!o6i)
583    o6i = ospf6_interface_create (ifp);
584  assert (o6i);
585
586  if (o6i->cost == strtol (argv[0], NULL, 10))
587    return CMD_SUCCESS;
588
589  o6i->cost = strtol (argv[0], NULL, 10);
590
591  /* execute LSA hooks */
592  CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
593
594  CALL_CHANGE_HOOK (&interface_hook, o6i);
595
596  return CMD_SUCCESS;
597}
598
599/* interface variable set command */
600DEFUN (ipv6_ospf6_hellointerval,
601       ipv6_ospf6_hellointerval_cmd,
602       "ipv6 ospf6 hello-interval HELLO_INTERVAL",
603       IP6_STR
604       OSPF6_STR
605       "Time between HELLO packets\n"
606       SECONDS_STR
607       )
608{
609  struct ospf6_interface *ospf6_interface;
610  struct interface *ifp;
611
612  ifp = (struct interface *) vty->index;
613  assert (ifp);
614  ospf6_interface = (struct ospf6_interface *) ifp->info;
615  if (!ospf6_interface)
616    ospf6_interface = ospf6_interface_create (ifp);
617  assert (ospf6_interface);
618
619  ospf6_interface->hello_interval = strtol (argv[0], NULL, 10);
620  return CMD_SUCCESS;
621}
622
623/* interface variable set command */
624DEFUN (ipv6_ospf6_deadinterval,
625       ipv6_ospf6_deadinterval_cmd,
626       "ipv6 ospf6 dead-interval ROUTER_DEAD_INTERVAL",
627       IP6_STR
628       OSPF6_STR
629       "Interval after which a neighbor is declared dead\n"
630       SECONDS_STR
631       )
632{
633  struct ospf6_interface *ospf6_interface;
634  struct interface *ifp;
635
636  ifp = (struct interface *) vty->index;
637  assert (ifp);
638  ospf6_interface = (struct ospf6_interface *) ifp->info;
639  if (!ospf6_interface)
640    ospf6_interface = ospf6_interface_create (ifp);
641  assert (ospf6_interface);
642
643  ospf6_interface->dead_interval = strtol (argv[0], NULL, 10);
644  return CMD_SUCCESS;
645}
646
647/* interface variable set command */
648DEFUN (ipv6_ospf6_transmitdelay,
649       ipv6_ospf6_transmitdelay_cmd,
650       "ipv6 ospf6 transmit-delay TRANSMITDELAY",
651       IP6_STR
652       OSPF6_STR
653       "Link state transmit delay\n"
654       SECONDS_STR
655       )
656{
657  struct ospf6_interface *ospf6_interface;
658  struct interface *ifp;
659
660  ifp = (struct interface *) vty->index;
661  assert (ifp);
662  ospf6_interface = (struct ospf6_interface *) ifp->info;
663  if (!ospf6_interface)
664    ospf6_interface = ospf6_interface_create (ifp);
665  assert (ospf6_interface);
666
667  ospf6_interface->transdelay = strtol (argv[0], NULL, 10);
668  return CMD_SUCCESS;
669}
670
671/* interface variable set command */
672DEFUN (ipv6_ospf6_retransmitinterval,
673       ipv6_ospf6_retransmitinterval_cmd,
674       "ipv6 ospf6 retransmit-interval RXMTINTERVAL",
675       IP6_STR
676       OSPF6_STR
677       "Time between retransmitting lost link state advertisements\n"
678       SECONDS_STR
679       )
680{
681  struct ospf6_interface *ospf6_interface;
682  struct interface *ifp;
683
684  ifp = (struct interface *) vty->index;
685  assert (ifp);
686  ospf6_interface = (struct ospf6_interface *) ifp->info;
687  if (!ospf6_interface)
688    ospf6_interface = ospf6_interface_create (ifp);
689  assert (ospf6_interface);
690
691  ospf6_interface->rxmt_interval = strtol (argv[0], NULL, 10);
692  return CMD_SUCCESS;
693}
694
695/* interface variable set command */
696DEFUN (ipv6_ospf6_priority,
697       ipv6_ospf6_priority_cmd,
698       "ipv6 ospf6 priority PRIORITY",
699       IP6_STR
700       OSPF6_STR
701       "Router priority\n"
702       "<0-255> Priority\n"
703       )
704{
705  struct ospf6_interface *ospf6_interface;
706  struct interface *ifp;
707
708  ifp = (struct interface *) vty->index;
709  assert (ifp);
710  ospf6_interface = (struct ospf6_interface *) ifp->info;
711  if (!ospf6_interface)
712    ospf6_interface = ospf6_interface_create (ifp);
713  assert (ospf6_interface);
714
715  ospf6_interface->priority = strtol (argv[0], NULL, 10);
716
717  if (ospf6_interface->area)
718    ifs_change (dr_election (ospf6_interface), "Priority reconfigured",
719                ospf6_interface);
720
721  return CMD_SUCCESS;
722}
723
724DEFUN (ipv6_ospf6_instance,
725       ipv6_ospf6_instance_cmd,
726       "ipv6 ospf6 instance-id INSTANCE",
727       IP6_STR
728       OSPF6_STR
729       "Instance ID\n"
730       "<0-255> Instance ID\n"
731       )
732{
733  struct ospf6_interface *ospf6_interface;
734  struct interface *ifp;
735
736  ifp = (struct interface *)vty->index;
737  assert (ifp);
738
739  ospf6_interface = (struct ospf6_interface *)ifp->info;
740  if (!ospf6_interface)
741    ospf6_interface = ospf6_interface_create (ifp);
742  assert (ospf6_interface);
743
744  ospf6_interface->instance_id = strtol (argv[0], NULL, 10);
745  return CMD_SUCCESS;
746}
747
748DEFUN (ipv6_ospf6_passive,
749       ipv6_ospf6_passive_cmd,
750       "ipv6 ospf6 passive",
751       IP6_STR
752       OSPF6_STR
753       "passive interface: No Adjacency will be formed on this I/F\n"
754       )
755{
756  struct ospf6_interface *o6i;
757  struct interface *ifp;
758  listnode node;
759  struct ospf6_neighbor *o6n;
760
761  ifp = (struct interface *) vty->index;
762  assert (ifp);
763  o6i = (struct ospf6_interface *) ifp->info;
764  if (! o6i)
765    o6i = ospf6_interface_create (ifp);
766  assert (o6i);
767
768  SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
769  if (o6i->thread_send_hello)
770    {
771      thread_cancel (o6i->thread_send_hello);
772      o6i->thread_send_hello = (struct thread *) NULL;
773    }
774
775  for (node = listhead (o6i->neighbor_list); node; nextnode (node))
776    {
777      o6n = getdata (node);
778      if (o6n->inactivity_timer)
779        thread_cancel (o6n->inactivity_timer);
780      thread_execute (master, inactivity_timer, o6n, 0);
781    }
782
783  return CMD_SUCCESS;
784}
785
786DEFUN (no_ipv6_ospf6_passive,
787       no_ipv6_ospf6_passive_cmd,
788       "no ipv6 ospf6 passive",
789       NO_STR
790       IP6_STR
791       OSPF6_STR
792       "passive interface: No Adjacency will be formed on this I/F\n"
793       )
794{
795  struct ospf6_interface *o6i;
796  struct interface *ifp;
797
798  ifp = (struct interface *) vty->index;
799  assert (ifp);
800  o6i = (struct ospf6_interface *) ifp->info;
801  if (! o6i)
802    o6i = ospf6_interface_create (ifp);
803  assert (o6i);
804
805  UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
806  if (o6i->thread_send_hello == NULL)
807    thread_add_event (master, ospf6_send_hello, o6i, 0);
808
809  return CMD_SUCCESS;
810}
811
812
813DEFUN (ipv6_ospf6_advertise_force_prefix,
814       ipv6_ospf6_advertise_force_prefix_cmd,
815       "ipv6 ospf6 advertise force-prefix",
816       IP6_STR
817       OSPF6_STR
818       "Advertising options\n"
819       "Force advertising prefix, applicable if Loopback or P-to-P\n"
820       )
821{
822  struct ospf6_interface *o6i;
823  struct interface *ifp;
824
825  ifp = (struct interface *) vty->index;
826  assert (ifp);
827  o6i = (struct ospf6_interface *) ifp->info;
828  if (! o6i)
829    o6i = ospf6_interface_create (ifp);
830  assert (o6i);
831
832  if (! if_is_loopback (ifp) && ! if_is_pointopoint (ifp))
833    {
834      vty_out (vty, "Interface not Loopback nor PointToPoint%s",
835               VTY_NEWLINE);
836      return CMD_ERR_NOTHING_TODO;
837    }
838
839  SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX);
840
841  /* execute LSA hooks */
842  CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
843
844  CALL_CHANGE_HOOK (&interface_hook, o6i);
845
846  return CMD_SUCCESS;
847}
848
849DEFUN (no_ipv6_ospf6_advertise_force_prefix,
850       no_ipv6_ospf6_advertise_force_prefix_cmd,
851       "no ipv6 ospf6 advertise force-prefix",
852       NO_STR
853       IP6_STR
854       OSPF6_STR
855       "Advertising options\n"
856       "Force to advertise prefix, applicable if Loopback or P-to-P\n"
857       )
858{
859  struct ospf6_interface *o6i;
860  struct interface *ifp;
861
862  ifp = (struct interface *) vty->index;
863  assert (ifp);
864  o6i = (struct ospf6_interface *) ifp->info;
865  if (! o6i)
866    o6i = ospf6_interface_create (ifp);
867  assert (o6i);
868
869  UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX);
870
871  /* execute LSA hooks */
872  CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
873
874  CALL_CHANGE_HOOK (&interface_hook, o6i);
875
876  return CMD_SUCCESS;
877}
878
879DEFUN (ipv6_ospf6_advertise_prefix_list,
880       ipv6_ospf6_advertise_prefix_list_cmd,
881       "ipv6 ospf6 advertise prefix-list WORD",
882       IP6_STR
883       OSPF6_STR
884       "Advertising options\n"
885       "Filter prefix using prefix-list\n"
886       "Prefix list name\n"
887       )
888{
889  struct ospf6_interface *o6i;
890  struct interface *ifp;
891
892  ifp = (struct interface *) vty->index;
893  assert (ifp);
894  o6i = (struct ospf6_interface *) ifp->info;
895  if (! o6i)
896    o6i = ospf6_interface_create (ifp);
897  assert (o6i);
898
899  if (o6i->plist_name)
900    XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name);
901  o6i->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, argv[0]);
902
903  /* execute LSA hooks */
904  CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
905
906  CALL_CHANGE_HOOK (&interface_hook, o6i);
907
908  return CMD_SUCCESS;
909}
910
911DEFUN (no_ipv6_ospf6_advertise_prefix_list,
912       no_ipv6_ospf6_advertise_prefix_list_cmd,
913       "no ipv6 ospf6 advertise prefix-list",
914       NO_STR
915       IP6_STR
916       OSPF6_STR
917       "Advertising options\n"
918       "Filter prefix using prefix-list\n"
919       )
920{
921  struct ospf6_interface *o6i;
922  struct interface *ifp;
923
924  ifp = (struct interface *) vty->index;
925  assert (ifp);
926  o6i = (struct ospf6_interface *) ifp->info;
927  if (! o6i)
928    o6i = ospf6_interface_create (ifp);
929  assert (o6i);
930
931  if (o6i->plist_name)
932    {
933      XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name);
934      o6i->plist_name = NULL;
935    }
936
937  /* execute LSA hooks */
938  CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
939
940  CALL_CHANGE_HOOK (&interface_hook, o6i);
941
942  return CMD_SUCCESS;
943}
944
945int
946ospf6_interface_config_write (struct vty *vty)
947{
948  listnode i;
949  struct ospf6_interface *o6i;
950  struct interface *ifp;
951
952  for (i = listhead (iflist); i; nextnode (i))
953    {
954      ifp = (struct interface *) getdata (i);
955      o6i = (struct ospf6_interface *) ifp->info;
956      if (! o6i)
957        continue;
958
959      vty_out (vty, "interface %s%s",
960               o6i->interface->name, VTY_NEWLINE);
961      vty_out (vty, " ipv6 ospf6 cost %d%s",
962               o6i->cost, VTY_NEWLINE);
963      vty_out (vty, " ipv6 ospf6 hello-interval %d%s",
964               o6i->hello_interval, VTY_NEWLINE);
965      vty_out (vty, " ipv6 ospf6 dead-interval %d%s",
966               o6i->dead_interval, VTY_NEWLINE);
967      vty_out (vty, " ipv6 ospf6 retransmit-interval %d%s",
968               o6i->rxmt_interval, VTY_NEWLINE);
969      vty_out (vty, " ipv6 ospf6 priority %d%s",
970               o6i->priority, VTY_NEWLINE);
971      vty_out (vty, " ipv6 ospf6 transmit-delay %d%s",
972               o6i->transdelay, VTY_NEWLINE);
973      vty_out (vty, " ipv6 ospf6 instance-id %d%s",
974               o6i->instance_id, VTY_NEWLINE);
975
976      if (CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX))
977        vty_out (vty, " ipv6 ospf6 advertise force-prefix%s", VTY_NEWLINE);
978      if (o6i->plist_name)
979        vty_out (vty, " ipv6 ospf6 advertise prefix-list %s%s",
980                 o6i->plist_name, VTY_NEWLINE);
981
982      if (CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE))
983        vty_out (vty, " ipv6 ospf6 passive%s", VTY_NEWLINE);
984
985      vty_out (vty, "!%s", VTY_NEWLINE);
986    }
987  return 0;
988}
989
990struct cmd_node interface_node =
991{
992  INTERFACE_NODE,
993  "%s(config-if)# ",
994};
995
996void
997ospf6_interface_init ()
998{
999  /* Install interface node. */
1000  install_node (&interface_node, ospf6_interface_config_write);
1001
1002  install_element (VIEW_NODE, &show_ipv6_ospf6_interface_cmd);
1003  install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
1004  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_cmd);
1005  install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
1006
1007  install_default (INTERFACE_NODE);
1008  install_element (INTERFACE_NODE, &interface_desc_cmd);
1009  install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1010  install_element (INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
1011  install_element (INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);
1012  install_element (INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd);
1013  install_element (INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
1014  install_element (INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
1015  install_element (INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
1016  install_element (INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
1017  install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_force_prefix_cmd);
1018  install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_force_prefix_cmd);
1019  install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
1020  install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd);
1021  install_element (INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
1022  install_element (INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);
1023}
1024
1025
1026