]> git.sommitrealweird.co.uk Git - quagga-debian.git/blob - pimd/pim_cmd.c
New upstream version 1.2.4
[quagga-debian.git] / pimd / pim_cmd.c
1 /*
2   PIM for Quagga
3   Copyright (C) 2008  Everton da Silva Marques
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14   
15   You should have received a copy of the GNU General Public License
16   along with this program; see the file COPYING; if not, write to the
17   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18   MA 02110-1301 USA
19   
20   $QuaggaId: $Format:%an, %ai, %h$ $
21 */
22
23 #include <zebra.h>
24
25 #include <sys/ioctl.h>
26
27 #include "command.h"
28 #include "if.h"
29 #include "prefix.h"
30 #include "zclient.h"
31
32 #include "pimd.h"
33 #include "pim_cmd.h"
34 #include "pim_iface.h"
35 #include "pim_vty.h"
36 #include "pim_mroute.h"
37 #include "pim_str.h"
38 #include "pim_igmp.h"
39 #include "pim_igmpv3.h"
40 #include "pim_sock.h"
41 #include "pim_time.h"
42 #include "pim_util.h"
43 #include "pim_oil.h"
44 #include "pim_neighbor.h"
45 #include "pim_pim.h"
46 #include "pim_ifchannel.h"
47 #include "pim_hello.h"
48 #include "pim_msg.h"
49 #include "pim_upstream.h"
50 #include "pim_rpf.h"
51 #include "pim_macro.h"
52 #include "pim_ssmpingd.h"
53 #include "pim_zebra.h"
54 #include "pim_static.h"
55
56 static struct cmd_node pim_global_node = {
57   PIM_NODE,
58   "",
59   1 /* vtysh ? yes */
60 };
61
62 static struct cmd_node interface_node = {
63   INTERFACE_NODE,
64   "%s(config-if)# ",
65   1 /* vtysh ? yes */
66 };
67
68 static void pim_if_membership_clear(struct interface *ifp)
69 {
70   struct pim_interface *pim_ifp;
71
72   pim_ifp = ifp->info;
73   zassert(pim_ifp);
74
75   if (PIM_IF_TEST_PIM(pim_ifp->options) &&
76       PIM_IF_TEST_IGMP(pim_ifp->options)) {
77     return;
78   }
79
80   pim_ifchannel_membership_clear(ifp);
81 }
82
83 /*
84   When PIM is disabled on interface, IGMPv3 local membership
85   information is not injected into PIM interface state.
86
87   The function pim_if_membership_refresh() fetches all IGMPv3 local
88   membership information into PIM. It is intented to be called
89   whenever PIM is enabled on the interface in order to collect missed
90   local membership information.
91  */
92 static void pim_if_membership_refresh(struct interface *ifp)
93 {
94   struct pim_interface *pim_ifp;
95   struct listnode      *sock_node;
96   struct igmp_sock     *igmp;
97
98   pim_ifp = ifp->info;
99   zassert(pim_ifp);
100
101   if (!PIM_IF_TEST_PIM(pim_ifp->options))
102     return;
103   if (!PIM_IF_TEST_IGMP(pim_ifp->options))
104     return;
105
106   /*
107     First clear off membership from all PIM (S,G) entries on the
108     interface
109   */
110
111   pim_ifchannel_membership_clear(ifp);
112
113   /*
114     Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
115     the interface
116   */
117
118   /* scan igmp sockets */
119   for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
120     struct listnode   *grpnode;
121     struct igmp_group *grp;
122     
123     /* scan igmp groups */
124     for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
125       struct listnode    *srcnode;
126       struct igmp_source *src;
127       
128       /* scan group sources */
129       for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
130
131         if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) {
132           pim_ifchannel_local_membership_add(ifp,
133                                              src->source_addr,
134                                              grp->group_addr);
135         }
136         
137       } /* scan group sources */
138     } /* scan igmp groups */
139   } /* scan igmp sockets */
140
141   /*
142     Finally delete every PIM (S,G) entry lacking all state info
143    */
144
145   pim_ifchannel_delete_on_noinfo(ifp);
146
147 }
148
149 static void pim_show_assert(struct vty *vty)
150 {
151   struct listnode  *ifnode;
152   struct interface *ifp;
153   time_t            now;
154   
155   now = pim_time_monotonic_sec();
156
157   vty_out(vty,
158           "Interface Address         Source          Group           State  Winner          Uptime   Timer%s",
159           VTY_NEWLINE);
160
161   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
162     struct pim_interface *pim_ifp;
163     struct in_addr ifaddr;
164     struct listnode *ch_node;
165     struct pim_ifchannel *ch;
166
167     pim_ifp = ifp->info;
168     
169     if (!pim_ifp)
170       continue;
171
172     ifaddr = pim_ifp->primary_address;
173
174     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
175       char ch_src_str[100];
176       char ch_grp_str[100];
177       char winner_str[100];
178       char uptime[10];
179       char timer[10];
180
181       pim_inet4_dump("<ch_src?>", ch->source_addr,
182                      ch_src_str, sizeof(ch_src_str));
183       pim_inet4_dump("<ch_grp?>", ch->group_addr,
184                      ch_grp_str, sizeof(ch_grp_str));
185       pim_inet4_dump("<assrt_win?>", ch->ifassert_winner,
186                      winner_str, sizeof(winner_str));
187
188       pim_time_uptime(uptime, sizeof(uptime), now - ch->ifassert_creation);
189       pim_time_timer_to_mmss(timer, sizeof(timer),
190                              ch->t_ifassert_timer);
191
192       vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %-15s %-8s %-5s%s",
193               ifp->name,
194               inet_ntoa(ifaddr),
195               ch_src_str,
196               ch_grp_str,
197               pim_ifchannel_ifassert_name(ch->ifassert_state),
198               winner_str,
199               uptime,
200               timer,
201               VTY_NEWLINE);
202     } /* scan interface channels */
203   } /* scan interfaces */
204 }
205
206 static void pim_show_assert_internal(struct vty *vty)
207 {
208   struct listnode  *ifnode;
209   struct interface *ifp;
210
211   vty_out(vty,
212           "CA:   CouldAssert%s"
213           "ECA:  Evaluate CouldAssert%s"
214           "ATD:  AssertTrackingDesired%s"
215           "eATD: Evaluate AssertTrackingDesired%s%s",
216           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
217
218   vty_out(vty,
219           "Interface Address         Source          Group           CA  eCA ATD eATD%s",
220           VTY_NEWLINE);
221
222   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
223     struct pim_interface *pim_ifp;
224     struct in_addr ifaddr;
225     struct listnode *ch_node;
226     struct pim_ifchannel *ch;
227
228     pim_ifp = ifp->info;
229     
230     if (!pim_ifp)
231       continue;
232
233     ifaddr = pim_ifp->primary_address;
234
235     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
236       char ch_src_str[100];
237       char ch_grp_str[100];
238
239       pim_inet4_dump("<ch_src?>", ch->source_addr,
240                      ch_src_str, sizeof(ch_src_str));
241       pim_inet4_dump("<ch_grp?>", ch->group_addr,
242                      ch_grp_str, sizeof(ch_grp_str));
243       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-3s %-3s %-4s%s",
244               ifp->name,
245               inet_ntoa(ifaddr),
246               ch_src_str,
247               ch_grp_str,
248               PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags) ? "yes" : "no",
249               pim_macro_ch_could_assert_eval(ch) ? "yes" : "no",
250               PIM_IF_FLAG_TEST_ASSERT_TRACKING_DESIRED(ch->flags) ? "yes" : "no",
251               pim_macro_assert_tracking_desired_eval(ch) ? "yes" : "no",
252               VTY_NEWLINE);
253     } /* scan interface channels */
254   } /* scan interfaces */
255 }
256
257 static void pim_show_assert_metric(struct vty *vty)
258 {
259   struct listnode  *ifnode;
260   struct interface *ifp;
261   
262   vty_out(vty,
263           "Interface Address         Source          Group           RPT Pref Metric Address        %s",
264           VTY_NEWLINE);
265
266   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
267     struct pim_interface *pim_ifp;
268     struct in_addr ifaddr;
269     struct listnode *ch_node;
270     struct pim_ifchannel *ch;
271
272     pim_ifp = ifp->info;
273     
274     if (!pim_ifp)
275       continue;
276
277     ifaddr = pim_ifp->primary_address;
278
279     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
280       char ch_src_str[100];
281       char ch_grp_str[100];
282       char addr_str[100];
283       struct pim_assert_metric am;
284
285       am = pim_macro_spt_assert_metric(&ch->upstream->rpf, pim_ifp->primary_address);
286
287       pim_inet4_dump("<ch_src?>", ch->source_addr,
288                      ch_src_str, sizeof(ch_src_str));
289       pim_inet4_dump("<ch_grp?>", ch->group_addr,
290                      ch_grp_str, sizeof(ch_grp_str));
291       pim_inet4_dump("<addr?>", am.ip_address,
292                      addr_str, sizeof(addr_str));
293
294       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %4u %6u %-15s%s",
295               ifp->name,
296               inet_ntoa(ifaddr),
297               ch_src_str,
298               ch_grp_str,
299               am.rpt_bit_flag ? "yes" : "no",
300               am.metric_preference,
301               am.route_metric,
302               addr_str,
303               VTY_NEWLINE);
304     } /* scan interface channels */
305   } /* scan interfaces */
306 }
307
308 static void pim_show_assert_winner_metric(struct vty *vty)
309 {
310   struct listnode  *ifnode;
311   struct interface *ifp;
312   
313   vty_out(vty,
314           "Interface Address         Source          Group           RPT Pref Metric Address        %s",
315           VTY_NEWLINE);
316
317   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
318     struct pim_interface *pim_ifp;
319     struct in_addr ifaddr;
320     struct listnode *ch_node;
321     struct pim_ifchannel *ch;
322
323     pim_ifp = ifp->info;
324     
325     if (!pim_ifp)
326       continue;
327
328     ifaddr = pim_ifp->primary_address;
329
330     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
331       char ch_src_str[100];
332       char ch_grp_str[100];
333       char addr_str[100];
334       struct pim_assert_metric *am;
335       char pref_str[5];
336       char metr_str[7];
337
338       am = &ch->ifassert_winner_metric;
339
340       pim_inet4_dump("<ch_src?>", ch->source_addr,
341                      ch_src_str, sizeof(ch_src_str));
342       pim_inet4_dump("<ch_grp?>", ch->group_addr,
343                      ch_grp_str, sizeof(ch_grp_str));
344       pim_inet4_dump("<addr?>", am->ip_address,
345                      addr_str, sizeof(addr_str));
346
347       if (am->metric_preference == PIM_ASSERT_METRIC_PREFERENCE_MAX)
348         snprintf(pref_str, sizeof(pref_str), "INFI");
349       else
350         snprintf(pref_str, sizeof(pref_str), "%4u", am->metric_preference);
351
352       if (am->route_metric == PIM_ASSERT_ROUTE_METRIC_MAX)
353         snprintf(metr_str, sizeof(metr_str), "INFI");
354       else
355         snprintf(metr_str, sizeof(metr_str), "%6u", am->route_metric);
356
357       vty_out(vty, "%-9s %-15s %-15s %-15s %-3s %-4s %-6s %-15s%s",
358               ifp->name,
359               inet_ntoa(ifaddr),
360               ch_src_str,
361               ch_grp_str,
362               am->rpt_bit_flag ? "yes" : "no",
363               pref_str,
364               metr_str,
365               addr_str,
366               VTY_NEWLINE);
367     } /* scan interface channels */
368   } /* scan interfaces */
369 }
370
371 static void pim_show_membership(struct vty *vty)
372 {
373   struct listnode  *ifnode;
374   struct interface *ifp;
375
376   vty_out(vty,
377           "Interface Address         Source          Group           Membership%s",
378           VTY_NEWLINE);
379
380   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
381     struct pim_interface *pim_ifp;
382     struct in_addr ifaddr;
383     struct listnode *ch_node;
384     struct pim_ifchannel *ch;
385
386     pim_ifp = ifp->info;
387     
388     if (!pim_ifp)
389       continue;
390
391     ifaddr = pim_ifp->primary_address;
392
393     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
394       char ch_src_str[100];
395       char ch_grp_str[100];
396
397       pim_inet4_dump("<ch_src?>", ch->source_addr,
398                      ch_src_str, sizeof(ch_src_str));
399       pim_inet4_dump("<ch_grp?>", ch->group_addr,
400                      ch_grp_str, sizeof(ch_grp_str));
401
402       vty_out(vty, "%-9s %-15s %-15s %-15s %-10s%s",
403               ifp->name,
404               inet_ntoa(ifaddr),
405               ch_src_str,
406               ch_grp_str,
407               ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO ?
408               "NOINFO" : "INCLUDE",
409               VTY_NEWLINE);
410     } /* scan interface channels */
411   } /* scan interfaces */
412
413 }
414
415 static void igmp_show_interfaces(struct vty *vty)
416 {
417   struct listnode  *node;
418   struct interface *ifp;
419   time_t            now;
420   
421   now = pim_time_monotonic_sec();
422
423   vty_out(vty,
424           "Interface Address         ifIndex Socket Uptime   Multi Broad MLoop AllMu Prmsc Del%s",
425           VTY_NEWLINE);
426
427   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
428     struct pim_interface *pim_ifp;
429     struct listnode *sock_node;
430     struct igmp_sock *igmp;
431
432     pim_ifp = ifp->info;
433     
434     if (!pim_ifp)
435       continue;
436
437     for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
438       char uptime[10];
439       int mloop;
440
441       pim_time_uptime(uptime, sizeof(uptime), now - igmp->sock_creation);
442
443       mloop = pim_socket_mcastloop_get(igmp->fd);
444       
445       vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s",
446               ifp->name,
447               inet_ntoa(igmp->ifaddr),
448               ifp->ifindex,
449               igmp->fd,
450               uptime,
451               if_is_multicast(ifp) ? "yes" : "no",
452               if_is_broadcast(ifp) ? "yes" : "no",
453               (mloop < 0) ? "?" : (mloop ? "yes" : "no"),
454               (ifp->flags & IFF_ALLMULTI) ? "yes" : "no",
455               (ifp->flags & IFF_PROMISC) ? "yes" : "no",
456               PIM_IF_IS_DELETED(ifp) ? "yes" : "no",
457               VTY_NEWLINE);
458     }
459   }
460 }
461
462 static void igmp_show_interface_join(struct vty *vty)
463 {
464   struct listnode  *node;
465   struct interface *ifp;
466   time_t            now;
467   
468   now = pim_time_monotonic_sec();
469
470   vty_out(vty,
471           "Interface Address         Source          Group           Socket Uptime  %s",
472           VTY_NEWLINE);
473
474   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
475     struct pim_interface *pim_ifp;
476     struct listnode *join_node;
477     struct igmp_join *ij;
478     struct in_addr pri_addr;
479     char pri_addr_str[100];
480
481     pim_ifp = ifp->info;
482     
483     if (!pim_ifp)
484       continue;
485
486     if (!pim_ifp->igmp_join_list)
487       continue;
488
489     pri_addr = pim_find_primary_addr(ifp);
490     pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, sizeof(pri_addr_str));
491
492     for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_join_list, join_node, ij)) {
493       char group_str[100];
494       char source_str[100];
495       char uptime[10];
496
497       pim_time_uptime(uptime, sizeof(uptime), now - ij->sock_creation);
498       pim_inet4_dump("<grp?>", ij->group_addr, group_str, sizeof(group_str));
499       pim_inet4_dump("<src?>", ij->source_addr, source_str, sizeof(source_str));
500       
501       vty_out(vty, "%-9s %-15s %-15s %-15s %6d %8s%s",
502               ifp->name,
503               pri_addr_str,
504               source_str,
505               group_str,
506               ij->sock_fd,
507               uptime,
508               VTY_NEWLINE);
509     } /* for (pim_ifp->igmp_join_list) */
510
511   } /* for (iflist) */
512
513 }
514
515 static void show_interface_address(struct vty *vty)
516 {
517   struct listnode  *ifpnode;
518   struct interface *ifp;
519   
520   vty_out(vty,
521           "Interface Primary         Secondary      %s",
522           VTY_NEWLINE);
523
524   for (ALL_LIST_ELEMENTS_RO(iflist, ifpnode, ifp)) {
525     struct listnode  *ifcnode;
526     struct connected *ifc;
527     struct in_addr    pri_addr;
528     char pri_addr_str[100];
529
530     pri_addr = pim_find_primary_addr(ifp);
531
532     pim_inet4_dump("<pri?>", pri_addr, pri_addr_str, sizeof(pri_addr_str));
533     
534     for (ALL_LIST_ELEMENTS_RO(ifp->connected, ifcnode, ifc)) {
535       char sec_addr_str[100];
536       struct prefix *p = ifc->address;
537
538       if (p->family != AF_INET)
539         continue;
540
541       if (p->u.prefix4.s_addr == pri_addr.s_addr) {
542         sec_addr_str[0] = '\0';
543       }
544       else {
545         pim_inet4_dump("<sec?>", p->u.prefix4, sec_addr_str, sizeof(sec_addr_str));
546       }
547     
548       vty_out(vty, "%-9s %-15s %-15s%s",
549               ifp->name,
550               pri_addr_str,
551               sec_addr_str,
552               VTY_NEWLINE);
553     }
554   }
555 }
556
557 static void pim_show_dr(struct vty *vty)
558 {
559   struct listnode  *node;
560   struct interface *ifp;
561   time_t            now;
562   
563   now = pim_time_monotonic_sec();
564
565   vty_out(vty,
566           "NonPri: Number of neighbors missing DR Priority hello option%s"
567           "DrPri: Designated Router Priority sent%s%s",
568           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
569   
570   vty_out(vty, "Interface Address         DR              Uptime   Elections Changes NonPri      DrPri%s", VTY_NEWLINE);
571
572   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
573     struct pim_interface *pim_ifp;
574     struct in_addr ifaddr;
575     char dr_str[100];
576     char dr_uptime[10];
577
578     pim_ifp = ifp->info;
579     
580     if (!pim_ifp)
581       continue;
582
583     if (pim_ifp->pim_sock_fd < 0)
584       continue;
585
586     ifaddr = pim_ifp->primary_address;
587
588     pim_time_uptime_begin(dr_uptime, sizeof(dr_uptime),
589                           now, pim_ifp->pim_dr_election_last);
590
591     pim_inet4_dump("<dr?>", pim_ifp->pim_dr_addr,
592                    dr_str, sizeof(dr_str));
593
594     vty_out(vty, "%-9s %-15s %-15s %8s %9d %7d %6d %10d%s",
595             ifp->name,
596             inet_ntoa(ifaddr),
597             dr_str,
598             dr_uptime,
599             pim_ifp->pim_dr_election_count,
600             pim_ifp->pim_dr_election_changes,
601             pim_ifp->pim_dr_num_nondrpri_neighbors,
602             pim_ifp->pim_dr_priority,
603             VTY_NEWLINE);
604   }
605 }
606
607 static void pim_show_hello(struct vty *vty)
608 {
609   struct listnode  *node;
610   struct interface *ifp;
611   time_t            now;
612   
613   now = pim_time_monotonic_sec();
614   
615   vty_out(vty, "Interface Address         Period Timer StatStart Recv Rfail Send Sfail%s", VTY_NEWLINE);
616
617   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
618     struct pim_interface *pim_ifp;
619     struct in_addr ifaddr;
620     char hello_period[10];
621     char hello_timer[10];
622     char stat_uptime[10];
623
624     pim_ifp = ifp->info;
625     
626     if (!pim_ifp)
627       continue;
628
629     if (pim_ifp->pim_sock_fd < 0)
630       continue;
631
632     ifaddr = pim_ifp->primary_address;
633
634     pim_time_timer_to_mmss(hello_timer, sizeof(hello_timer), pim_ifp->t_pim_hello_timer);
635     pim_time_mmss(hello_period, sizeof(hello_period), pim_ifp->pim_hello_period);
636     pim_time_uptime(stat_uptime, sizeof(stat_uptime), now - pim_ifp->pim_ifstat_start);
637
638     vty_out(vty, "%-9s %-15s %6s %5s %9s %4u %5u %4u %5u%s",
639             ifp->name,
640             inet_ntoa(ifaddr),
641             hello_period,
642             hello_timer,
643             stat_uptime,
644             pim_ifp->pim_ifstat_hello_recv,
645             pim_ifp->pim_ifstat_hello_recvfail,
646             pim_ifp->pim_ifstat_hello_sent,
647             pim_ifp->pim_ifstat_hello_sendfail,
648             VTY_NEWLINE);
649   }
650 }
651
652 static void pim_show_interfaces(struct vty *vty)
653 {
654   struct listnode  *node;
655   struct interface *ifp;
656   time_t            now;
657   
658   now = pim_time_monotonic_sec();
659
660   vty_out(vty, "Interface Address         ifIndex Socket Uptime   Multi Broad MLoop AllMu Prmsc Del%s", VTY_NEWLINE);
661
662   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
663     struct pim_interface *pim_ifp;
664     struct in_addr ifaddr;
665     char uptime[10];
666     int mloop;
667
668     pim_ifp = ifp->info;
669     
670     if (!pim_ifp)
671       continue;
672
673     if (pim_ifp->pim_sock_fd < 0)
674       continue;
675
676     ifaddr = pim_ifp->primary_address;
677
678     pim_time_uptime(uptime, sizeof(uptime), now - pim_ifp->pim_sock_creation);
679
680     mloop = pim_socket_mcastloop_get(pim_ifp->pim_sock_fd);
681       
682     vty_out(vty, "%-9s %-15s %7d %6d %8s %5s %5s %5s %5s %5s %3s%s",
683             ifp->name,
684             inet_ntoa(ifaddr),
685             ifp->ifindex,
686             pim_ifp->pim_sock_fd,
687             uptime,
688             if_is_multicast(ifp) ? "yes" : "no",
689             if_is_broadcast(ifp) ? "yes" : "no",
690             (mloop < 0) ? "?" : (mloop ? "yes" : "no"),
691             (ifp->flags & IFF_ALLMULTI) ? "yes" : "no",
692             (ifp->flags & IFF_PROMISC) ? "yes" : "no",
693             PIM_IF_IS_DELETED(ifp) ? "yes" : "no",
694             VTY_NEWLINE);
695   }
696 }
697
698 static void pim_show_join(struct vty *vty)
699 {
700   struct listnode  *ifnode;
701   struct interface *ifp;
702   time_t            now;
703   
704   now = pim_time_monotonic_sec();
705
706   vty_out(vty,
707           "Interface Address         Source          Group           State  Uptime   Expire Prune%s",
708           VTY_NEWLINE);
709
710   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
711     struct pim_interface *pim_ifp;
712     struct in_addr ifaddr;
713     struct listnode *ch_node;
714     struct pim_ifchannel *ch;
715
716     pim_ifp = ifp->info;
717     
718     if (!pim_ifp)
719       continue;
720
721     ifaddr = pim_ifp->primary_address;
722
723     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
724       char ch_src_str[100];
725       char ch_grp_str[100];
726       char uptime[10];
727       char expire[10];
728       char prune[10];
729
730       pim_inet4_dump("<ch_src?>", ch->source_addr,
731                      ch_src_str, sizeof(ch_src_str));
732       pim_inet4_dump("<ch_grp?>", ch->group_addr,
733                      ch_grp_str, sizeof(ch_grp_str));
734
735       pim_time_uptime_begin(uptime, sizeof(uptime), now, ch->ifjoin_creation);
736       pim_time_timer_to_mmss(expire, sizeof(expire),
737                              ch->t_ifjoin_expiry_timer);
738       pim_time_timer_to_mmss(prune, sizeof(prune),
739                              ch->t_ifjoin_prune_pending_timer);
740
741       vty_out(vty, "%-9s %-15s %-15s %-15s %-6s %8s %-6s %5s%s",
742               ifp->name,
743               inet_ntoa(ifaddr),
744               ch_src_str,
745               ch_grp_str,
746               pim_ifchannel_ifjoin_name(ch->ifjoin_state),
747               uptime,
748               expire,
749               prune,
750               VTY_NEWLINE);
751     } /* scan interface channels */
752   } /* scan interfaces */
753
754 }
755
756 static void pim_show_neighbors(struct vty *vty)
757 {
758   struct listnode  *node;
759   struct interface *ifp;
760   time_t            now;
761   
762   now = pim_time_monotonic_sec();
763
764   vty_out(vty,
765           "Recv flags: H=holdtime L=lan_prune_delay P=dr_priority G=generation_id A=address_list%s"
766           "            T=can_disable_join_suppression%s%s",
767           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
768
769   vty_out(vty, "Interface Address         Neighbor        Uptime   Timer Holdt DrPri GenId    Recv  %s", VTY_NEWLINE);
770
771   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
772     struct pim_interface *pim_ifp;
773     struct in_addr ifaddr;
774     struct listnode *neighnode;
775     struct pim_neighbor *neigh;
776
777     pim_ifp = ifp->info;
778     
779     if (!pim_ifp)
780       continue;
781
782     if (pim_ifp->pim_sock_fd < 0)
783       continue;
784
785     ifaddr = pim_ifp->primary_address;
786
787     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
788       char uptime[10];
789       char holdtime[10];
790       char expire[10];
791       char neigh_src_str[100];
792       char recv[7];
793
794       pim_inet4_dump("<src?>", neigh->source_addr,
795                      neigh_src_str, sizeof(neigh_src_str));
796       pim_time_uptime(uptime, sizeof(uptime), now - neigh->creation);
797       pim_time_mmss(holdtime, sizeof(holdtime), neigh->holdtime);
798       pim_time_timer_to_mmss(expire, sizeof(expire), neigh->t_expire_timer);
799
800       recv[0] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_HOLDTIME)                     ? 'H' : ' ';
801       recv[1] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY)              ? 'L' : ' ';
802       recv[2] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)                  ? 'P' : ' ';
803       recv[3] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID)                ? 'G' : ' ';
804       recv[4] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_ADDRESS_LIST)                 ? 'A' : ' ';
805       recv[5] = PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION) ? 'T' : ' ';
806       recv[6] = '\0';
807
808       vty_out(vty, "%-9s %-15s %-15s %8s %5s %5s %5u %08x %6s%s",
809               ifp->name,
810               inet_ntoa(ifaddr),
811               neigh_src_str,
812               uptime,
813               expire,
814               holdtime,
815               neigh->dr_priority,
816               neigh->generation_id,
817               recv,
818               VTY_NEWLINE);
819     }
820
821
822   }
823 }
824
825 static void pim_show_lan_prune_delay(struct vty *vty)
826 {
827   struct listnode  *node;
828   struct interface *ifp;
829
830   vty_out(vty,
831           "PrDly=propagation_delay (msec)           OvInt=override_interval (msec)%s"
832           "HiDly=highest_propagation_delay (msec)   HiInt=highest_override_interval (msec)%s"
833           "NoDly=number_of_non_lan_delay_neighbors%s"
834           "T=t_bit LPD=lan_prune_delay_hello_option%s%s",
835           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
836
837   vty_out(vty, "Interface Address         PrDly OvInt NoDly HiDly HiInt T | Neighbor        LPD PrDly OvInt T%s", VTY_NEWLINE);
838
839   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
840     struct pim_interface *pim_ifp;
841     struct in_addr ifaddr;
842     struct listnode *neighnode;
843     struct pim_neighbor *neigh;
844
845     pim_ifp = ifp->info;
846     
847     if (!pim_ifp)
848       continue;
849
850     if (pim_ifp->pim_sock_fd < 0)
851       continue;
852
853     ifaddr = pim_ifp->primary_address;
854
855     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
856       char neigh_src_str[100];
857
858       pim_inet4_dump("<src?>", neigh->source_addr,
859                      neigh_src_str, sizeof(neigh_src_str));
860
861       vty_out(vty, "%-9s %-15s %5u %5u %5u %5u %5u %1u | %-15s %-3s %5u %5u %1u%s",
862               ifp->name,
863               inet_ntoa(ifaddr),
864               pim_ifp->pim_propagation_delay_msec,
865               pim_ifp->pim_override_interval_msec,
866               pim_ifp->pim_number_of_nonlandelay_neighbors,
867               pim_ifp->pim_neighbors_highest_propagation_delay_msec,
868               pim_ifp->pim_neighbors_highest_override_interval_msec,
869               PIM_FORCE_BOOLEAN(PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options)),
870               neigh_src_str,
871               PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY) ? "yes" : "no",
872               neigh->propagation_delay_msec,
873               neigh->override_interval_msec,
874               PIM_FORCE_BOOLEAN(PIM_OPTION_IS_SET(neigh->hello_options,
875                                                   PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)),
876               VTY_NEWLINE);
877     }
878
879   }
880 }
881
882 static void pim_show_jp_override_interval(struct vty *vty)
883 {
884   struct listnode  *node;
885   struct interface *ifp;
886
887   vty_out(vty,
888           "EffPDelay=effective_propagation_delay (msec)%s"
889           "EffOvrInt=override_interval (msec)%s"
890           "JPOvrInt=jp_override_interval (msec)%s%s",
891           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
892
893   vty_out(vty, "Interface Address         LAN_Delay EffPDelay EffOvrInt JPOvrInt%s", VTY_NEWLINE);
894
895   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
896     struct pim_interface *pim_ifp;
897     struct in_addr ifaddr;
898
899     pim_ifp = ifp->info;
900     
901     if (!pim_ifp)
902       continue;
903
904     if (pim_ifp->pim_sock_fd < 0)
905       continue;
906
907     ifaddr = pim_ifp->primary_address;
908
909     vty_out(vty, "%-9s %-15s %-9s %9u %9u %8u%s",
910             ifp->name,
911             inet_ntoa(ifaddr),
912             pim_if_lan_delay_enabled(ifp) ? "enabled" : "disabled",
913             pim_if_effective_propagation_delay_msec(ifp),
914             pim_if_effective_override_interval_msec(ifp),
915             pim_if_jp_override_interval_msec(ifp),
916             VTY_NEWLINE);
917   }
918 }
919
920 static void pim_show_neighbors_secondary(struct vty *vty)
921 {
922   struct listnode  *node;
923   struct interface *ifp;
924
925   vty_out(vty, "Interface Address         Neighbor        Secondary      %s", VTY_NEWLINE);
926
927   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
928     struct pim_interface *pim_ifp;
929     struct in_addr ifaddr;
930     struct listnode *neighnode;
931     struct pim_neighbor *neigh;
932
933     pim_ifp = ifp->info;
934     
935     if (!pim_ifp)
936       continue;
937
938     if (pim_ifp->pim_sock_fd < 0)
939       continue;
940
941     ifaddr = pim_ifp->primary_address;
942
943     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode, neigh)) {
944       char neigh_src_str[100];
945       struct listnode *prefix_node;
946       struct prefix *p;
947
948       if (!neigh->prefix_list)
949         continue;
950
951       pim_inet4_dump("<src?>", neigh->source_addr,
952                      neigh_src_str, sizeof(neigh_src_str));
953
954       for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, prefix_node, p)) {
955         char neigh_sec_str[100];
956
957         if (p->family != AF_INET)
958           continue;
959
960         pim_inet4_dump("<src?>", p->u.prefix4,
961                        neigh_sec_str, sizeof(neigh_sec_str));
962
963         vty_out(vty, "%-9s %-15s %-15s %-15s%s",
964                 ifp->name,
965                 inet_ntoa(ifaddr),
966                 neigh_src_str,
967                 neigh_sec_str,
968                 VTY_NEWLINE);
969       }
970     }
971   }
972 }
973
974 static void pim_show_upstream(struct vty *vty)
975 {
976   struct listnode     *upnode;
977   struct pim_upstream *up;
978   time_t               now;
979
980   now = pim_time_monotonic_sec();
981
982   vty_out(vty, "Source          Group           State Uptime   JoinTimer RefCnt%s", VTY_NEWLINE);
983
984   for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) {
985       char src_str[100];
986       char grp_str[100];
987       char uptime[10];
988       char join_timer[10];
989
990       pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
991       pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
992       pim_time_uptime(uptime, sizeof(uptime), now - up->state_transition);
993       pim_time_timer_to_hhmmss(join_timer, sizeof(join_timer), up->t_join_timer);
994
995       vty_out(vty, "%-15s %-15s %-5s %-8s %-9s %6d%s",
996               src_str,
997               grp_str,
998               up->join_state == PIM_UPSTREAM_JOINED ? "Jnd" : "NtJnd",
999               uptime,
1000               join_timer,
1001               up->ref_count,
1002               VTY_NEWLINE);
1003   }
1004 }
1005
1006 static void pim_show_join_desired(struct vty *vty)
1007 {
1008   struct listnode      *ifnode;
1009   struct listnode      *chnode;
1010   struct interface     *ifp;
1011   struct pim_interface *pim_ifp;
1012   struct pim_ifchannel *ch;
1013   char src_str[100];
1014   char grp_str[100];
1015
1016   vty_out(vty,
1017           "Interface Source          Group           LostAssert Joins PimInclude JoinDesired EvalJD%s",
1018           VTY_NEWLINE);
1019
1020   /* scan all interfaces */
1021   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1022     pim_ifp = ifp->info;
1023     if (!pim_ifp)
1024       continue;
1025
1026     /* scan per-interface (S,G) state */
1027     for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, chnode, ch)) {
1028       struct pim_upstream *up = ch->upstream;
1029
1030       pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
1031       pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
1032
1033       vty_out(vty, "%-9s %-15s %-15s %-10s %-5s %-10s %-11s %-6s%s",
1034               ifp->name,
1035               src_str,
1036               grp_str,
1037               pim_macro_ch_lost_assert(ch) ? "yes" : "no",
1038               pim_macro_chisin_joins(ch) ? "yes" : "no",
1039               pim_macro_chisin_pim_include(ch) ? "yes" : "no",
1040               PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags) ? "yes" : "no",
1041               pim_upstream_evaluate_join_desired(up) ? "yes" : "no",
1042               VTY_NEWLINE);
1043     }
1044   }
1045 }
1046
1047 static void pim_show_upstream_rpf(struct vty *vty)
1048 {
1049   struct listnode     *upnode;
1050   struct pim_upstream *up;
1051
1052   vty_out(vty,
1053           "Source          Group           RpfIface RibNextHop      RpfAddress     %s",
1054           VTY_NEWLINE);
1055
1056   for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, upnode, up)) {
1057     char src_str[100];
1058     char grp_str[100];
1059     char rpf_nexthop_str[100];
1060     char rpf_addr_str[100];
1061     struct pim_rpf *rpf;
1062     const char *rpf_ifname;
1063     
1064     rpf = &up->rpf;
1065     
1066     pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
1067     pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
1068     pim_inet4_dump("<nexthop?>", rpf->source_nexthop.mrib_nexthop_addr, rpf_nexthop_str, sizeof(rpf_nexthop_str));
1069     pim_inet4_dump("<rpf?>", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
1070     
1071     rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
1072     
1073     vty_out(vty, "%-15s %-15s %-8s %-15s %-15s%s",
1074             src_str,
1075             grp_str,
1076             rpf_ifname,
1077             rpf_nexthop_str,
1078             rpf_addr_str,
1079             VTY_NEWLINE);
1080   }
1081 }
1082
1083 static void show_rpf_refresh_stats(struct vty *vty, time_t now)
1084 {
1085   char refresh_uptime[10];
1086
1087   pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now, qpim_rpf_cache_refresh_last);
1088
1089   vty_out(vty, 
1090           "RPF Cache Refresh Delay:    %ld msecs%s"
1091           "RPF Cache Refresh Timer:    %ld msecs%s"
1092           "RPF Cache Refresh Requests: %lld%s"
1093           "RPF Cache Refresh Events:   %lld%s"
1094           "RPF Cache Refresh Last:     %s%s",
1095           qpim_rpf_cache_refresh_delay_msec, VTY_NEWLINE,
1096           pim_time_timer_remain_msec(qpim_rpf_cache_refresher), VTY_NEWLINE,
1097           (long long)qpim_rpf_cache_refresh_requests, VTY_NEWLINE,
1098           (long long)qpim_rpf_cache_refresh_events, VTY_NEWLINE,
1099           refresh_uptime, VTY_NEWLINE);
1100 }
1101
1102 static void show_scan_oil_stats(struct vty *vty, time_t now)
1103 {
1104   char uptime_scan_oil[10];
1105   char uptime_mroute_add[10];
1106   char uptime_mroute_del[10];
1107
1108   pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now, qpim_scan_oil_last);
1109   pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now, qpim_mroute_add_last);
1110   pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now, qpim_mroute_del_last);
1111
1112   vty_out(vty,
1113           "Scan OIL - Last: %s  Events: %lld%s"
1114           "MFC Add  - Last: %s  Events: %lld%s"
1115           "MFC Del  - Last: %s  Events: %lld%s",
1116           uptime_scan_oil,   (long long) qpim_scan_oil_events,   VTY_NEWLINE,
1117           uptime_mroute_add, (long long) qpim_mroute_add_events, VTY_NEWLINE,
1118           uptime_mroute_del, (long long) qpim_mroute_del_events, VTY_NEWLINE);
1119 }
1120
1121 static void pim_show_rpf(struct vty *vty)
1122 {
1123   struct listnode     *up_node;
1124   struct pim_upstream *up;
1125   time_t               now = pim_time_monotonic_sec();
1126
1127   show_rpf_refresh_stats(vty, now);
1128
1129   vty_out(vty, "%s", VTY_NEWLINE);
1130
1131   vty_out(vty,
1132           "Source          Group           RpfIface RpfAddress      RibNextHop      Metric Pref%s",
1133           VTY_NEWLINE);
1134
1135   for (ALL_LIST_ELEMENTS_RO(qpim_upstream_list, up_node, up)) {
1136     char src_str[100];
1137     char grp_str[100];
1138     char rpf_addr_str[100];
1139     char rib_nexthop_str[100];
1140     const char *rpf_ifname;
1141     struct pim_rpf  *rpf = &up->rpf;
1142     
1143     pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
1144     pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
1145     pim_inet4_dump("<rpf?>", rpf->rpf_addr, rpf_addr_str, sizeof(rpf_addr_str));
1146     pim_inet4_dump("<nexthop?>", rpf->source_nexthop.mrib_nexthop_addr, rib_nexthop_str, sizeof(rib_nexthop_str));
1147     
1148     rpf_ifname = rpf->source_nexthop.interface ? rpf->source_nexthop.interface->name : "<ifname?>";
1149     
1150     vty_out(vty, "%-15s %-15s %-8s %-15s %-15s %6d %4d%s",
1151             src_str,
1152             grp_str,
1153             rpf_ifname,
1154             rpf_addr_str,
1155             rib_nexthop_str,
1156             rpf->source_nexthop.mrib_route_metric,
1157             rpf->source_nexthop.mrib_metric_preference,
1158             VTY_NEWLINE);
1159   }
1160 }
1161
1162 static void igmp_show_querier(struct vty *vty)
1163 {
1164   struct listnode  *node;
1165   struct interface *ifp;
1166
1167   vty_out(vty, "Interface Address         Querier StartCount Query-Timer Other-Timer%s", VTY_NEWLINE);
1168
1169   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
1170     struct pim_interface *pim_ifp = ifp->info;
1171     struct listnode  *sock_node;
1172     struct igmp_sock *igmp;
1173     
1174     if (!pim_ifp)
1175       continue;
1176
1177     for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1178       char query_hhmmss[10];
1179       char other_hhmmss[10];
1180
1181       pim_time_timer_to_hhmmss(query_hhmmss, sizeof(query_hhmmss), igmp->t_igmp_query_timer);
1182       pim_time_timer_to_hhmmss(other_hhmmss, sizeof(other_hhmmss), igmp->t_other_querier_timer);
1183
1184       vty_out(vty, "%-9s %-15s %-7s %10d %11s %11s%s",
1185               ifp->name,
1186               inet_ntoa(igmp->ifaddr),
1187               igmp->t_igmp_query_timer ? "THIS" : "OTHER",
1188               igmp->startup_query_count,
1189               query_hhmmss,
1190               other_hhmmss,
1191               VTY_NEWLINE);
1192     }
1193   }
1194 }
1195
1196 static void igmp_show_groups(struct vty *vty)
1197 {
1198   struct listnode  *ifnode;
1199   struct interface *ifp;
1200   time_t            now;
1201
1202   now = pim_time_monotonic_sec();
1203
1204   vty_out(vty, "Interface Address         Group           Mode Timer    Srcs V Uptime  %s", VTY_NEWLINE);
1205
1206   /* scan interfaces */
1207   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1208     struct pim_interface *pim_ifp = ifp->info;
1209     struct listnode  *sock_node;
1210     struct igmp_sock *igmp;
1211     
1212     if (!pim_ifp)
1213       continue;
1214     
1215     /* scan igmp sockets */
1216     for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1217       char ifaddr_str[100];
1218       struct listnode *grpnode;
1219       struct igmp_group *grp;
1220
1221       pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1222
1223       /* scan igmp groups */
1224       for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1225         char group_str[100];
1226         char hhmmss[10];
1227         char uptime[10];
1228
1229         pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1230         pim_time_timer_to_hhmmss(hhmmss, sizeof(hhmmss), grp->t_group_timer);
1231         pim_time_uptime(uptime, sizeof(uptime), now - grp->group_creation);
1232
1233         vty_out(vty, "%-9s %-15s %-15s %4s %8s %4d %d %8s%s",
1234                 ifp->name,
1235                 ifaddr_str,
1236                 group_str,
1237                 grp->group_filtermode_isexcl ? "EXCL" : "INCL",
1238                 hhmmss,
1239                 grp->group_source_list ? listcount(grp->group_source_list) : 0,
1240                 igmp_group_compat_mode(igmp, grp),
1241                 uptime,
1242                 VTY_NEWLINE);
1243
1244       } /* scan igmp groups */
1245     } /* scan igmp sockets */
1246   } /* scan interfaces */
1247 }
1248
1249 static void igmp_show_group_retransmission(struct vty *vty)
1250 {
1251   struct listnode  *ifnode;
1252   struct interface *ifp;
1253
1254   vty_out(vty, "Interface Address         Group           RetTimer Counter RetSrcs%s", VTY_NEWLINE);
1255
1256   /* scan interfaces */
1257   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1258     struct pim_interface *pim_ifp = ifp->info;
1259     struct listnode  *sock_node;
1260     struct igmp_sock *igmp;
1261     
1262     if (!pim_ifp)
1263       continue;
1264     
1265     /* scan igmp sockets */
1266     for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1267       char ifaddr_str[100];
1268       struct listnode *grpnode;
1269       struct igmp_group *grp;
1270
1271       pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1272
1273       /* scan igmp groups */
1274       for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1275         char group_str[100];
1276         char grp_retr_mmss[10];
1277         struct listnode    *src_node;
1278         struct igmp_source *src;
1279         int grp_retr_sources = 0;
1280
1281         pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1282         pim_time_timer_to_mmss(grp_retr_mmss, sizeof(grp_retr_mmss), grp->t_group_query_retransmit_timer);
1283
1284
1285         /* count group sources with retransmission state */
1286         for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) {
1287           if (src->source_query_retransmit_count > 0) {
1288             ++grp_retr_sources;
1289           }
1290         }
1291
1292         vty_out(vty, "%-9s %-15s %-15s %-8s %7d %7d%s",
1293                 ifp->name,
1294                 ifaddr_str,
1295                 group_str,
1296                 grp_retr_mmss,
1297                 grp->group_specific_query_retransmit_count,
1298                 grp_retr_sources,
1299                 VTY_NEWLINE);
1300
1301       } /* scan igmp groups */
1302     } /* scan igmp sockets */
1303   } /* scan interfaces */
1304 }
1305
1306 static void igmp_show_parameters(struct vty *vty)
1307 {
1308   struct listnode  *ifnode;
1309   struct interface *ifp;
1310
1311   vty_out(vty,
1312           "QRV: Robustness Variable             SQI: Startup Query Interval%s"
1313           "QQI: Query Interval                  OQPI: Other Querier Present Interval%s"
1314           "QRI: Query Response Interval         LMQT: Last Member Query Time%s"
1315           "GMI: Group Membership Interval       OHPI: Older Host Present Interval%s%s",
1316           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
1317
1318   vty_out(vty,
1319           "Interface Address         QRV QQI QRI   GMI   SQI OQPI  LMQT  OHPI %s",
1320           VTY_NEWLINE);
1321
1322   /* scan interfaces */
1323   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1324     struct pim_interface *pim_ifp = ifp->info;
1325     struct listnode  *sock_node;
1326     struct igmp_sock *igmp;
1327     
1328     if (!pim_ifp)
1329       continue;
1330     
1331     /* scan igmp sockets */
1332     for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1333       char ifaddr_str[100];
1334       long gmi_dsec;  /* Group Membership Interval */
1335       long oqpi_dsec; /* Other Querier Present Interval */
1336       int  sqi;
1337       long lmqt_dsec;
1338       long ohpi_dsec;
1339       long qri_dsec;
1340
1341       pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1342
1343       gmi_dsec = PIM_IGMP_GMI_MSEC(igmp->querier_robustness_variable,
1344                                    igmp->querier_query_interval,
1345                                    pim_ifp->igmp_query_max_response_time_dsec) / 100;
1346
1347       sqi = PIM_IGMP_SQI(pim_ifp->igmp_default_query_interval);
1348
1349       oqpi_dsec = PIM_IGMP_OQPI_MSEC(igmp->querier_robustness_variable,
1350                                      igmp->querier_query_interval,
1351                                      pim_ifp->igmp_query_max_response_time_dsec) / 100;
1352
1353       lmqt_dsec = PIM_IGMP_LMQT_MSEC(pim_ifp->igmp_query_max_response_time_dsec,
1354                                      igmp->querier_robustness_variable) / 100;
1355
1356       ohpi_dsec = PIM_IGMP_OHPI_DSEC(igmp->querier_robustness_variable,
1357                                      igmp->querier_query_interval,
1358                                      pim_ifp->igmp_query_max_response_time_dsec);
1359
1360       qri_dsec = pim_ifp->igmp_query_max_response_time_dsec;
1361
1362       vty_out(vty,
1363               "%-9s %-15s %3d %3d %3ld.%ld %3ld.%ld %3d %3ld.%ld %3ld.%ld %3ld.%ld%s",
1364               ifp->name,
1365               ifaddr_str,
1366               igmp->querier_robustness_variable,
1367               igmp->querier_query_interval,
1368               qri_dsec / 10, qri_dsec % 10,
1369               gmi_dsec / 10, gmi_dsec % 10,
1370               sqi,
1371               oqpi_dsec / 10, oqpi_dsec % 10,
1372               lmqt_dsec / 10, lmqt_dsec % 10,
1373               ohpi_dsec / 10, ohpi_dsec % 10,
1374               VTY_NEWLINE);
1375
1376     } /* scan igmp sockets */
1377   } /* scan interfaces */
1378 }
1379
1380 static void igmp_show_sources(struct vty *vty)
1381 {
1382   struct listnode  *ifnode;
1383   struct interface *ifp;
1384   time_t            now;
1385
1386   now = pim_time_monotonic_sec();
1387
1388   vty_out(vty, "Interface Address         Group           Source          Timer Fwd Uptime  %s", VTY_NEWLINE);
1389
1390   /* scan interfaces */
1391   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1392     struct pim_interface *pim_ifp = ifp->info;
1393     struct listnode  *sock_node;
1394     struct igmp_sock *igmp;
1395     
1396     if (!pim_ifp)
1397       continue;
1398     
1399     /* scan igmp sockets */
1400     for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1401       char ifaddr_str[100];
1402       struct listnode   *grpnode;
1403       struct igmp_group *grp;
1404
1405       pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1406
1407       /* scan igmp groups */
1408       for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1409         char group_str[100];
1410         struct listnode    *srcnode;
1411         struct igmp_source *src;
1412
1413         pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1414         
1415         /* scan group sources */
1416         for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
1417           char source_str[100];
1418           char mmss[10];
1419           char uptime[10];
1420
1421           pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str));
1422
1423           pim_time_timer_to_mmss(mmss, sizeof(mmss), src->t_source_timer);
1424
1425           pim_time_uptime(uptime, sizeof(uptime), now - src->source_creation);
1426
1427           vty_out(vty, "%-9s %-15s %-15s %-15s %5s %3s %8s%s",
1428                   ifp->name,
1429                   ifaddr_str,
1430                   group_str,
1431                   source_str,
1432                   mmss,
1433                   IGMP_SOURCE_TEST_FORWARDING(src->source_flags) ? "Y" : "N",
1434                   uptime,
1435                   VTY_NEWLINE);
1436           
1437         } /* scan group sources */
1438       } /* scan igmp groups */
1439     } /* scan igmp sockets */
1440   } /* scan interfaces */
1441 }
1442
1443 static void igmp_show_source_retransmission(struct vty *vty)
1444 {
1445   struct listnode  *ifnode;
1446   struct interface *ifp;
1447
1448   vty_out(vty, "Interface Address         Group           Source          Counter%s", VTY_NEWLINE);
1449
1450   /* scan interfaces */
1451   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
1452     struct pim_interface *pim_ifp = ifp->info;
1453     struct listnode  *sock_node;
1454     struct igmp_sock *igmp;
1455     
1456     if (!pim_ifp)
1457       continue;
1458     
1459     /* scan igmp sockets */
1460     for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
1461       char ifaddr_str[100];
1462       struct listnode   *grpnode;
1463       struct igmp_group *grp;
1464
1465       pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
1466
1467       /* scan igmp groups */
1468       for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode, grp)) {
1469         char group_str[100];
1470         struct listnode    *srcnode;
1471         struct igmp_source *src;
1472
1473         pim_inet4_dump("<group?>", grp->group_addr, group_str, sizeof(group_str));
1474         
1475         /* scan group sources */
1476         for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode, src)) {
1477           char source_str[100];
1478
1479           pim_inet4_dump("<source?>", src->source_addr, source_str, sizeof(source_str));
1480
1481           vty_out(vty, "%-9s %-15s %-15s %-15s %7d%s",
1482                   ifp->name,
1483                   ifaddr_str,
1484                   group_str,
1485                   source_str,
1486                   src->source_query_retransmit_count,
1487                   VTY_NEWLINE);
1488           
1489         } /* scan group sources */
1490       } /* scan igmp groups */
1491     } /* scan igmp sockets */
1492   } /* scan interfaces */
1493 }
1494
1495 static void clear_igmp_interfaces()
1496 {
1497   struct listnode  *ifnode;
1498   struct listnode  *ifnextnode;
1499   struct interface *ifp;
1500
1501   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
1502     pim_if_addr_del_all_igmp(ifp);
1503   }
1504
1505   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
1506     pim_if_addr_add_all(ifp);
1507   }
1508 }
1509
1510 static void clear_pim_interfaces()
1511 {
1512   struct listnode  *ifnode;
1513   struct listnode  *ifnextnode;
1514   struct interface *ifp;
1515
1516   for (ALL_LIST_ELEMENTS(iflist, ifnode, ifnextnode, ifp)) {
1517     if (ifp->info) {
1518       pim_neighbor_delete_all(ifp, "interface cleared");
1519     }
1520   }
1521 }
1522
1523 static void clear_interfaces()
1524 {
1525   clear_igmp_interfaces();
1526   clear_pim_interfaces();
1527 }
1528
1529 DEFUN (pim_interface,
1530        pim_interface_cmd,
1531        "interface IFNAME",
1532        "Select an interface to configure\n"
1533        "Interface's name\n")
1534 {
1535   struct interface *ifp;
1536   const char *ifname = argv[0];
1537   size_t sl;
1538
1539   sl = strlen(ifname);
1540   if (sl > INTERFACE_NAMSIZ) {
1541     vty_out(vty, "%% Interface name %s is invalid: length exceeds "
1542             "%d characters%s",
1543             ifname, INTERFACE_NAMSIZ, VTY_NEWLINE);
1544     return CMD_WARNING;
1545   }
1546
1547   ifp = if_lookup_by_name_len(ifname, sl);
1548   if (!ifp) {
1549     vty_out(vty, "%% Interface %s does not exist%s", ifname, VTY_NEWLINE);
1550
1551     /* Returning here would prevent pimd from booting when there are
1552        interface commands in pimd.conf, since all interfaces are
1553        unknown at pimd boot time (the zebra daemon has not been
1554        contacted for interface discovery). */
1555     
1556     ifp = if_get_by_name_len(ifname, sl);
1557     if (!ifp) {
1558       vty_out(vty, "%% Could not create interface %s%s", ifname, VTY_NEWLINE);
1559       return CMD_WARNING;
1560     }
1561   }
1562
1563   vty->index = ifp;
1564   vty->node = INTERFACE_NODE;
1565
1566   return CMD_SUCCESS;
1567 }
1568
1569 DEFUN (clear_ip_interfaces,
1570        clear_ip_interfaces_cmd,
1571        "clear ip interfaces",
1572        CLEAR_STR
1573        IP_STR
1574        "Reset interfaces\n")
1575 {
1576   clear_interfaces();
1577
1578   return CMD_SUCCESS;
1579 }
1580
1581 DEFUN (clear_ip_igmp_interfaces,
1582        clear_ip_igmp_interfaces_cmd,
1583        "clear ip igmp interfaces",
1584        CLEAR_STR
1585        IP_STR
1586        CLEAR_IP_IGMP_STR
1587        "Reset IGMP interfaces\n")
1588 {
1589   clear_igmp_interfaces();
1590
1591   return CMD_SUCCESS;
1592 }
1593
1594 static void mroute_add_all()
1595 {
1596   struct listnode    *node;
1597   struct channel_oil *c_oil;
1598
1599   for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
1600     if (pim_mroute_add(&c_oil->oil)) {
1601       /* just log warning */
1602       char source_str[100];
1603       char group_str[100];
1604       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
1605       pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
1606       zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
1607                 __FILE__, __PRETTY_FUNCTION__,
1608                 source_str, group_str);
1609     }
1610   }
1611 }
1612
1613 static void mroute_del_all()
1614 {
1615   struct listnode    *node;
1616   struct channel_oil *c_oil;
1617
1618   for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
1619     if (pim_mroute_del(&c_oil->oil)) {
1620       /* just log warning */
1621       char source_str[100];
1622       char group_str[100];
1623       pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
1624       pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
1625       zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
1626                 __FILE__, __PRETTY_FUNCTION__,
1627                 source_str, group_str);
1628     }
1629   }
1630 }
1631
1632 static void static_mroute_add_all()
1633 {
1634   struct listnode     *node;
1635   struct static_route *s_route;
1636
1637   for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
1638     if (pim_mroute_add(&s_route->mc)) {
1639       /* just log warning */
1640       char source_str[100];
1641       char group_str[100];
1642       pim_inet4_dump("<source?>", s_route->mc.mfcc_origin, source_str, sizeof(source_str));
1643       pim_inet4_dump("<group?>", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str));
1644       zlog_warn("%s %s: (S,G)=(%s,%s) failure writing MFC",
1645       __FILE__, __PRETTY_FUNCTION__,
1646       source_str, group_str);
1647     }
1648   }
1649 }
1650
1651 static void static_mroute_del_all()
1652 {
1653    struct listnode     *node;
1654    struct static_route *s_route;
1655
1656    for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
1657      if (pim_mroute_del(&s_route->mc)) {
1658        /* just log warning */
1659        char source_str[100];
1660        char group_str[100];
1661        pim_inet4_dump("<source?>", s_route->mc.mfcc_origin, source_str, sizeof(source_str));
1662        pim_inet4_dump("<group?>", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str));
1663        zlog_warn("%s %s: (S,G)=(%s,%s) failure clearing MFC",
1664        __FILE__, __PRETTY_FUNCTION__,
1665        source_str, group_str);
1666      }
1667    }
1668 }
1669
1670 DEFUN (clear_ip_mroute,
1671        clear_ip_mroute_cmd,
1672        "clear ip mroute",
1673        CLEAR_STR
1674        IP_STR
1675        "Reset multicast routes\n")
1676 {
1677   mroute_del_all();
1678   mroute_add_all();
1679
1680   return CMD_SUCCESS;
1681 }
1682
1683 DEFUN (clear_ip_pim_interfaces,
1684        clear_ip_pim_interfaces_cmd,
1685        "clear ip pim interfaces",
1686        CLEAR_STR
1687        IP_STR
1688        CLEAR_IP_PIM_STR
1689        "Reset PIM interfaces\n")
1690 {
1691   clear_pim_interfaces();
1692
1693   return CMD_SUCCESS;
1694 }
1695
1696 DEFUN (clear_ip_pim_oil,
1697        clear_ip_pim_oil_cmd,
1698        "clear ip pim oil",
1699        CLEAR_STR
1700        IP_STR
1701        CLEAR_IP_PIM_STR
1702        "Rescan PIM OIL (output interface list)\n")
1703 {
1704   pim_scan_oil();
1705
1706   return CMD_SUCCESS;
1707 }
1708
1709 DEFUN (show_ip_igmp_interface,
1710        show_ip_igmp_interface_cmd,
1711        "show ip igmp interface",
1712        SHOW_STR
1713        IP_STR
1714        IGMP_STR
1715        "IGMP interface information\n")
1716 {
1717   igmp_show_interfaces(vty);
1718
1719   return CMD_SUCCESS;
1720 }
1721
1722 DEFUN (show_ip_igmp_join,
1723        show_ip_igmp_join_cmd,
1724        "show ip igmp join",
1725        SHOW_STR
1726        IP_STR
1727        IGMP_STR
1728        "IGMP static join information\n")
1729 {
1730   igmp_show_interface_join(vty);
1731
1732   return CMD_SUCCESS;
1733 }
1734
1735 DEFUN (show_ip_igmp_groups,
1736        show_ip_igmp_groups_cmd,
1737        "show ip igmp groups",
1738        SHOW_STR
1739        IP_STR
1740        IGMP_STR
1741        IGMP_GROUP_STR)
1742 {
1743   igmp_show_groups(vty);
1744
1745   return CMD_SUCCESS;
1746 }
1747
1748 DEFUN (show_ip_igmp_groups_retransmissions,
1749        show_ip_igmp_groups_retransmissions_cmd,
1750        "show ip igmp groups retransmissions",
1751        SHOW_STR
1752        IP_STR
1753        IGMP_STR
1754        IGMP_GROUP_STR
1755        "IGMP group retransmissions\n")
1756 {
1757   igmp_show_group_retransmission(vty);
1758
1759   return CMD_SUCCESS;
1760 }
1761
1762 DEFUN (show_ip_igmp_parameters,
1763        show_ip_igmp_parameters_cmd,
1764        "show ip igmp parameters",
1765        SHOW_STR
1766        IP_STR
1767        IGMP_STR
1768        "IGMP parameters information\n")
1769 {
1770   igmp_show_parameters(vty);
1771
1772   return CMD_SUCCESS;
1773 }
1774
1775 DEFUN (show_ip_igmp_sources,
1776        show_ip_igmp_sources_cmd,
1777        "show ip igmp sources",
1778        SHOW_STR
1779        IP_STR
1780        IGMP_STR
1781        IGMP_SOURCE_STR)
1782 {
1783   igmp_show_sources(vty);
1784
1785   return CMD_SUCCESS;
1786 }
1787
1788 DEFUN (show_ip_igmp_sources_retransmissions,
1789        show_ip_igmp_sources_retransmissions_cmd,
1790        "show ip igmp sources retransmissions",
1791        SHOW_STR
1792        IP_STR
1793        IGMP_STR
1794        IGMP_SOURCE_STR
1795        "IGMP source retransmissions\n")
1796 {
1797   igmp_show_source_retransmission(vty);
1798
1799   return CMD_SUCCESS;
1800 }
1801
1802 DEFUN (show_ip_igmp_querier,
1803        show_ip_igmp_querier_cmd,
1804        "show ip igmp querier",
1805        SHOW_STR
1806        IP_STR
1807        IGMP_STR
1808        "IGMP querier information\n")
1809 {
1810   igmp_show_querier(vty);
1811
1812   return CMD_SUCCESS;
1813 }
1814
1815 DEFUN (show_ip_pim_address,
1816        show_ip_pim_address_cmd,
1817        "show ip pim address",
1818        SHOW_STR
1819        IP_STR
1820        PIM_STR
1821        "PIM interface address\n")
1822 {
1823   show_interface_address(vty);
1824
1825   return CMD_SUCCESS;
1826 }
1827
1828 DEFUN (show_ip_pim_assert,
1829        show_ip_pim_assert_cmd,
1830        "show ip pim assert",
1831        SHOW_STR
1832        IP_STR
1833        PIM_STR
1834        "PIM interface assert\n")
1835 {
1836   pim_show_assert(vty);
1837
1838   return CMD_SUCCESS;
1839 }
1840
1841 DEFUN (show_ip_pim_assert_internal,
1842        show_ip_pim_assert_internal_cmd,
1843        "show ip pim assert-internal",
1844        SHOW_STR
1845        IP_STR
1846        PIM_STR
1847        "PIM interface internal assert state\n")
1848 {
1849   pim_show_assert_internal(vty);
1850
1851   return CMD_SUCCESS;
1852 }
1853
1854 DEFUN (show_ip_pim_assert_metric,
1855        show_ip_pim_assert_metric_cmd,
1856        "show ip pim assert-metric",
1857        SHOW_STR
1858        IP_STR
1859        PIM_STR
1860        "PIM interface assert metric\n")
1861 {
1862   pim_show_assert_metric(vty);
1863
1864   return CMD_SUCCESS;
1865 }
1866
1867 DEFUN (show_ip_pim_assert_winner_metric,
1868        show_ip_pim_assert_winner_metric_cmd,
1869        "show ip pim assert-winner-metric",
1870        SHOW_STR
1871        IP_STR
1872        PIM_STR
1873        "PIM interface assert winner metric\n")
1874 {
1875   pim_show_assert_winner_metric(vty);
1876
1877   return CMD_SUCCESS;
1878 }
1879
1880 DEFUN (show_ip_pim_dr,
1881        show_ip_pim_dr_cmd,
1882        "show ip pim designated-router",
1883        SHOW_STR
1884        IP_STR
1885        PIM_STR
1886        "PIM interface designated router\n")
1887 {
1888   pim_show_dr(vty);
1889
1890   return CMD_SUCCESS;
1891 }
1892
1893 DEFUN (show_ip_pim_hello,
1894        show_ip_pim_hello_cmd,
1895        "show ip pim hello",
1896        SHOW_STR
1897        IP_STR
1898        PIM_STR
1899        "PIM interface hello information\n")
1900 {
1901   pim_show_hello(vty);
1902
1903   return CMD_SUCCESS;
1904 }
1905
1906 DEFUN (show_ip_pim_interface,
1907        show_ip_pim_interface_cmd,
1908        "show ip pim interface",
1909        SHOW_STR
1910        IP_STR
1911        PIM_STR
1912        "PIM interface information\n")
1913 {
1914   pim_show_interfaces(vty);
1915
1916   return CMD_SUCCESS;
1917 }
1918
1919 DEFUN (show_ip_pim_join,
1920        show_ip_pim_join_cmd,
1921        "show ip pim join",
1922        SHOW_STR
1923        IP_STR
1924        PIM_STR
1925        "PIM interface join information\n")
1926 {
1927   pim_show_join(vty);
1928
1929   return CMD_SUCCESS;
1930 }
1931
1932 DEFUN (show_ip_pim_lan_prune_delay,
1933        show_ip_pim_lan_prune_delay_cmd,
1934        "show ip pim lan-prune-delay",
1935        SHOW_STR
1936        IP_STR
1937        PIM_STR
1938        "PIM neighbors LAN prune delay parameters\n")
1939 {
1940   pim_show_lan_prune_delay(vty);
1941
1942   return CMD_SUCCESS;
1943 }
1944
1945 DEFUN (show_ip_pim_local_membership,
1946        show_ip_pim_local_membership_cmd,
1947        "show ip pim local-membership",
1948        SHOW_STR
1949        IP_STR
1950        PIM_STR
1951        "PIM interface local-membership\n")
1952 {
1953   pim_show_membership(vty);
1954
1955   return CMD_SUCCESS;
1956 }
1957
1958 DEFUN (show_ip_pim_jp_override_interval,
1959        show_ip_pim_jp_override_interval_cmd,
1960        "show ip pim jp-override-interval",
1961        SHOW_STR
1962        IP_STR
1963        PIM_STR
1964        "PIM interface J/P override interval\n")
1965 {
1966   pim_show_jp_override_interval(vty);
1967
1968   return CMD_SUCCESS;
1969 }
1970
1971 DEFUN (show_ip_pim_neighbor,
1972        show_ip_pim_neighbor_cmd,
1973        "show ip pim neighbor",
1974        SHOW_STR
1975        IP_STR
1976        PIM_STR
1977        "PIM neighbor information\n")
1978 {
1979   pim_show_neighbors(vty);
1980
1981   return CMD_SUCCESS;
1982 }
1983
1984 DEFUN (show_ip_pim_secondary,
1985        show_ip_pim_secondary_cmd,
1986        "show ip pim secondary",
1987        SHOW_STR
1988        IP_STR
1989        PIM_STR
1990        "PIM neighbor addresses\n")
1991 {
1992   pim_show_neighbors_secondary(vty);
1993
1994   return CMD_SUCCESS;
1995 }
1996
1997 DEFUN (show_ip_pim_upstream,
1998        show_ip_pim_upstream_cmd,
1999        "show ip pim upstream",
2000        SHOW_STR
2001        IP_STR
2002        PIM_STR
2003        "PIM upstream information\n")
2004 {
2005   pim_show_upstream(vty);
2006
2007   return CMD_SUCCESS;
2008 }
2009
2010 DEFUN (show_ip_pim_upstream_join_desired,
2011        show_ip_pim_upstream_join_desired_cmd,
2012        "show ip pim upstream-join-desired",
2013        SHOW_STR
2014        IP_STR
2015        PIM_STR
2016        "PIM upstream join-desired\n")
2017 {
2018   pim_show_join_desired(vty);
2019
2020   return CMD_SUCCESS;
2021 }
2022
2023 DEFUN (show_ip_pim_upstream_rpf,
2024        show_ip_pim_upstream_rpf_cmd,
2025        "show ip pim upstream-rpf",
2026        SHOW_STR
2027        IP_STR
2028        PIM_STR
2029        "PIM upstream source rpf\n")
2030 {
2031   pim_show_upstream_rpf(vty);
2032
2033   return CMD_SUCCESS;
2034 }
2035
2036 DEFUN (show_ip_pim_rpf,
2037        show_ip_pim_rpf_cmd,
2038        "show ip pim rpf",
2039        SHOW_STR
2040        IP_STR
2041        PIM_STR
2042        "PIM cached source rpf information\n")
2043 {
2044   pim_show_rpf(vty);
2045
2046   return CMD_SUCCESS;
2047 }
2048
2049 static void show_multicast_interfaces(struct vty *vty)
2050 {
2051   struct listnode  *node;
2052   struct interface *ifp;
2053
2054   vty_out(vty, "%s", VTY_NEWLINE);
2055   
2056   vty_out(vty, "Interface Address         ifi Vif  PktsIn PktsOut    BytesIn   BytesOut%s",
2057           VTY_NEWLINE);
2058
2059   for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) {
2060     struct pim_interface *pim_ifp;
2061     struct in_addr ifaddr;
2062     struct sioc_vif_req vreq;
2063
2064     pim_ifp = ifp->info;
2065     
2066     if (!pim_ifp)
2067       continue;
2068
2069     memset(&vreq, 0, sizeof(vreq));
2070     vreq.vifi = pim_ifp->mroute_vif_index;
2071
2072     if (ioctl(qpim_mroute_socket_fd, SIOCGETVIFCNT, &vreq)) {
2073       zlog_warn("ioctl(SIOCGETVIFCNT=%lu) failure for interface %s vif_index=%d: errno=%d: %s%s",
2074                 (unsigned long)SIOCGETVIFCNT,
2075                 ifp->name,
2076                 pim_ifp->mroute_vif_index,
2077                 errno,
2078                 safe_strerror(errno),
2079                 VTY_NEWLINE);
2080     }
2081
2082     ifaddr = pim_ifp->primary_address;
2083
2084     vty_out(vty, "%-9s %-15s %3d %3d %7lu %7lu %10lu %10lu%s",
2085             ifp->name,
2086             inet_ntoa(ifaddr),
2087             ifp->ifindex,
2088             pim_ifp->mroute_vif_index,
2089             vreq.icount,
2090             vreq.ocount,
2091             vreq.ibytes,
2092             vreq.obytes,
2093             VTY_NEWLINE);
2094   }
2095 }
2096
2097 DEFUN (show_ip_multicast,
2098        show_ip_multicast_cmd,
2099        "show ip multicast",
2100        SHOW_STR
2101        IP_STR
2102        "Multicast global information\n")
2103 {
2104   time_t now = pim_time_monotonic_sec();
2105
2106   if (PIM_MROUTE_IS_ENABLED) {
2107     char uptime[10];
2108
2109     vty_out(vty, "Mroute socket descriptor: %d%s",
2110             qpim_mroute_socket_fd,
2111             VTY_NEWLINE);
2112
2113     pim_time_uptime(uptime, sizeof(uptime), now - qpim_mroute_socket_creation);
2114     vty_out(vty, "Mroute socket uptime: %s%s",
2115             uptime,
2116             VTY_NEWLINE);
2117   }
2118   else {
2119     vty_out(vty, "Multicast disabled%s",
2120             VTY_NEWLINE);
2121   }
2122
2123   vty_out(vty, "%s", VTY_NEWLINE);
2124   vty_out(vty, "Zclient update socket: ");
2125   if (qpim_zclient_update) {
2126     vty_out(vty, "%d failures=%d%s", qpim_zclient_update->sock,
2127             qpim_zclient_update->fail, VTY_NEWLINE);
2128   }
2129   else {
2130     vty_out(vty, "<null zclient>%s", VTY_NEWLINE);
2131   }
2132   vty_out(vty, "Zclient lookup socket: ");
2133   if (qpim_zclient_lookup) {
2134     vty_out(vty, "%d failures=%d%s", qpim_zclient_lookup->sock,
2135             qpim_zclient_lookup->fail, VTY_NEWLINE);
2136   }
2137   else {
2138     vty_out(vty, "<null zclient>%s", VTY_NEWLINE);
2139   }
2140
2141   vty_out(vty, "%s", VTY_NEWLINE);
2142   vty_out(vty, "Current highest VifIndex: %d%s",
2143           qpim_mroute_oif_highest_vif_index,
2144           VTY_NEWLINE);
2145   vty_out(vty, "Maximum highest VifIndex: %d%s",
2146           MAXVIFS - 1,
2147           VTY_NEWLINE);
2148
2149   vty_out(vty, "%s", VTY_NEWLINE);
2150   vty_out(vty, "Upstream Join Timer: %d secs%s",
2151           qpim_t_periodic,
2152           VTY_NEWLINE);
2153   vty_out(vty, "Join/Prune Holdtime: %d secs%s",
2154           PIM_JP_HOLDTIME,
2155           VTY_NEWLINE);
2156
2157   vty_out(vty, "%s", VTY_NEWLINE);
2158
2159   show_rpf_refresh_stats(vty, now);
2160
2161   vty_out(vty, "%s", VTY_NEWLINE);
2162
2163   show_scan_oil_stats(vty, now);
2164
2165   show_multicast_interfaces(vty);
2166   
2167   return CMD_SUCCESS;
2168 }
2169
2170 static void show_mroute(struct vty *vty)
2171 {
2172   struct listnode    *node;
2173   struct channel_oil *c_oil;
2174   struct static_route *s_route;
2175   time_t              now;
2176
2177   vty_out(vty, "Proto: I=IGMP P=PIM S=STATIC%s%s", VTY_NEWLINE, VTY_NEWLINE);
2178   
2179   vty_out(vty, "Source          Group           Proto Input iVifI Output oVifI TTL Uptime  %s",
2180           VTY_NEWLINE);
2181
2182   now = pim_time_monotonic_sec();
2183
2184   /* print list of PIM and IGMP routes */
2185   for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
2186     char group_str[100]; 
2187     char source_str[100];
2188     int oif_vif_index;
2189
2190     pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2191     pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2192     
2193     for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) {
2194       struct interface *ifp_in;
2195       struct interface *ifp_out;
2196       char oif_uptime[10];
2197       int ttl;
2198       char proto[5];
2199
2200       ttl = c_oil->oil.mfcc_ttls[oif_vif_index];
2201       if (ttl < 1)
2202         continue;
2203
2204       ifp_in  = pim_if_find_by_vif_index(c_oil->oil.mfcc_parent);
2205       ifp_out = pim_if_find_by_vif_index(oif_vif_index);
2206
2207       pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - c_oil->oif_creation[oif_vif_index]);
2208
2209       proto[0] = '\0';
2210       if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_PIM) {
2211         strcat(proto, "P");
2212       }
2213       if (c_oil->oif_flags[oif_vif_index] & PIM_OIF_FLAG_PROTO_IGMP) {
2214         strcat(proto, "I");
2215       }
2216
2217       vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s",
2218               source_str,
2219               group_str,
2220               proto,
2221               ifp_in ? ifp_in->name : "<iif?>",
2222               c_oil->oil.mfcc_parent,
2223               ifp_out ? ifp_out->name : "<oif?>",
2224               oif_vif_index,
2225               ttl,
2226               oif_uptime,
2227               VTY_NEWLINE);
2228     }
2229   }
2230
2231   /* Print list of static routes */
2232   for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
2233     char group_str[100];
2234     char source_str[100];
2235     int oif_vif_index;
2236
2237     pim_inet4_dump("<group?>", s_route->group, group_str, sizeof(group_str));
2238     pim_inet4_dump("<source?>", s_route->source, source_str, sizeof(source_str));
2239
2240     for (oif_vif_index = 0; oif_vif_index < MAXVIFS; ++oif_vif_index) {
2241       struct interface *ifp_in;
2242       struct interface *ifp_out;
2243       char oif_uptime[10];
2244       int ttl;
2245       char proto[5];
2246
2247       ttl = s_route->oif_ttls[oif_vif_index];
2248       if (ttl < 1)
2249          continue;
2250
2251       ifp_in  = pim_if_find_by_vif_index(s_route->iif);
2252       ifp_out = pim_if_find_by_vif_index(oif_vif_index);
2253
2254       pim_time_uptime(oif_uptime, sizeof(oif_uptime), now - s_route->creation[oif_vif_index]);
2255
2256       proto[0] = '\0';
2257       strcat(proto, "S");
2258
2259       vty_out(vty, "%-15s %-15s %-5s %-5s %5d %-6s %5d %3d %8s %s",
2260          source_str,
2261          group_str,
2262          proto,
2263          ifp_in ? ifp_in->name : "<iif?>",
2264          s_route->iif,
2265          ifp_out ? ifp_out->name : "<oif?>",
2266          oif_vif_index,
2267          ttl,
2268          oif_uptime,
2269          VTY_NEWLINE);
2270     }
2271   }
2272 }
2273
2274 DEFUN (show_ip_mroute,
2275        show_ip_mroute_cmd,
2276        "show ip mroute",
2277        SHOW_STR
2278        IP_STR
2279        MROUTE_STR)
2280 {
2281   show_mroute(vty);
2282   return CMD_SUCCESS;
2283 }
2284
2285 static void show_mroute_count(struct vty *vty)
2286 {
2287   struct listnode    *node;
2288   struct channel_oil *c_oil;
2289   struct static_route *s_route;
2290
2291   vty_out(vty, "%s", VTY_NEWLINE);
2292   
2293   vty_out(vty, "Source          Group           Packets      Bytes WrongIf  %s",
2294           VTY_NEWLINE);
2295
2296   /* Print PIM and IGMP route counts */
2297   for (ALL_LIST_ELEMENTS_RO(qpim_channel_oil_list, node, c_oil)) {
2298     char group_str[100]; 
2299     char source_str[100];
2300     struct sioc_sg_req sgreq;
2301
2302     memset(&sgreq, 0, sizeof(sgreq));
2303     sgreq.src = c_oil->oil.mfcc_origin;
2304     sgreq.grp = c_oil->oil.mfcc_mcastgrp;
2305
2306     pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
2307     pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
2308
2309     if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) {
2310       int e = errno;
2311       vty_out(vty,
2312               "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s%s",
2313               (unsigned long)SIOCGETSGCNT,
2314               source_str,
2315               group_str,
2316               e,
2317               safe_strerror(e),
2318               VTY_NEWLINE);           
2319       continue;
2320     }
2321     
2322     vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s",
2323             source_str,
2324             group_str,
2325             sgreq.pktcnt,
2326             sgreq.bytecnt,
2327             sgreq.wrong_if,
2328             VTY_NEWLINE);
2329   }
2330
2331    /* Print static route counts */
2332   for (ALL_LIST_ELEMENTS_RO(qpim_static_route_list, node, s_route)) {
2333     char group_str[100];
2334     char source_str[100];
2335     struct sioc_sg_req sgreq;
2336
2337     memset(&sgreq, 0, sizeof(sgreq));
2338     sgreq.src = s_route->mc.mfcc_origin;
2339     sgreq.grp = s_route->mc.mfcc_mcastgrp;
2340
2341     pim_inet4_dump("<group?>", s_route->mc.mfcc_mcastgrp, group_str, sizeof(group_str));
2342     pim_inet4_dump("<source?>", s_route->mc.mfcc_origin, source_str, sizeof(source_str));
2343
2344     if (ioctl(qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq)) {
2345       int e = errno;
2346       vty_out(vty,
2347          "ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s%s",
2348          /* note that typeof ioctl defs can vary across platforms, from
2349           * int, to unsigned int, to long unsigned int
2350           */
2351          (unsigned long)SIOCGETSGCNT,
2352          source_str,
2353          group_str,
2354          e,
2355          safe_strerror(e),
2356          VTY_NEWLINE);
2357       continue;
2358     }
2359
2360     vty_out(vty, "%-15s %-15s %7ld %10ld %7ld %s",
2361        source_str,
2362        group_str,
2363        sgreq.pktcnt,
2364        sgreq.bytecnt,
2365        sgreq.wrong_if,
2366        VTY_NEWLINE);
2367   }
2368 }
2369
2370 DEFUN (show_ip_mroute_count,
2371        show_ip_mroute_count_cmd,
2372        "show ip mroute count",
2373        SHOW_STR
2374        IP_STR
2375        MROUTE_STR
2376        "Route and packet count data\n")
2377 {
2378   show_mroute_count(vty);
2379   return CMD_SUCCESS;
2380 }
2381
2382 DEFUN (show_ip_rib,
2383        show_ip_rib_cmd,
2384        "show ip rib A.B.C.D",
2385        SHOW_STR
2386        IP_STR
2387        RIB_STR
2388        "Unicast address\n")
2389 {
2390   struct in_addr addr;
2391   const char *addr_str;
2392   struct pim_nexthop nexthop;
2393   char nexthop_addr_str[100];
2394   int result;
2395
2396   addr_str = argv[0];
2397   result = inet_pton(AF_INET, addr_str, &addr);
2398   if (result <= 0) {
2399     vty_out(vty, "Bad unicast address %s: errno=%d: %s%s",
2400             addr_str, errno, safe_strerror(errno), VTY_NEWLINE);
2401     return CMD_WARNING;
2402   }
2403
2404   if (pim_nexthop_lookup(&nexthop, addr)) {
2405     vty_out(vty, "Failure querying RIB nexthop for unicast address %s%s",
2406             addr_str, VTY_NEWLINE);
2407     return CMD_WARNING;
2408   }
2409
2410   vty_out(vty, "Address         NextHop         Interface Metric Preference%s",
2411           VTY_NEWLINE);
2412
2413   pim_inet4_dump("<nexthop?>", nexthop.mrib_nexthop_addr,
2414                  nexthop_addr_str, sizeof(nexthop_addr_str));
2415
2416   vty_out(vty, "%-15s %-15s %-9s %6d %10d%s",
2417           addr_str,
2418           nexthop_addr_str,
2419           nexthop.interface ? nexthop.interface->name : "<ifname?>",
2420           nexthop.mrib_route_metric,
2421           nexthop.mrib_metric_preference,
2422           VTY_NEWLINE);
2423
2424   return CMD_SUCCESS;
2425 }
2426
2427 static void show_ssmpingd(struct vty *vty)
2428 {
2429   struct listnode      *node;
2430   struct ssmpingd_sock *ss;
2431   time_t                now;
2432
2433   vty_out(vty, "Source          Socket Address          Port Uptime   Requests%s",
2434           VTY_NEWLINE);
2435
2436   if (!qpim_ssmpingd_list)
2437     return;
2438
2439   now = pim_time_monotonic_sec();
2440
2441   for (ALL_LIST_ELEMENTS_RO(qpim_ssmpingd_list, node, ss)) {
2442     char source_str[100];
2443     char ss_uptime[10];
2444     struct sockaddr_in bind_addr;
2445     socklen_t len = sizeof(bind_addr);
2446     char bind_addr_str[100];
2447
2448     pim_inet4_dump("<src?>", ss->source_addr, source_str, sizeof(source_str));
2449
2450     if (pim_socket_getsockname(ss->sock_fd, (struct sockaddr *) &bind_addr, &len)) {
2451       vty_out(vty, "%% Failure reading socket name for ssmpingd source %s on fd=%d%s",
2452               source_str, ss->sock_fd, VTY_NEWLINE);
2453     }
2454
2455     pim_inet4_dump("<addr?>", bind_addr.sin_addr, bind_addr_str, sizeof(bind_addr_str));
2456     pim_time_uptime(ss_uptime, sizeof(ss_uptime), now - ss->creation);
2457
2458     vty_out(vty, "%-15s %6d %-15s %5d %8s %8lld%s",
2459             source_str,
2460             ss->sock_fd,
2461             bind_addr_str,
2462             ntohs(bind_addr.sin_port),
2463             ss_uptime,
2464             (long long)ss->requests,
2465             VTY_NEWLINE);
2466   }
2467 }
2468
2469 DEFUN (show_ip_ssmpingd,
2470        show_ip_ssmpingd_cmd,
2471        "show ip ssmpingd",
2472        SHOW_STR
2473        IP_STR
2474        SHOW_SSMPINGD_STR)
2475 {
2476   show_ssmpingd(vty);
2477   return CMD_SUCCESS;
2478 }
2479
2480 DEFUN (ip_multicast_routing,
2481        ip_multicast_routing_cmd,
2482        PIM_CMD_IP_MULTICAST_ROUTING,
2483        IP_STR
2484        "Enable IP multicast forwarding\n")
2485 {
2486   pim_mroute_socket_enable();
2487   pim_if_add_vif_all();
2488   mroute_add_all();
2489   static_mroute_add_all();
2490   return CMD_SUCCESS;
2491 }
2492
2493 DEFUN (no_ip_multicast_routing,
2494        no_ip_multicast_routing_cmd,
2495        PIM_CMD_NO " " PIM_CMD_IP_MULTICAST_ROUTING,
2496        NO_STR
2497        IP_STR
2498        "Global IP configuration subcommands\n"
2499        "Enable IP multicast forwarding\n")
2500 {
2501   mroute_del_all();
2502   static_mroute_del_all();
2503   pim_if_del_vif_all();
2504   pim_mroute_socket_disable();
2505   return CMD_SUCCESS;
2506 }
2507
2508 DEFUN (ip_ssmpingd,
2509        ip_ssmpingd_cmd,
2510        "ip ssmpingd [A.B.C.D]",
2511        IP_STR
2512        CONF_SSMPINGD_STR
2513        "Source address\n")
2514 {
2515   int result;
2516   struct in_addr source_addr;
2517   const char *source_str = (argc > 0) ? argv[0] : "0.0.0.0";
2518
2519   result = inet_pton(AF_INET, source_str, &source_addr);
2520   if (result <= 0) {
2521     vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
2522             source_str, errno, safe_strerror(errno), VTY_NEWLINE);
2523     return CMD_WARNING;
2524   }
2525
2526   result = pim_ssmpingd_start(source_addr);
2527   if (result) {
2528     vty_out(vty, "%% Failure starting ssmpingd for source %s: %d%s",
2529             source_str, result, VTY_NEWLINE);
2530     return CMD_WARNING;
2531   }
2532
2533   return CMD_SUCCESS;
2534 }
2535
2536 DEFUN (no_ip_ssmpingd,
2537        no_ip_ssmpingd_cmd,
2538        "no ip ssmpingd [A.B.C.D]",
2539        NO_STR
2540        IP_STR
2541        CONF_SSMPINGD_STR
2542        "Source address\n")
2543 {
2544   int result;
2545   struct in_addr source_addr;
2546   const char *source_str = (argc > 0) ? argv[0] : "0.0.0.0";
2547
2548   result = inet_pton(AF_INET, source_str, &source_addr);
2549   if (result <= 0) {
2550     vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
2551             source_str, errno, safe_strerror(errno), VTY_NEWLINE);
2552     return CMD_WARNING;
2553   }
2554
2555   result = pim_ssmpingd_stop(source_addr);
2556   if (result) {
2557     vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d%s",
2558             source_str, result, VTY_NEWLINE);
2559     return CMD_WARNING;
2560   }
2561
2562   return CMD_SUCCESS;
2563 }
2564
2565 DEFUN (interface_ip_igmp,
2566        interface_ip_igmp_cmd,
2567        "ip igmp",
2568        IP_STR
2569        IFACE_IGMP_STR)
2570 {
2571   struct interface *ifp;
2572   struct pim_interface *pim_ifp;
2573
2574   ifp = vty->index;
2575   pim_ifp = ifp->info;
2576
2577   if (!pim_ifp) {
2578     pim_ifp = pim_if_new(ifp, 1 /* igmp=true */, 0 /* pim=false */);
2579     if (!pim_ifp) {
2580       vty_out(vty, "Could not enable IGMP on interface %s%s",
2581               ifp->name, VTY_NEWLINE);
2582       return CMD_WARNING;
2583     }
2584   }
2585   else {
2586     PIM_IF_DO_IGMP(pim_ifp->options);
2587   }
2588
2589   pim_if_addr_add_all(ifp);
2590   pim_if_membership_refresh(ifp);
2591
2592   return CMD_SUCCESS;
2593 }
2594
2595 DEFUN (interface_no_ip_igmp,
2596        interface_no_ip_igmp_cmd,
2597        "no ip igmp",
2598        NO_STR
2599        IP_STR
2600        IFACE_IGMP_STR)
2601 {
2602   struct interface *ifp;
2603   struct pim_interface *pim_ifp;
2604
2605   ifp = vty->index;
2606   pim_ifp = ifp->info;
2607   if (!pim_ifp)
2608     return CMD_SUCCESS;
2609
2610   PIM_IF_DONT_IGMP(pim_ifp->options);
2611
2612   pim_if_membership_clear(ifp);
2613
2614   pim_if_addr_del_all_igmp(ifp);
2615
2616   if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
2617     pim_if_delete(ifp);
2618   }
2619
2620   return CMD_SUCCESS;
2621 }
2622
2623 DEFUN (interface_ip_igmp_join,
2624        interface_ip_igmp_join_cmd,
2625        "ip igmp join A.B.C.D A.B.C.D",
2626        IP_STR
2627        IFACE_IGMP_STR
2628        "IGMP join multicast group\n"
2629        "Multicast group address\n"
2630        "Source address\n")
2631 {
2632   struct interface *ifp;
2633   const char *group_str;
2634   const char *source_str;
2635   struct in_addr group_addr;
2636   struct in_addr source_addr;
2637   int result;
2638
2639   ifp = vty->index;
2640
2641   /* Group address */
2642   group_str = argv[0];
2643   result = inet_pton(AF_INET, group_str, &group_addr);
2644   if (result <= 0) {
2645     vty_out(vty, "Bad group address %s: errno=%d: %s%s",
2646             group_str, errno, safe_strerror(errno), VTY_NEWLINE);
2647     return CMD_WARNING;
2648   }
2649
2650   /* Source address */
2651   source_str = argv[1];
2652   result = inet_pton(AF_INET, source_str, &source_addr);
2653   if (result <= 0) {
2654     vty_out(vty, "Bad source address %s: errno=%d: %s%s",
2655             source_str, errno, safe_strerror(errno), VTY_NEWLINE);
2656     return CMD_WARNING;
2657   }
2658
2659   result = pim_if_igmp_join_add(ifp, group_addr, source_addr);
2660   if (result) {
2661     vty_out(vty, "%% Failure joining IGMP group %s source %s on interface %s: %d%s",
2662             group_str, source_str, ifp->name, result, VTY_NEWLINE);
2663     return CMD_WARNING;
2664   }
2665
2666   return CMD_SUCCESS;
2667 }
2668
2669 DEFUN (interface_no_ip_igmp_join,
2670        interface_no_ip_igmp_join_cmd,
2671        "no ip igmp join A.B.C.D A.B.C.D",
2672        NO_STR
2673        IP_STR
2674        IFACE_IGMP_STR
2675        "IGMP join multicast group\n"
2676        "Multicast group address\n"
2677        "Source address\n")
2678 {
2679   struct interface *ifp;
2680   const char *group_str;
2681   const char *source_str;
2682   struct in_addr group_addr;
2683   struct in_addr source_addr;
2684   int result;
2685
2686   ifp = vty->index;
2687
2688   /* Group address */
2689   group_str = argv[0];
2690   result = inet_pton(AF_INET, group_str, &group_addr);
2691   if (result <= 0) {
2692     vty_out(vty, "Bad group address %s: errno=%d: %s%s",
2693             group_str, errno, safe_strerror(errno), VTY_NEWLINE);
2694     return CMD_WARNING;
2695   }
2696
2697   /* Source address */
2698   source_str = argv[1];
2699   result = inet_pton(AF_INET, source_str, &source_addr);
2700   if (result <= 0) {
2701     vty_out(vty, "Bad source address %s: errno=%d: %s%s",
2702             source_str, errno, safe_strerror(errno), VTY_NEWLINE);
2703     return CMD_WARNING;
2704   }
2705
2706   result = pim_if_igmp_join_del(ifp, group_addr, source_addr);
2707   if (result) {
2708     vty_out(vty, "%% Failure leaving IGMP group %s source %s on interface %s: %d%s",
2709             group_str, source_str, ifp->name, result, VTY_NEWLINE);
2710     return CMD_WARNING;
2711   }
2712
2713   return CMD_SUCCESS;
2714 }
2715
2716 /*
2717   CLI reconfiguration affects the interface level (struct pim_interface).
2718   This function propagates the reconfiguration to every active socket
2719   for that interface.
2720  */
2721 static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
2722 {
2723   struct interface *ifp;
2724   struct pim_interface *pim_ifp;
2725
2726   zassert(igmp);
2727
2728   /* other querier present? */
2729
2730   if (igmp->t_other_querier_timer)
2731     return;
2732
2733   /* this is the querier */
2734
2735   zassert(igmp->interface);
2736   zassert(igmp->interface->info);
2737
2738   ifp = igmp->interface;
2739   pim_ifp = ifp->info;
2740
2741   if (PIM_DEBUG_IGMP_TRACE) {
2742     char ifaddr_str[100];
2743     pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
2744     zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
2745                __PRETTY_FUNCTION__,
2746                ifaddr_str,
2747                ifp->name,
2748                pim_ifp->igmp_default_query_interval);
2749   }
2750
2751   /*
2752     igmp_startup_mode_on() will reset QQI:
2753
2754     igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
2755   */
2756   igmp_startup_mode_on(igmp);
2757 }
2758
2759 static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
2760 {
2761   if (igmp->t_igmp_query_timer) {
2762     /* other querier present */
2763     zassert(igmp->t_igmp_query_timer);
2764     zassert(!igmp->t_other_querier_timer);
2765
2766     pim_igmp_general_query_off(igmp);
2767     pim_igmp_general_query_on(igmp);
2768
2769     zassert(igmp->t_igmp_query_timer);
2770     zassert(!igmp->t_other_querier_timer);
2771   }
2772   else {
2773     /* this is the querier */
2774
2775     zassert(!igmp->t_igmp_query_timer);
2776     zassert(igmp->t_other_querier_timer);
2777
2778     pim_igmp_other_querier_timer_off(igmp);
2779     pim_igmp_other_querier_timer_on(igmp);
2780
2781     zassert(!igmp->t_igmp_query_timer);
2782     zassert(igmp->t_other_querier_timer);
2783   }
2784 }
2785
2786 static void change_query_interval(struct pim_interface *pim_ifp,
2787                                   int query_interval)
2788 {
2789   struct listnode  *sock_node;
2790   struct igmp_sock *igmp;
2791
2792   pim_ifp->igmp_default_query_interval = query_interval;
2793
2794   for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
2795     igmp_sock_query_interval_reconfig(igmp);
2796     igmp_sock_query_reschedule(igmp);
2797   }
2798 }
2799
2800 static void change_query_max_response_time(struct pim_interface *pim_ifp,
2801                                            int query_max_response_time_dsec)
2802 {
2803   struct listnode  *sock_node;
2804   struct igmp_sock *igmp;
2805
2806   pim_ifp->igmp_query_max_response_time_dsec = query_max_response_time_dsec;
2807
2808   /*
2809     Below we modify socket/group/source timers in order to quickly
2810     reflect the change. Otherwise, those timers would eventually catch
2811     up.
2812    */
2813
2814   /* scan all sockets */
2815   for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
2816     struct listnode   *grp_node;
2817     struct igmp_group *grp;
2818
2819     /* reschedule socket general query */
2820     igmp_sock_query_reschedule(igmp);
2821
2822     /* scan socket groups */
2823     for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node, grp)) {
2824       struct listnode    *src_node;
2825       struct igmp_source *src;
2826
2827       /* reset group timers for groups in EXCLUDE mode */
2828       if (grp->group_filtermode_isexcl) {
2829         igmp_group_reset_gmi(grp);
2830       }
2831
2832       /* scan group sources */
2833       for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node, src)) {
2834
2835         /* reset source timers for sources with running timers */
2836         if (src->t_source_timer) {
2837           igmp_source_reset_gmi(igmp, grp, src);
2838         }
2839       }
2840     }
2841   }
2842 }
2843
2844 #define IGMP_QUERY_INTERVAL_MIN (1)
2845 #define IGMP_QUERY_INTERVAL_MAX (1800)
2846
2847 DEFUN (interface_ip_igmp_query_interval,
2848        interface_ip_igmp_query_interval_cmd,
2849        PIM_CMD_IP_IGMP_QUERY_INTERVAL " <1-1800>",
2850        IP_STR
2851        IFACE_IGMP_STR
2852        IFACE_IGMP_QUERY_INTERVAL_STR
2853        "Query interval in seconds\n")
2854 {
2855   struct interface *ifp;
2856   struct pim_interface *pim_ifp;
2857   int query_interval;
2858   int query_interval_dsec;
2859
2860   ifp = vty->index;
2861   pim_ifp = ifp->info;
2862
2863   if (!pim_ifp) {
2864     vty_out(vty,
2865             "IGMP not enabled on interface %s. Please enable IGMP first.%s",
2866             ifp->name,
2867             VTY_NEWLINE);
2868     return CMD_WARNING;
2869   }
2870
2871   query_interval = atoi(argv[0]);
2872   query_interval_dsec = 10 * query_interval;
2873
2874   /*
2875     It seems we don't need to check bounds since command.c does it
2876     already, but we verify them anyway for extra safety.
2877   */
2878   if (query_interval < IGMP_QUERY_INTERVAL_MIN) {
2879     vty_out(vty, "General query interval %d lower than minimum %d%s",
2880             query_interval,
2881             IGMP_QUERY_INTERVAL_MIN,
2882             VTY_NEWLINE);
2883     return CMD_WARNING;
2884   }
2885   if (query_interval > IGMP_QUERY_INTERVAL_MAX) {
2886     vty_out(vty, "General query interval %d higher than maximum %d%s",
2887             query_interval,
2888             IGMP_QUERY_INTERVAL_MAX,
2889             VTY_NEWLINE);
2890     return CMD_WARNING;
2891   }
2892
2893   if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
2894     vty_out(vty,
2895             "Can't set general query interval %d dsec <= query max response time %d dsec.%s",
2896             query_interval_dsec, pim_ifp->igmp_query_max_response_time_dsec,
2897             VTY_NEWLINE);
2898     return CMD_WARNING;
2899   }
2900
2901   change_query_interval(pim_ifp, query_interval);
2902
2903   return CMD_SUCCESS;
2904 }
2905
2906 DEFUN (interface_no_ip_igmp_query_interval,
2907        interface_no_ip_igmp_query_interval_cmd,
2908        PIM_CMD_NO " " PIM_CMD_IP_IGMP_QUERY_INTERVAL,
2909        NO_STR
2910        IP_STR
2911        IFACE_IGMP_STR
2912        IFACE_IGMP_QUERY_INTERVAL_STR)
2913 {
2914   struct interface *ifp;
2915   struct pim_interface *pim_ifp;
2916   int default_query_interval_dsec;
2917
2918   ifp = vty->index;
2919   pim_ifp = ifp->info;
2920
2921   if (!pim_ifp)
2922     return CMD_SUCCESS;
2923
2924   default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10;
2925
2926   if (default_query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
2927     vty_out(vty,
2928             "Can't set default general query interval %d dsec <= query max response time %d dsec.%s",
2929             default_query_interval_dsec, pim_ifp->igmp_query_max_response_time_dsec,
2930             VTY_NEWLINE);
2931     return CMD_WARNING;
2932   }
2933
2934   change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL);
2935
2936   return CMD_SUCCESS;
2937 }
2938
2939 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN (1)
2940 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX (25)
2941
2942 DEFUN (interface_ip_igmp_query_max_response_time,
2943        interface_ip_igmp_query_max_response_time_cmd,
2944        PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME " <1-25>",
2945        IP_STR
2946        IFACE_IGMP_STR
2947        IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
2948        "Query response value in seconds\n")
2949 {
2950   struct interface *ifp;
2951   struct pim_interface *pim_ifp;
2952   int query_max_response_time;
2953
2954   ifp = vty->index;
2955   pim_ifp = ifp->info;
2956
2957   if (!pim_ifp) {
2958     vty_out(vty,
2959             "IGMP not enabled on interface %s. Please enable IGMP first.%s",
2960             ifp->name,
2961             VTY_NEWLINE);
2962     return CMD_WARNING;
2963   }
2964
2965   query_max_response_time = atoi(argv[0]);
2966
2967   /*
2968     It seems we don't need to check bounds since command.c does it
2969     already, but we verify them anyway for extra safety.
2970   */
2971   if (query_max_response_time < IGMP_QUERY_MAX_RESPONSE_TIME_MIN) {
2972     vty_out(vty, "Query max response time %d sec lower than minimum %d sec%s",
2973             query_max_response_time,
2974             IGMP_QUERY_MAX_RESPONSE_TIME_MIN,
2975             VTY_NEWLINE);
2976     return CMD_WARNING;
2977   }
2978   if (query_max_response_time > IGMP_QUERY_MAX_RESPONSE_TIME_MAX) {
2979     vty_out(vty, "Query max response time %d sec higher than maximum %d sec%s",
2980             query_max_response_time,
2981             IGMP_QUERY_MAX_RESPONSE_TIME_MAX,
2982             VTY_NEWLINE);
2983     return CMD_WARNING;
2984   }
2985
2986   if (query_max_response_time >= pim_ifp->igmp_default_query_interval) {
2987     vty_out(vty,
2988             "Can't set query max response time %d sec >= general query interval %d sec%s",
2989             query_max_response_time, pim_ifp->igmp_default_query_interval,
2990             VTY_NEWLINE);
2991     return CMD_WARNING;
2992   }
2993
2994   change_query_max_response_time(pim_ifp, 10 * query_max_response_time);
2995
2996   return CMD_SUCCESS;
2997 }
2998
2999 DEFUN (interface_no_ip_igmp_query_max_response_time,
3000        interface_no_ip_igmp_query_max_response_time_cmd,
3001        PIM_CMD_NO " " PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME,
3002        NO_STR
3003        IP_STR
3004        IFACE_IGMP_STR
3005        IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR)
3006 {
3007   struct interface *ifp;
3008   struct pim_interface *pim_ifp;
3009   int default_query_interval_dsec;
3010
3011   ifp = vty->index;
3012   pim_ifp = ifp->info;
3013
3014   if (!pim_ifp)
3015     return CMD_SUCCESS;
3016
3017   default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
3018
3019   if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) {
3020     vty_out(vty,
3021             "Can't set default query max response time %d dsec >= general query interval %d dsec.%s",
3022             IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec,
3023             VTY_NEWLINE);
3024     return CMD_WARNING;
3025   }
3026
3027   change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
3028
3029   return CMD_SUCCESS;
3030 }
3031
3032 #define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
3033 #define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
3034
3035 DEFUN (interface_ip_igmp_query_max_response_time_dsec,
3036        interface_ip_igmp_query_max_response_time_dsec_cmd,
3037        PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC " <10-250>",
3038        IP_STR
3039        IFACE_IGMP_STR
3040        IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
3041        "Query response value in deciseconds\n")
3042 {
3043   struct interface *ifp;
3044   struct pim_interface *pim_ifp;
3045   int query_max_response_time_dsec;
3046   int default_query_interval_dsec;
3047
3048   ifp = vty->index;
3049   pim_ifp = ifp->info;
3050
3051   if (!pim_ifp) {
3052     vty_out(vty,
3053             "IGMP not enabled on interface %s. Please enable IGMP first.%s",
3054             ifp->name,
3055             VTY_NEWLINE);
3056     return CMD_WARNING;
3057   }
3058
3059   query_max_response_time_dsec = atoi(argv[0]);
3060
3061   /*
3062     It seems we don't need to check bounds since command.c does it
3063     already, but we verify them anyway for extra safety.
3064   */
3065   if (query_max_response_time_dsec < IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC) {
3066     vty_out(vty, "Query max response time %d dsec lower than minimum %d dsec%s",
3067             query_max_response_time_dsec,
3068             IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC,
3069             VTY_NEWLINE);
3070     return CMD_WARNING;
3071   }
3072   if (query_max_response_time_dsec > IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC) {
3073     vty_out(vty, "Query max response time %d dsec higher than maximum %d dsec%s",
3074             query_max_response_time_dsec,
3075             IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC,
3076             VTY_NEWLINE);
3077     return CMD_WARNING;
3078   }
3079
3080   default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
3081
3082   if (query_max_response_time_dsec >= default_query_interval_dsec) {
3083     vty_out(vty,
3084             "Can't set query max response time %d dsec >= general query interval %d dsec%s",
3085             query_max_response_time_dsec, default_query_interval_dsec,
3086             VTY_NEWLINE);
3087     return CMD_WARNING;
3088   }
3089
3090   change_query_max_response_time(pim_ifp, query_max_response_time_dsec);
3091
3092   return CMD_SUCCESS;
3093 }
3094
3095 DEFUN (interface_no_ip_igmp_query_max_response_time_dsec,
3096        interface_no_ip_igmp_query_max_response_time_dsec_cmd,
3097        PIM_CMD_NO " " PIM_CMD_IP_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC,
3098        NO_STR
3099        IP_STR
3100        IFACE_IGMP_STR
3101        IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
3102 {
3103   struct interface *ifp;
3104   struct pim_interface *pim_ifp;
3105   int default_query_interval_dsec;
3106
3107   ifp = vty->index;
3108   pim_ifp = ifp->info;
3109
3110   if (!pim_ifp)
3111     return CMD_SUCCESS;
3112
3113   default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
3114
3115   if (IGMP_QUERY_MAX_RESPONSE_TIME_DSEC >= default_query_interval_dsec) {
3116     vty_out(vty,
3117             "Can't set default query max response time %d dsec >= general query interval %d dsec.%s",
3118             IGMP_QUERY_MAX_RESPONSE_TIME_DSEC, default_query_interval_dsec,
3119             VTY_NEWLINE);
3120     return CMD_WARNING;
3121   }
3122
3123   change_query_max_response_time(pim_ifp, IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
3124
3125   return CMD_SUCCESS;
3126 }
3127
3128 DEFUN (interface_ip_pim_drprio,
3129        interface_ip_pim_drprio_cmd,
3130        "ip pim drpriority <1-4294967295>",
3131        IP_STR
3132        PIM_STR
3133        "Set the Designated Router Election Priority\n"
3134        "Value of the new DR Priority\n")
3135 {
3136   struct interface *ifp;
3137   struct pim_interface *pim_ifp;
3138   uint32_t old_dr_prio;
3139
3140   ifp = vty->index;
3141   pim_ifp = ifp->info;
3142
3143   if (!pim_ifp) {
3144     vty_out(vty, "Please enable PIM on interface, first%s", VTY_NEWLINE);
3145     return CMD_WARNING;
3146   }
3147
3148   old_dr_prio = pim_ifp->pim_dr_priority;
3149
3150   pim_ifp->pim_dr_priority = strtol(argv[0], NULL, 10);
3151
3152   if (old_dr_prio != pim_ifp->pim_dr_priority) {
3153     if (pim_if_dr_election(ifp))
3154       pim_hello_restart_now(ifp);
3155   }
3156
3157   return CMD_SUCCESS;
3158 }
3159
3160 DEFUN (interface_no_ip_pim_drprio,
3161        interface_no_ip_pim_drprio_cmd,
3162        "no ip pim drpriority {<1-4294967295>}",
3163        IP_STR
3164        PIM_STR
3165        "Revert the Designated Router Priority to default\n"
3166        "Old Value of the Priority\n")
3167 {
3168   struct interface *ifp;
3169   struct pim_interface *pim_ifp;
3170
3171   ifp = vty->index;
3172   pim_ifp = ifp->info;
3173
3174   if (!pim_ifp) {
3175     vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
3176     return CMD_WARNING;
3177   }
3178
3179   if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
3180     pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
3181     if (pim_if_dr_election(ifp))
3182       pim_hello_restart_now(ifp);
3183   }
3184
3185   return CMD_SUCCESS;
3186 }
3187
3188 DEFUN (interface_ip_pim_ssm,
3189        interface_ip_pim_ssm_cmd,
3190        "ip pim ssm",
3191        IP_STR
3192        PIM_STR
3193        IFACE_PIM_STR)
3194 {
3195   struct interface *ifp;
3196   struct pim_interface *pim_ifp;
3197
3198   ifp = vty->index;
3199   pim_ifp = ifp->info;
3200
3201   if (!pim_ifp) {
3202     pim_ifp = pim_if_new(ifp, 0 /* igmp=false */, 1 /* pim=true */);
3203     if (!pim_ifp) {
3204       vty_out(vty, "Could not enable PIM on interface%s", VTY_NEWLINE);
3205       return CMD_WARNING;
3206     }
3207   }
3208   else {
3209     PIM_IF_DO_PIM(pim_ifp->options);
3210   }
3211
3212   pim_if_addr_add_all(ifp);
3213   pim_if_membership_refresh(ifp);
3214
3215   return CMD_SUCCESS;
3216 }
3217
3218 DEFUN (interface_no_ip_pim_ssm,
3219        interface_no_ip_pim_ssm_cmd,
3220        "no ip pim ssm",
3221        NO_STR
3222        IP_STR
3223        PIM_STR
3224        IFACE_PIM_STR)
3225 {
3226   struct interface *ifp;
3227   struct pim_interface *pim_ifp;
3228
3229   ifp = vty->index;
3230   pim_ifp = ifp->info;
3231   if (!pim_ifp)
3232     return CMD_SUCCESS;
3233
3234   PIM_IF_DONT_PIM(pim_ifp->options);
3235
3236   pim_if_membership_clear(ifp);
3237
3238   /*
3239     pim_if_addr_del_all() removes all sockets from
3240     pim_ifp->igmp_socket_list.
3241    */
3242   pim_if_addr_del_all(ifp);
3243
3244   /*
3245     pim_sock_delete() removes all neighbors from
3246     pim_ifp->pim_neighbor_list.
3247    */
3248   pim_sock_delete(ifp, "pim unconfigured on interface");
3249
3250   if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
3251     pim_if_delete(ifp);
3252   }
3253
3254   return CMD_SUCCESS;
3255 }
3256
3257 DEFUN (interface_ip_mroute,
3258        interface_ip_mroute_cmd,
3259        "ip mroute INTERFACE A.B.C.D",
3260        IP_STR
3261        "Add multicast route\n"
3262        "Outgoing interface name\n"
3263        "Group address\n")
3264 {
3265    struct interface *iif;
3266    struct interface *oif;
3267    const char       *oifname;
3268    const char       *grp_str;
3269    struct in_addr    grp_addr;
3270    struct in_addr    src_addr;
3271    int               result;
3272
3273    iif = vty->index;
3274
3275    oifname = argv[0];
3276    oif = if_lookup_by_name(oifname);
3277    if (!oif) {
3278      vty_out(vty, "No such interface name %s%s",
3279         oifname, VTY_NEWLINE);
3280      return CMD_WARNING;
3281    }
3282
3283    grp_str = argv[1];
3284    result = inet_pton(AF_INET, grp_str, &grp_addr);
3285    if (result <= 0) {
3286      vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3287         grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
3288      return CMD_WARNING;
3289    }
3290
3291    src_addr.s_addr = INADDR_ANY;
3292
3293    if (pim_static_add(iif, oif, grp_addr, src_addr)) {
3294       vty_out(vty, "Failed to add route%s", VTY_NEWLINE);
3295       return CMD_WARNING;
3296    }
3297
3298    return CMD_SUCCESS;
3299 }
3300
3301 DEFUN (interface_ip_mroute_source,
3302        interface_ip_mroute_source_cmd,
3303        "ip mroute INTERFACE A.B.C.D A.B.C.D",
3304        IP_STR
3305        "Add multicast route\n"
3306        "Outgoing interface name\n"
3307        "Group address\n"
3308        "Source address\n")
3309 {
3310    struct interface *iif;
3311    struct interface *oif;
3312    const char       *oifname;
3313    const char       *grp_str;
3314    struct in_addr    grp_addr;
3315    const char       *src_str;
3316    struct in_addr    src_addr;
3317    int               result;
3318
3319    iif = vty->index;
3320
3321    oifname = argv[0];
3322    oif = if_lookup_by_name(oifname);
3323    if (!oif) {
3324      vty_out(vty, "No such interface name %s%s",
3325         oifname, VTY_NEWLINE);
3326      return CMD_WARNING;
3327    }
3328
3329    grp_str = argv[1];
3330    result = inet_pton(AF_INET, grp_str, &grp_addr);
3331    if (result <= 0) {
3332      vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3333         grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
3334      return CMD_WARNING;
3335    }
3336
3337    src_str = argv[2];
3338    result = inet_pton(AF_INET, src_str, &src_addr);
3339    if (result <= 0) {
3340      vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3341         src_str, errno, safe_strerror(errno), VTY_NEWLINE);
3342      return CMD_WARNING;
3343    }
3344
3345    if (pim_static_add(iif, oif, grp_addr, src_addr)) {
3346       vty_out(vty, "Failed to add route%s", VTY_NEWLINE);
3347       return CMD_WARNING;
3348    }
3349
3350    return CMD_SUCCESS;
3351 }
3352
3353 DEFUN (interface_no_ip_mroute,
3354        interface_no_ip_mroute_cmd,
3355        "no ip mroute INTERFACE A.B.C.D",
3356        NO_STR
3357        IP_STR
3358        "Add multicast route\n"
3359        "Outgoing interface name\n"
3360        "Group Address\n")
3361 {
3362    struct interface *iif;
3363    struct interface *oif;
3364    const char       *oifname;
3365    const char       *grp_str;
3366    struct in_addr    grp_addr;
3367    struct in_addr    src_addr;
3368    int               result;
3369
3370    iif = vty->index;
3371
3372    oifname = argv[0];
3373    oif = if_lookup_by_name(oifname);
3374    if (!oif) {
3375      vty_out(vty, "No such interface name %s%s",
3376         oifname, VTY_NEWLINE);
3377      return CMD_WARNING;
3378    }
3379
3380    grp_str = argv[1];
3381    result = inet_pton(AF_INET, grp_str, &grp_addr);
3382    if (result <= 0) {
3383      vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3384         grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
3385      return CMD_WARNING;
3386    }
3387
3388    src_addr.s_addr = INADDR_ANY;
3389
3390    if (pim_static_del(iif, oif, grp_addr, src_addr)) {
3391       vty_out(vty, "Failed to remove route%s", VTY_NEWLINE);
3392       return CMD_WARNING;
3393    }
3394
3395    return CMD_SUCCESS;
3396 }
3397
3398 DEFUN (interface_no_ip_mroute_source,
3399        interface_no_ip_mroute_source_cmd,
3400        "no ip mroute INTERFACE A.B.C.D A.B.C.D",
3401        NO_STR
3402        IP_STR
3403        "Add multicast route\n"
3404        "Outgoing interface name\n"
3405        "Group Address\n"
3406        "Source Address\n")
3407 {
3408    struct interface *iif;
3409    struct interface *oif;
3410    const char       *oifname;
3411    const char       *grp_str;
3412    struct in_addr    grp_addr;
3413    const char       *src_str;
3414    struct in_addr    src_addr;
3415    int               result;
3416
3417    iif = vty->index;
3418
3419    oifname = argv[0];
3420    oif = if_lookup_by_name(oifname);
3421    if (!oif) {
3422      vty_out(vty, "No such interface name %s%s",
3423         oifname, VTY_NEWLINE);
3424      return CMD_WARNING;
3425    }
3426
3427    grp_str = argv[1];
3428    result = inet_pton(AF_INET, grp_str, &grp_addr);
3429    if (result <= 0) {
3430      vty_out(vty, "Bad group address %s: errno=%d: %s%s",
3431         grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
3432      return CMD_WARNING;
3433    }
3434
3435    src_str = argv[2];
3436    result = inet_pton(AF_INET, src_str, &src_addr);
3437    if (result <= 0) {
3438      vty_out(vty, "Bad source address %s: errno=%d: %s%s",
3439         src_str, errno, safe_strerror(errno), VTY_NEWLINE);
3440      return CMD_WARNING;
3441    }
3442
3443    if (pim_static_del(iif, oif, grp_addr, src_addr)) {
3444       vty_out(vty, "Failed to remove route%s", VTY_NEWLINE);
3445       return CMD_WARNING;
3446    }
3447
3448    return CMD_SUCCESS;
3449 }
3450
3451 DEFUN (interface_ip_pim_hello,
3452        interface_ip_pim_hello_cmd,
3453        "ip pim hello <1-180>",
3454        IP_STR
3455        PIM_STR
3456        IFACE_PIM_HELLO_STR
3457        IFACE_PIM_HELLO_TIME_STR)
3458 {
3459   struct interface *ifp;
3460   struct pim_interface *pim_ifp;
3461
3462   ifp = vty->index;
3463   pim_ifp = ifp->info;
3464
3465   if (!pim_ifp) {
3466     vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
3467     return CMD_WARNING;
3468   }
3469
3470   pim_ifp->pim_hello_period = strtol(argv[0], NULL, 10);
3471
3472   if (argc == 2)
3473     pim_ifp->pim_default_holdtime = strtol(argv[1], NULL, 10);
3474
3475   return CMD_SUCCESS;
3476 }
3477
3478 ALIAS (interface_ip_pim_hello,
3479        interface_ip_pim_hello_hold_cmd,
3480        "ip pim hello <1-180> <1-180>",
3481        IP_STR
3482        PIM_STR
3483        IFACE_PIM_HELLO_STR
3484        IFACE_PIM_HELLO_TIME_STR
3485        IFACE_PIM_HELLO_HOLD_STR)
3486
3487
3488 DEFUN (interface_no_ip_pim_hello,
3489        interface_no_ip_pim_hello_cmd,
3490        "no ip pim hello {<1-180> <1-180>}",
3491        NO_STR
3492        IP_STR
3493        PIM_STR
3494        IFACE_PIM_HELLO_STR
3495        IFACE_PIM_HELLO_TIME_STR
3496        IFACE_PIM_HELLO_HOLD_STR)
3497 {
3498   struct interface *ifp;
3499   struct pim_interface *pim_ifp;
3500
3501   ifp = vty->index;
3502   pim_ifp = ifp->info;
3503
3504   if (!pim_ifp) {
3505     vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE);
3506     return CMD_WARNING;
3507   }
3508
3509   pim_ifp->pim_hello_period     = PIM_DEFAULT_HELLO_PERIOD;
3510   pim_ifp->pim_default_holdtime = -1;
3511
3512   return CMD_SUCCESS;
3513 }
3514
3515 DEFUN (debug_igmp,
3516        debug_igmp_cmd,
3517        "debug igmp",
3518        DEBUG_STR
3519        DEBUG_IGMP_STR)
3520 {
3521   PIM_DO_DEBUG_IGMP_EVENTS;
3522   PIM_DO_DEBUG_IGMP_PACKETS;
3523   PIM_DO_DEBUG_IGMP_TRACE;
3524   return CMD_SUCCESS;
3525 }
3526
3527 DEFUN (no_debug_igmp,
3528        no_debug_igmp_cmd,
3529        "no debug igmp",
3530        NO_STR
3531        DEBUG_STR
3532        DEBUG_IGMP_STR)
3533 {
3534   PIM_DONT_DEBUG_IGMP_EVENTS;
3535   PIM_DONT_DEBUG_IGMP_PACKETS;
3536   PIM_DONT_DEBUG_IGMP_TRACE;
3537   return CMD_SUCCESS;
3538 }
3539
3540 ALIAS (no_debug_igmp,
3541        undebug_igmp_cmd,
3542        "undebug igmp",
3543        UNDEBUG_STR
3544        DEBUG_IGMP_STR)
3545
3546 DEFUN (debug_igmp_events,
3547        debug_igmp_events_cmd,
3548        "debug igmp events",
3549        DEBUG_STR
3550        DEBUG_IGMP_STR
3551        DEBUG_IGMP_EVENTS_STR)
3552 {
3553   PIM_DO_DEBUG_IGMP_EVENTS;
3554   return CMD_SUCCESS;
3555 }
3556
3557 DEFUN (no_debug_igmp_events,
3558        no_debug_igmp_events_cmd,
3559        "no debug igmp events",
3560        NO_STR
3561        DEBUG_STR
3562        DEBUG_IGMP_STR
3563        DEBUG_IGMP_EVENTS_STR)
3564 {
3565   PIM_DONT_DEBUG_IGMP_EVENTS;
3566   return CMD_SUCCESS;
3567 }
3568
3569 ALIAS (no_debug_igmp_events,
3570        undebug_igmp_events_cmd,
3571        "undebug igmp events",
3572        UNDEBUG_STR
3573        DEBUG_IGMP_STR
3574        DEBUG_IGMP_EVENTS_STR)
3575
3576 DEFUN (debug_igmp_packets,
3577        debug_igmp_packets_cmd,
3578        "debug igmp packets",
3579        DEBUG_STR
3580        DEBUG_IGMP_STR
3581        DEBUG_IGMP_PACKETS_STR)
3582 {
3583   PIM_DO_DEBUG_IGMP_PACKETS;
3584   return CMD_SUCCESS;
3585 }
3586
3587 DEFUN (no_debug_igmp_packets,
3588        no_debug_igmp_packets_cmd,
3589        "no debug igmp packets",
3590        NO_STR
3591        DEBUG_STR
3592        DEBUG_IGMP_STR
3593        DEBUG_IGMP_PACKETS_STR)
3594 {
3595   PIM_DONT_DEBUG_IGMP_PACKETS;
3596   return CMD_SUCCESS;
3597 }
3598
3599 ALIAS (no_debug_igmp_packets,
3600        undebug_igmp_packets_cmd,
3601        "undebug igmp packets",
3602        UNDEBUG_STR
3603        DEBUG_IGMP_STR
3604        DEBUG_IGMP_PACKETS_STR)
3605
3606 DEFUN (debug_igmp_trace,
3607        debug_igmp_trace_cmd,
3608        "debug igmp trace",
3609        DEBUG_STR
3610        DEBUG_IGMP_STR
3611        DEBUG_IGMP_TRACE_STR)
3612 {
3613   PIM_DO_DEBUG_IGMP_TRACE;
3614   return CMD_SUCCESS;
3615 }
3616
3617 DEFUN (no_debug_igmp_trace,
3618        no_debug_igmp_trace_cmd,
3619        "no debug igmp trace",
3620        NO_STR
3621        DEBUG_STR
3622        DEBUG_IGMP_STR
3623        DEBUG_IGMP_TRACE_STR)
3624 {
3625   PIM_DONT_DEBUG_IGMP_TRACE;
3626   return CMD_SUCCESS;
3627 }
3628
3629 ALIAS (no_debug_igmp_trace,
3630        undebug_igmp_trace_cmd,
3631        "undebug igmp trace",
3632        UNDEBUG_STR
3633        DEBUG_IGMP_STR
3634        DEBUG_IGMP_TRACE_STR)
3635
3636 DEFUN (debug_mroute,
3637        debug_mroute_cmd,
3638        "debug mroute",
3639        DEBUG_STR
3640        DEBUG_MROUTE_STR)
3641 {
3642   PIM_DO_DEBUG_MROUTE;
3643   return CMD_SUCCESS;
3644 }
3645
3646 DEFUN (no_debug_mroute,
3647        no_debug_mroute_cmd,
3648        "no debug mroute",
3649        NO_STR
3650        DEBUG_STR
3651        DEBUG_MROUTE_STR)
3652 {
3653   PIM_DONT_DEBUG_MROUTE;
3654   return CMD_SUCCESS;
3655 }
3656
3657 ALIAS (no_debug_mroute,
3658        undebug_mroute_cmd,
3659        "undebug mroute",
3660        UNDEBUG_STR
3661        DEBUG_MROUTE_STR)
3662
3663 DEFUN (debug_static,
3664        debug_static_cmd,
3665        "debug static",
3666        DEBUG_STR
3667        DEBUG_STATIC_STR)
3668 {
3669   PIM_DO_DEBUG_STATIC;
3670   return CMD_SUCCESS;
3671 }
3672
3673 DEFUN (no_debug_static,
3674        no_debug_static_cmd,
3675        "no debug static",
3676        NO_STR
3677        DEBUG_STR
3678        DEBUG_STATIC_STR)
3679 {
3680   PIM_DONT_DEBUG_STATIC;
3681   return CMD_SUCCESS;
3682 }
3683
3684 ALIAS (no_debug_static,
3685        undebug_static_cmd,
3686        "undebug static",
3687        UNDEBUG_STR
3688        DEBUG_STATIC_STR)
3689
3690 DEFUN (debug_pim,
3691        debug_pim_cmd,
3692        "debug pim",
3693        DEBUG_STR
3694        DEBUG_PIM_STR)
3695 {
3696   PIM_DO_DEBUG_PIM_EVENTS;
3697   PIM_DO_DEBUG_PIM_PACKETS;
3698   PIM_DO_DEBUG_PIM_TRACE;
3699   return CMD_SUCCESS;
3700 }
3701
3702 DEFUN (no_debug_pim,
3703        no_debug_pim_cmd,
3704        "no debug pim",
3705        NO_STR
3706        DEBUG_STR
3707        DEBUG_PIM_STR)
3708 {
3709   PIM_DONT_DEBUG_PIM_EVENTS;
3710   PIM_DONT_DEBUG_PIM_PACKETS;
3711   PIM_DONT_DEBUG_PIM_TRACE;
3712
3713   PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
3714   PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
3715
3716   return CMD_SUCCESS;
3717 }
3718
3719 ALIAS (no_debug_pim,
3720        undebug_pim_cmd,
3721        "undebug pim",
3722        UNDEBUG_STR
3723        DEBUG_PIM_STR)
3724
3725 DEFUN (debug_pim_events,
3726        debug_pim_events_cmd,
3727        "debug pim events",
3728        DEBUG_STR
3729        DEBUG_PIM_STR
3730        DEBUG_PIM_EVENTS_STR)
3731 {
3732   PIM_DO_DEBUG_PIM_EVENTS;
3733   return CMD_SUCCESS;
3734 }
3735
3736 DEFUN (no_debug_pim_events,
3737        no_debug_pim_events_cmd,
3738        "no debug pim events",
3739        NO_STR
3740        DEBUG_STR
3741        DEBUG_PIM_STR
3742        DEBUG_PIM_EVENTS_STR)
3743 {
3744   PIM_DONT_DEBUG_PIM_EVENTS;
3745   return CMD_SUCCESS;
3746 }
3747
3748 ALIAS (no_debug_pim_events,
3749        undebug_pim_events_cmd,
3750        "undebug pim events",
3751        UNDEBUG_STR
3752        DEBUG_PIM_STR
3753        DEBUG_PIM_EVENTS_STR)
3754
3755 DEFUN (debug_pim_packets,
3756        debug_pim_packets_cmd,
3757        "debug pim packets",
3758        DEBUG_STR
3759        DEBUG_PIM_STR
3760        DEBUG_PIM_PACKETS_STR)
3761 {
3762     PIM_DO_DEBUG_PIM_PACKETS;
3763     vty_out (vty, "PIM Packet debugging is on %s", VTY_NEWLINE);
3764     return CMD_SUCCESS;
3765 }
3766
3767 DEFUN (debug_pim_packets_filter,
3768        debug_pim_packets_filter_cmd,
3769        "debug pim packets (hello|joins)",
3770        DEBUG_STR
3771        DEBUG_PIM_STR
3772        DEBUG_PIM_PACKETS_STR
3773        DEBUG_PIM_HELLO_PACKETS_STR
3774        DEBUG_PIM_J_P_PACKETS_STR)
3775 {
3776     if (strncmp(argv[0],"h",1) == 0) 
3777     {
3778       PIM_DO_DEBUG_PIM_HELLO;
3779       vty_out (vty, "PIM Hello debugging is on %s", VTY_NEWLINE);
3780     }
3781     else if (strncmp(argv[0],"j",1) == 0)
3782     {
3783       PIM_DO_DEBUG_PIM_J_P;
3784       vty_out (vty, "PIM Join/Prune debugging is on %s", VTY_NEWLINE);
3785     }
3786   return CMD_SUCCESS;
3787 }
3788
3789 DEFUN (no_debug_pim_packets,
3790        no_debug_pim_packets_cmd,
3791        "no debug pim packets",
3792        NO_STR
3793        DEBUG_STR
3794        DEBUG_PIM_STR
3795        DEBUG_PIM_PACKETS_STR
3796        DEBUG_PIM_HELLO_PACKETS_STR
3797        DEBUG_PIM_J_P_PACKETS_STR)
3798 {
3799   PIM_DONT_DEBUG_PIM_PACKETS;
3800   vty_out (vty, "PIM Packet debugging is off %s", VTY_NEWLINE);
3801   return CMD_SUCCESS;
3802 }
3803
3804 DEFUN (no_debug_pim_packets_filter,
3805        no_debug_pim_packets_filter_cmd,
3806        "no debug pim packets (hello|joins)",
3807        NO_STR
3808        DEBUG_STR
3809        DEBUG_PIM_STR
3810        DEBUG_PIM_PACKETS_STR
3811        DEBUG_PIM_HELLO_PACKETS_STR
3812        DEBUG_PIM_J_P_PACKETS_STR)
3813 {
3814     if (strncmp(argv[0],"h",1) == 0) 
3815     {
3816       PIM_DONT_DEBUG_PIM_HELLO;
3817       vty_out (vty, "PIM Hello debugging is off %s", VTY_NEWLINE);
3818     }
3819     else if (strncmp(argv[0],"j",1) == 0)
3820     {
3821       PIM_DONT_DEBUG_PIM_J_P;
3822       vty_out (vty, "PIM Join/Prune debugging is off %s", VTY_NEWLINE);
3823     }
3824     return CMD_SUCCESS;
3825 }
3826
3827 ALIAS (no_debug_pim_packets,
3828        undebug_pim_packets_cmd,
3829        "undebug pim packets",
3830        UNDEBUG_STR
3831        DEBUG_PIM_STR
3832        DEBUG_PIM_PACKETS_STR)
3833
3834 DEFUN (debug_pim_packetdump_send,
3835        debug_pim_packetdump_send_cmd,
3836        "debug pim packet-dump send",
3837        DEBUG_STR
3838        DEBUG_PIM_STR
3839        DEBUG_PIM_PACKETDUMP_STR
3840        DEBUG_PIM_PACKETDUMP_SEND_STR)
3841 {
3842   PIM_DO_DEBUG_PIM_PACKETDUMP_SEND;
3843   return CMD_SUCCESS;
3844 }
3845
3846 DEFUN (no_debug_pim_packetdump_send,
3847        no_debug_pim_packetdump_send_cmd,
3848        "no debug pim packet-dump send",
3849        NO_STR
3850        DEBUG_STR
3851        DEBUG_PIM_STR
3852        DEBUG_PIM_PACKETDUMP_STR
3853        DEBUG_PIM_PACKETDUMP_SEND_STR)
3854 {
3855   PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
3856   return CMD_SUCCESS;
3857 }
3858
3859 ALIAS (no_debug_pim_packetdump_send,
3860        undebug_pim_packetdump_send_cmd,
3861        "undebug pim packet-dump send",
3862        UNDEBUG_STR
3863        DEBUG_PIM_STR
3864        DEBUG_PIM_PACKETDUMP_STR
3865        DEBUG_PIM_PACKETDUMP_SEND_STR)
3866
3867 DEFUN (debug_pim_packetdump_recv,
3868        debug_pim_packetdump_recv_cmd,
3869        "debug pim packet-dump receive",
3870        DEBUG_STR
3871        DEBUG_PIM_STR
3872        DEBUG_PIM_PACKETDUMP_STR
3873        DEBUG_PIM_PACKETDUMP_RECV_STR)
3874 {
3875   PIM_DO_DEBUG_PIM_PACKETDUMP_RECV;
3876   return CMD_SUCCESS;
3877 }
3878
3879 DEFUN (no_debug_pim_packetdump_recv,
3880        no_debug_pim_packetdump_recv_cmd,
3881        "no debug pim packet-dump receive",
3882        NO_STR
3883        DEBUG_STR
3884        DEBUG_PIM_STR
3885        DEBUG_PIM_PACKETDUMP_STR
3886        DEBUG_PIM_PACKETDUMP_RECV_STR)
3887 {
3888   PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
3889   return CMD_SUCCESS;
3890 }
3891
3892 ALIAS (no_debug_pim_packetdump_recv,
3893        undebug_pim_packetdump_recv_cmd,
3894        "undebug pim packet-dump receive",
3895        UNDEBUG_STR
3896        DEBUG_PIM_STR
3897        DEBUG_PIM_PACKETDUMP_STR
3898        DEBUG_PIM_PACKETDUMP_RECV_STR)
3899
3900 DEFUN (debug_pim_trace,
3901        debug_pim_trace_cmd,
3902        "debug pim trace",
3903        DEBUG_STR
3904        DEBUG_PIM_STR
3905        DEBUG_PIM_TRACE_STR)
3906 {
3907   PIM_DO_DEBUG_PIM_TRACE;
3908   return CMD_SUCCESS;
3909 }
3910
3911 DEFUN (no_debug_pim_trace,
3912        no_debug_pim_trace_cmd,
3913        "no debug pim trace",
3914        NO_STR
3915        DEBUG_STR
3916        DEBUG_PIM_STR
3917        DEBUG_PIM_TRACE_STR)
3918 {
3919   PIM_DONT_DEBUG_PIM_TRACE;
3920   return CMD_SUCCESS;
3921 }
3922
3923 ALIAS (no_debug_pim_trace,
3924        undebug_pim_trace_cmd,
3925        "undebug pim trace",
3926        UNDEBUG_STR
3927        DEBUG_PIM_STR
3928        DEBUG_PIM_TRACE_STR)
3929
3930 DEFUN (debug_ssmpingd,
3931        debug_ssmpingd_cmd,
3932        "debug ssmpingd",
3933        DEBUG_STR
3934        DEBUG_PIM_STR
3935        DEBUG_SSMPINGD_STR)
3936 {
3937   PIM_DO_DEBUG_SSMPINGD;
3938   return CMD_SUCCESS;
3939 }
3940
3941 DEFUN (no_debug_ssmpingd,
3942        no_debug_ssmpingd_cmd,
3943        "no debug ssmpingd",
3944        NO_STR
3945        DEBUG_STR
3946        DEBUG_PIM_STR
3947        DEBUG_SSMPINGD_STR)
3948 {
3949   PIM_DONT_DEBUG_SSMPINGD;
3950   return CMD_SUCCESS;
3951 }
3952
3953 ALIAS (no_debug_ssmpingd,
3954        undebug_ssmpingd_cmd,
3955        "undebug ssmpingd",
3956        UNDEBUG_STR
3957        DEBUG_PIM_STR
3958        DEBUG_SSMPINGD_STR)
3959
3960 DEFUN (debug_pim_zebra,
3961        debug_pim_zebra_cmd,
3962        "debug pim zebra",
3963        DEBUG_STR
3964        DEBUG_PIM_STR
3965        DEBUG_PIM_ZEBRA_STR)
3966 {
3967   PIM_DO_DEBUG_ZEBRA;
3968   return CMD_SUCCESS;
3969 }
3970
3971 DEFUN (no_debug_pim_zebra,
3972        no_debug_pim_zebra_cmd,
3973        "no debug pim zebra",
3974        NO_STR
3975        DEBUG_STR
3976        DEBUG_PIM_STR
3977        DEBUG_PIM_ZEBRA_STR)
3978 {
3979   PIM_DONT_DEBUG_ZEBRA;
3980   return CMD_SUCCESS;
3981 }
3982
3983 ALIAS (no_debug_pim_zebra,
3984        undebug_pim_zebra_cmd,
3985        "undebug pim zebra",
3986        UNDEBUG_STR
3987        DEBUG_PIM_STR
3988        DEBUG_PIM_ZEBRA_STR)
3989
3990 DEFUN (show_debugging_pim,
3991        show_debugging_pim_cmd,
3992        "show debugging pim",
3993        SHOW_STR
3994        DEBUG_STR
3995        PIM_STR)
3996 {
3997   pim_debug_config_write(vty);
3998   return CMD_SUCCESS;
3999 }
4000
4001 static struct igmp_sock *find_igmp_sock_by_fd(int fd)
4002 {
4003   struct listnode  *ifnode;
4004   struct interface *ifp;
4005
4006   /* scan all interfaces */
4007   for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) {
4008     struct pim_interface *pim_ifp;
4009     struct igmp_sock     *igmp;
4010     
4011     if (!ifp->info)
4012       continue;
4013
4014     pim_ifp = ifp->info;
4015
4016     /* lookup igmp socket under current interface */
4017     igmp = igmp_sock_lookup_by_fd(pim_ifp->igmp_socket_list, fd);
4018     if (igmp)
4019       return igmp;
4020   }
4021
4022   return 0;
4023 }
4024
4025 DEFUN (test_igmp_receive_report,
4026        test_igmp_receive_report_cmd,
4027        "test igmp receive report <0-65535> A.B.C.D <1-6> .LINE",
4028        "Test\n"
4029        "Test IGMP protocol\n"
4030        "Test IGMP message\n"
4031        "Test IGMP report\n"
4032        "Socket\n"
4033        "IGMP group address\n"
4034        "Record type\n"
4035        "Sources\n")
4036 {
4037   char              buf[1000];
4038   char             *igmp_msg;
4039   struct ip        *ip_hdr;
4040   size_t            ip_hlen; /* ip header length in bytes */
4041   int               ip_msg_len;
4042   int               igmp_msg_len;
4043   const char       *socket;
4044   int               socket_fd;
4045   const char       *grp_str;
4046   struct in_addr    grp_addr;
4047   const char       *record_type_str;
4048   int               record_type;
4049   const char       *src_str;
4050   int               result;
4051   struct igmp_sock *igmp;
4052   char             *group_record;
4053   int               num_sources;
4054   struct in_addr   *sources;
4055   struct in_addr   *src_addr;
4056   int               argi;
4057
4058   socket = argv[0];
4059   socket_fd = atoi(socket);
4060   igmp = find_igmp_sock_by_fd(socket_fd);
4061   if (!igmp) {
4062     vty_out(vty, "Could not find IGMP socket %s: fd=%d%s",
4063             socket, socket_fd, VTY_NEWLINE);
4064     return CMD_WARNING;
4065   }
4066
4067   grp_str = argv[1];
4068   result = inet_pton(AF_INET, grp_str, &grp_addr);
4069   if (result <= 0) {
4070     vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4071             grp_str, errno, safe_strerror(errno), VTY_NEWLINE);
4072     return CMD_WARNING;
4073   }
4074
4075   record_type_str = argv[2];
4076   record_type = atoi(record_type_str);
4077
4078   /*
4079     Tweak IP header
4080    */
4081   ip_hdr = (struct ip *) buf;
4082   ip_hdr->ip_p = PIM_IP_PROTO_IGMP;
4083   ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4084   ip_hdr->ip_hl = ip_hlen >> 2;    /* ip header length in 4-byte words */
4085   ip_hdr->ip_src = igmp->ifaddr;
4086   ip_hdr->ip_dst = igmp->ifaddr;
4087
4088   /*
4089     Build IGMP v3 report message
4090    */
4091   igmp_msg = buf + ip_hlen;
4092   group_record = igmp_msg + IGMP_V3_REPORT_GROUPPRECORD_OFFSET;
4093   *igmp_msg = PIM_IGMP_V3_MEMBERSHIP_REPORT; /* type */
4094   *(uint16_t *)      (igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = 0; /* for computing checksum */
4095   *(uint16_t *)      (igmp_msg + IGMP_V3_REPORT_NUMGROUPS_OFFSET) = htons(1); /* one group record */
4096   *(uint8_t  *)      (group_record + IGMP_V3_GROUP_RECORD_TYPE_OFFSET) = record_type;
4097   memcpy(group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET, &grp_addr, sizeof(struct in_addr));
4098
4099   /* Scan LINE sources */
4100   sources = (struct in_addr *) (group_record + IGMP_V3_GROUP_RECORD_SOURCE_OFFSET);
4101   src_addr = sources;
4102   for (argi = 3; argi < argc; ++argi,++src_addr) {
4103     src_str = argv[argi];
4104     result = inet_pton(AF_INET, src_str, src_addr);
4105     if (result <= 0) {
4106       vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4107               src_str, errno, safe_strerror(errno), VTY_NEWLINE);
4108       return CMD_WARNING;
4109     }
4110   }
4111   num_sources = src_addr - sources;
4112
4113   *(uint16_t *)(group_record + IGMP_V3_GROUP_RECORD_NUMSOURCES_OFFSET) = htons(num_sources);
4114
4115   igmp_msg_len = IGMP_V3_MSG_MIN_SIZE + (num_sources << 4);   /* v3 report for one single group record */
4116
4117   /* compute checksum */
4118   *(uint16_t *)(igmp_msg + IGMP_V3_CHECKSUM_OFFSET) = in_cksum(igmp_msg, igmp_msg_len);
4119
4120   /* "receive" message */
4121
4122   ip_msg_len = ip_hlen + igmp_msg_len;
4123   result = pim_igmp_packet(igmp, buf, ip_msg_len);
4124   if (result) {
4125     vty_out(vty, "pim_igmp_packet(len=%d) returned: %d%s",
4126             ip_msg_len, result, VTY_NEWLINE);
4127     return CMD_WARNING;
4128   }
4129
4130   return CMD_SUCCESS;
4131 }
4132
4133 static int hexval(uint8_t ch)
4134 {
4135   return isdigit(ch) ? (ch - '0') : (10 + tolower(ch) - 'a');
4136 }
4137
4138 DEFUN (test_pim_receive_dump,
4139        test_pim_receive_dump_cmd,
4140        "test pim receive dump INTERFACE A.B.C.D .LINE",
4141        "Test\n"
4142        "Test PIM protocol\n"
4143        "Test PIM message reception\n"
4144        "Test PIM packet dump reception from neighbor\n"
4145        "Interface\n"
4146        "Neighbor address\n"
4147        "Packet dump\n")
4148 {
4149   uint8_t           buf[1000];
4150   uint8_t          *pim_msg;
4151   struct ip        *ip_hdr;
4152   size_t            ip_hlen; /* ip header length in bytes */
4153   int               ip_msg_len;
4154   int               pim_msg_size;
4155   const char       *neigh_str;
4156   struct in_addr    neigh_addr;
4157   const char       *ifname;
4158   struct interface *ifp;
4159   int               argi;
4160   int               result;
4161
4162   /* Find interface */
4163   ifname = argv[0];
4164   ifp = if_lookup_by_name(ifname);
4165   if (!ifp) {
4166     vty_out(vty, "No such interface name %s%s",
4167             ifname, VTY_NEWLINE);
4168     return CMD_WARNING;
4169   }
4170
4171   /* Neighbor address */
4172   neigh_str = argv[1];
4173   result = inet_pton(AF_INET, neigh_str, &neigh_addr);
4174   if (result <= 0) {
4175     vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
4176             neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
4177     return CMD_WARNING;
4178   }
4179
4180   /*
4181     Tweak IP header
4182    */
4183   ip_hdr = (struct ip *) buf;
4184   ip_hdr->ip_p = PIM_IP_PROTO_PIM;
4185   ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4186   ip_hdr->ip_hl = ip_hlen >> 2;    /* ip header length in 4-byte words */
4187   ip_hdr->ip_src = neigh_addr;
4188   ip_hdr->ip_dst = qpim_all_pim_routers_addr;
4189
4190   /*
4191     Build PIM hello message
4192   */
4193   pim_msg = buf + ip_hlen;
4194   pim_msg_size = 0;
4195
4196   /* Scan LINE dump into buffer */
4197   for (argi = 2; argi < argc; ++argi) {
4198     const char *str = argv[argi];
4199     int str_len = strlen(str);
4200     int str_last = str_len - 1;
4201     int i;
4202
4203     if (str_len % 2) {
4204       vty_out(vty, "%% Uneven hex array arg %d=%s%s",
4205               argi, str, VTY_NEWLINE);
4206       return CMD_WARNING;
4207     }
4208
4209     for (i = 0; i < str_last; i += 2) {
4210       uint8_t octet;
4211       int left;
4212       uint8_t h1 = str[i];
4213       uint8_t h2 = str[i + 1];
4214
4215       if (!isxdigit(h1) || !isxdigit(h2)) {
4216         vty_out(vty, "%% Non-hex octet %c%c at hex array arg %d=%s%s",
4217                 h1, h2, argi, str, VTY_NEWLINE);
4218         return CMD_WARNING;
4219       }
4220       octet = (hexval(h1) << 4) + hexval(h2);
4221
4222       left = sizeof(buf) - ip_hlen - pim_msg_size;
4223       if (left < 1) {
4224         vty_out(vty, "%% Overflow buf_size=%zu buf_left=%d at hex array arg %d=%s octet %02x%s",
4225                 sizeof(buf), left, argi, str, octet, VTY_NEWLINE);
4226         return CMD_WARNING;
4227       }
4228       
4229       pim_msg[pim_msg_size++] = octet;
4230     }
4231   }
4232
4233   ip_msg_len = ip_hlen + pim_msg_size;
4234
4235   vty_out(vty, "Receiving: buf_size=%zu ip_msg_size=%d pim_msg_size=%d%s",
4236           sizeof(buf), ip_msg_len, pim_msg_size, VTY_NEWLINE);
4237
4238   /* "receive" message */
4239
4240   result = pim_pim_packet(ifp, buf, ip_msg_len);
4241   if (result) {
4242     vty_out(vty, "%% pim_pim_packet(len=%d) returned failure: %d%s",
4243             ip_msg_len, result, VTY_NEWLINE);
4244     return CMD_WARNING;
4245   }
4246
4247   return CMD_SUCCESS;
4248 }
4249
4250 DEFUN (test_pim_receive_hello,
4251        test_pim_receive_hello_cmd,
4252        "test pim receive hello INTERFACE A.B.C.D <0-65535> <0-65535> <0-65535> <0-32767> <0-65535> <0-1>[LINE]",
4253        "Test\n"
4254        "Test PIM protocol\n"
4255        "Test PIM message reception\n"
4256        "Test PIM hello reception from neighbor\n"
4257        "Interface\n"
4258        "Neighbor address\n"
4259        "Neighbor holdtime\n"
4260        "Neighbor DR priority\n"
4261        "Neighbor generation ID\n"
4262        "Neighbor propagation delay (msec)\n"
4263        "Neighbor override interval (msec)\n"
4264        "Neighbor LAN prune delay T-bit\n"
4265        "Neighbor secondary addresses\n")
4266 {
4267   uint8_t           buf[1000];
4268   uint8_t          *pim_msg;
4269   struct ip        *ip_hdr;
4270   size_t            ip_hlen; /* ip header length in bytes */
4271   int               ip_msg_len;
4272   int               pim_tlv_size;
4273   int               pim_msg_size;
4274   const char       *neigh_str;
4275   struct in_addr    neigh_addr;
4276   const char       *ifname;
4277   struct interface *ifp;
4278   uint16_t          neigh_holdtime;
4279   uint16_t          neigh_propagation_delay;
4280   uint16_t          neigh_override_interval;
4281   int               neigh_can_disable_join_suppression;
4282   uint32_t          neigh_dr_priority;
4283   uint32_t          neigh_generation_id;
4284   int               argi;
4285   int               result;
4286
4287   /* Find interface */
4288   ifname = argv[0];
4289   ifp = if_lookup_by_name(ifname);
4290   if (!ifp) {
4291     vty_out(vty, "No such interface name %s%s",
4292             ifname, VTY_NEWLINE);
4293     return CMD_WARNING;
4294   }
4295
4296   /* Neighbor address */
4297   neigh_str = argv[1];
4298   result = inet_pton(AF_INET, neigh_str, &neigh_addr);
4299   if (result <= 0) {
4300     vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
4301             neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
4302     return CMD_WARNING;
4303   }
4304
4305   neigh_holdtime                     = atoi(argv[2]);
4306   neigh_dr_priority                  = atoi(argv[3]);
4307   neigh_generation_id                = atoi(argv[4]);
4308   neigh_propagation_delay            = atoi(argv[5]);
4309   neigh_override_interval            = atoi(argv[6]);
4310   neigh_can_disable_join_suppression = atoi(argv[7]);
4311
4312   /*
4313     Tweak IP header
4314    */
4315   ip_hdr = (struct ip *) buf;
4316   ip_hdr->ip_p = PIM_IP_PROTO_PIM;
4317   ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4318   ip_hdr->ip_hl = ip_hlen >> 2;    /* ip header length in 4-byte words */
4319   ip_hdr->ip_src = neigh_addr;
4320   ip_hdr->ip_dst = qpim_all_pim_routers_addr;
4321
4322   /*
4323     Build PIM hello message
4324   */
4325   pim_msg = buf + ip_hlen;
4326
4327   /* Scan LINE addresses */
4328   for (argi = 8; argi < argc; ++argi) {
4329     const char *sec_str = argv[argi];
4330     struct in_addr sec_addr;
4331     result = inet_pton(AF_INET, sec_str, &sec_addr);
4332     if (result <= 0) {
4333       vty_out(vty, "Bad neighbor secondary address %s: errno=%d: %s%s",
4334               sec_str, errno, safe_strerror(errno), VTY_NEWLINE);
4335       return CMD_WARNING;
4336     }
4337
4338     vty_out(vty,
4339             "FIXME WRITEME consider neighbor secondary address %s%s",
4340             sec_str, VTY_NEWLINE);
4341   }
4342
4343   pim_tlv_size = pim_hello_build_tlv(ifp->name,
4344                                      pim_msg + PIM_PIM_MIN_LEN,
4345                                      sizeof(buf) - ip_hlen - PIM_PIM_MIN_LEN,
4346                                      neigh_holdtime,
4347                                      neigh_dr_priority,
4348                                      neigh_generation_id,
4349                                      neigh_propagation_delay,
4350                                      neigh_override_interval,
4351                                      neigh_can_disable_join_suppression,
4352                                      0 /* FIXME secondary address list */);
4353   if (pim_tlv_size < 0) {
4354     vty_out(vty, "pim_hello_build_tlv() returned failure: %d%s",
4355             pim_tlv_size, VTY_NEWLINE);
4356     return CMD_WARNING;
4357   }
4358
4359   pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
4360
4361   pim_msg_build_header(pim_msg, pim_msg_size,
4362                        PIM_MSG_TYPE_HELLO);
4363
4364   /* "receive" message */
4365
4366   ip_msg_len = ip_hlen + pim_msg_size;
4367   result = pim_pim_packet(ifp, buf, ip_msg_len);
4368   if (result) {
4369     vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
4370             ip_msg_len, result, VTY_NEWLINE);
4371     return CMD_WARNING;
4372   }
4373
4374   return CMD_SUCCESS;
4375 }
4376
4377 DEFUN (test_pim_receive_assert,
4378        test_pim_receive_assert_cmd,
4379        "test pim receive assert INTERFACE A.B.C.D A.B.C.D A.B.C.D <0-65535> <0-65535> <0-1>",
4380        "Test\n"
4381        "Test PIM protocol\n"
4382        "Test PIM message reception\n"
4383        "Test reception of PIM assert\n"
4384        "Interface\n"
4385        "Neighbor address\n"
4386        "Assert multicast group address\n"
4387        "Assert unicast source address\n"
4388        "Assert metric preference\n"
4389        "Assert route metric\n"
4390        "Assert RPT bit flag\n")
4391 {
4392   uint8_t           buf[1000];
4393   uint8_t          *buf_pastend = buf + sizeof(buf);
4394   uint8_t          *pim_msg;
4395   struct ip        *ip_hdr;
4396   size_t            ip_hlen; /* ip header length in bytes */
4397   int               ip_msg_len;
4398   int               pim_msg_size;
4399   const char       *neigh_str;
4400   struct in_addr    neigh_addr;
4401   const char       *group_str;
4402   struct in_addr    group_addr;
4403   const char       *source_str;
4404   struct in_addr    source_addr;
4405   const char       *ifname;
4406   struct interface *ifp;
4407   uint32_t          assert_metric_preference;
4408   uint32_t          assert_route_metric;
4409   uint32_t          assert_rpt_bit_flag;
4410   int               remain;
4411   int               result;
4412
4413   /* Find interface */
4414   ifname = argv[0];
4415   ifp = if_lookup_by_name(ifname);
4416   if (!ifp) {
4417     vty_out(vty, "No such interface name %s%s",
4418             ifname, VTY_NEWLINE);
4419     return CMD_WARNING;
4420   }
4421
4422   /* Neighbor address */
4423   neigh_str = argv[1];
4424   result = inet_pton(AF_INET, neigh_str, &neigh_addr);
4425   if (result <= 0) {
4426     vty_out(vty, "Bad neighbor address %s: errno=%d: %s%s",
4427             neigh_str, errno, safe_strerror(errno), VTY_NEWLINE);
4428     return CMD_WARNING;
4429   }
4430
4431   /* Group address */
4432   group_str = argv[2];
4433   result = inet_pton(AF_INET, group_str, &group_addr);
4434   if (result <= 0) {
4435     vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4436             group_str, errno, safe_strerror(errno), VTY_NEWLINE);
4437     return CMD_WARNING;
4438   }
4439
4440   /* Source address */
4441   source_str = argv[3];
4442   result = inet_pton(AF_INET, source_str, &source_addr);
4443   if (result <= 0) {
4444     vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4445             source_str, errno, safe_strerror(errno), VTY_NEWLINE);
4446     return CMD_WARNING;
4447   }
4448
4449   assert_metric_preference = atoi(argv[4]);
4450   assert_route_metric      = atoi(argv[5]);
4451   assert_rpt_bit_flag      = atoi(argv[6]);
4452
4453   remain = buf_pastend - buf;
4454   if (remain < (int) sizeof(struct ip)) {
4455     vty_out(vty, "No room for ip header: buf_size=%d < ip_header_size=%zu%s",
4456             remain, sizeof(struct ip), VTY_NEWLINE);
4457     return CMD_WARNING;
4458   }
4459
4460   /*
4461     Tweak IP header
4462    */
4463   ip_hdr = (struct ip *) buf;
4464   ip_hdr->ip_p = PIM_IP_PROTO_PIM;
4465   ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4466   ip_hdr->ip_hl = ip_hlen >> 2;    /* ip header length in 4-byte words */
4467   ip_hdr->ip_src = neigh_addr;
4468   ip_hdr->ip_dst = qpim_all_pim_routers_addr;
4469
4470   /*
4471     Build PIM assert message
4472   */
4473   pim_msg = buf + ip_hlen; /* skip ip header */
4474
4475   pim_msg_size = pim_assert_build_msg(pim_msg, buf_pastend - pim_msg, ifp,
4476                                       group_addr, source_addr,
4477                                       assert_metric_preference,
4478                                       assert_route_metric,
4479                                       assert_rpt_bit_flag);
4480   if (pim_msg_size < 0) {
4481     vty_out(vty, "Failure building PIM assert message: size=%d%s",
4482             pim_msg_size, VTY_NEWLINE);
4483     return CMD_WARNING;
4484   }
4485
4486   /* "receive" message */
4487
4488   ip_msg_len = ip_hlen + pim_msg_size;
4489   result = pim_pim_packet(ifp, buf, ip_msg_len);
4490   if (result) {
4491     vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
4492             ip_msg_len, result, VTY_NEWLINE);
4493     return CMD_WARNING;
4494   }
4495
4496   return CMD_SUCCESS;
4497 }
4498
4499 static int recv_joinprune(struct vty *vty,
4500                           const char *argv[],
4501                           int src_is_join)
4502 {
4503   uint8_t           buf[1000];
4504   const uint8_t    *buf_pastend = buf + sizeof(buf);
4505   uint8_t          *pim_msg;
4506   uint8_t          *pim_msg_curr;
4507   int               pim_msg_size;
4508   struct ip        *ip_hdr;
4509   size_t            ip_hlen; /* ip header length in bytes */
4510   int               ip_msg_len;
4511   uint16_t          neigh_holdtime;
4512   const char       *neigh_dst_str;
4513   struct in_addr    neigh_dst_addr;
4514   const char       *neigh_src_str;
4515   struct in_addr    neigh_src_addr;
4516   const char       *group_str;
4517   struct in_addr    group_addr;
4518   const char       *source_str;
4519   struct in_addr    source_addr;
4520   const char       *ifname;
4521   struct interface *ifp;
4522   int               result;
4523   int               remain;
4524   uint16_t          num_joined;
4525   uint16_t          num_pruned;
4526
4527   /* Find interface */
4528   ifname = argv[0];
4529   ifp = if_lookup_by_name(ifname);
4530   if (!ifp) {
4531     vty_out(vty, "No such interface name %s%s",
4532             ifname, VTY_NEWLINE);
4533     return CMD_WARNING;
4534   }
4535
4536   neigh_holdtime = atoi(argv[1]);
4537
4538   /* Neighbor destination address */
4539   neigh_dst_str = argv[2];
4540   result = inet_pton(AF_INET, neigh_dst_str, &neigh_dst_addr);
4541   if (result <= 0) {
4542     vty_out(vty, "Bad neighbor destination address %s: errno=%d: %s%s",
4543             neigh_dst_str, errno, safe_strerror(errno), VTY_NEWLINE);
4544     return CMD_WARNING;
4545   }
4546
4547   /* Neighbor source address */
4548   neigh_src_str = argv[3];
4549   result = inet_pton(AF_INET, neigh_src_str, &neigh_src_addr);
4550   if (result <= 0) {
4551     vty_out(vty, "Bad neighbor source address %s: errno=%d: %s%s",
4552             neigh_src_str, errno, safe_strerror(errno), VTY_NEWLINE);
4553     return CMD_WARNING;
4554   }
4555
4556   /* Multicast group address */
4557   group_str = argv[4];
4558   result = inet_pton(AF_INET, group_str, &group_addr);
4559   if (result <= 0) {
4560     vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4561             group_str, errno, safe_strerror(errno), VTY_NEWLINE);
4562     return CMD_WARNING;
4563   }
4564
4565   /* Multicast source address */
4566   source_str = argv[5];
4567   result = inet_pton(AF_INET, source_str, &source_addr);
4568   if (result <= 0) {
4569     vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4570             source_str, errno, safe_strerror(errno), VTY_NEWLINE);
4571     return CMD_WARNING;
4572   }
4573
4574   /*
4575     Tweak IP header
4576    */
4577   ip_hdr = (struct ip *) buf;
4578   ip_hdr->ip_p = PIM_IP_PROTO_PIM;
4579   ip_hlen = PIM_IP_HEADER_MIN_LEN; /* ip header length in bytes */
4580   ip_hdr->ip_hl = ip_hlen >> 2;    /* ip header length in 4-byte words */
4581   ip_hdr->ip_src = neigh_src_addr;
4582   ip_hdr->ip_dst = qpim_all_pim_routers_addr;
4583
4584   /*
4585     Build PIM message
4586   */
4587   pim_msg = buf + ip_hlen;
4588
4589   /* skip room for pim header */
4590   pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN;
4591
4592   remain = buf_pastend - pim_msg_curr;
4593   pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr,
4594                                                 remain,
4595                                                 neigh_dst_addr);
4596   if (!pim_msg_curr) {
4597     vty_out(vty, "Failure encoding destination address %s: space left=%d%s",
4598             neigh_dst_str, remain, VTY_NEWLINE);
4599     return CMD_WARNING;
4600   }
4601
4602   remain = buf_pastend - pim_msg_curr;
4603   if (remain < 4) {
4604     vty_out(vty, "Group will not fit: space left=%d%s",
4605             remain, VTY_NEWLINE);
4606     return CMD_WARNING;
4607   }
4608
4609   *pim_msg_curr = 0; /* reserved */
4610   ++pim_msg_curr;
4611   *pim_msg_curr = 1; /* number of groups */
4612   ++pim_msg_curr;
4613   *((uint16_t *) pim_msg_curr) = htons(neigh_holdtime);
4614   ++pim_msg_curr;
4615   ++pim_msg_curr;
4616
4617   remain = buf_pastend - pim_msg_curr;
4618   pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr,
4619                                                 remain,
4620                                                 group_addr);
4621   if (!pim_msg_curr) {
4622     vty_out(vty, "Failure encoding group address %s: space left=%d%s",
4623             group_str, remain, VTY_NEWLINE);
4624     return CMD_WARNING;
4625   }
4626
4627   remain = buf_pastend - pim_msg_curr;
4628   if (remain < 4) {
4629     vty_out(vty, "Sources will not fit: space left=%d%s",
4630             remain, VTY_NEWLINE);
4631     return CMD_WARNING;
4632   }
4633
4634   if (src_is_join) {
4635     num_joined = 1;
4636     num_pruned = 0;
4637   }
4638   else {
4639     num_joined = 0;
4640     num_pruned = 1;
4641   }
4642
4643   /* number of joined sources */
4644   *((uint16_t *) pim_msg_curr) = htons(num_joined);
4645   ++pim_msg_curr;
4646   ++pim_msg_curr;
4647
4648   /* number of pruned sources */
4649   *((uint16_t *) pim_msg_curr) = htons(num_pruned);
4650   ++pim_msg_curr;
4651   ++pim_msg_curr;
4652
4653   remain = buf_pastend - pim_msg_curr;
4654   pim_msg_curr = pim_msg_addr_encode_ipv4_source(pim_msg_curr,
4655                                                  remain,
4656                                                  source_addr);
4657   if (!pim_msg_curr) {
4658     vty_out(vty, "Failure encoding source address %s: space left=%d%s",
4659             source_str, remain, VTY_NEWLINE);
4660     return CMD_WARNING;
4661   }
4662
4663   /* Add PIM header */
4664
4665   pim_msg_size = pim_msg_curr - pim_msg;
4666
4667   pim_msg_build_header(pim_msg, pim_msg_size,
4668                        PIM_MSG_TYPE_JOIN_PRUNE);
4669
4670   /*
4671     "Receive" message
4672   */
4673
4674   ip_msg_len = ip_hlen + pim_msg_size;
4675   result = pim_pim_packet(ifp, buf, ip_msg_len);
4676   if (result) {
4677     vty_out(vty, "pim_pim_packet(len=%d) returned failure: %d%s",
4678             ip_msg_len, result, VTY_NEWLINE);
4679     return CMD_WARNING;
4680   }
4681
4682   return CMD_SUCCESS;
4683 }
4684
4685 DEFUN (test_pim_receive_join,
4686        test_pim_receive_join_cmd,
4687        "test pim receive join INTERFACE <0-65535> A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
4688        "Test\n"
4689        "Test PIM protocol\n"
4690        "Test PIM message reception\n"
4691        "Test PIM join reception from neighbor\n"
4692        "Interface\n"
4693        "Neighbor holdtime\n"
4694        "Upstream neighbor unicast destination address\n"
4695        "Downstream neighbor unicast source address\n"
4696        "Multicast group address\n"
4697        "Unicast source address\n")
4698 {
4699   return recv_joinprune(vty, argv, 1 /* src_is_join=true */);
4700 }
4701
4702 DEFUN (test_pim_receive_prune,
4703        test_pim_receive_prune_cmd,
4704        "test pim receive prune INTERFACE <0-65535> A.B.C.D A.B.C.D A.B.C.D A.B.C.D",
4705        "Test\n"
4706        "Test PIM protocol\n"
4707        "Test PIM message reception\n"
4708        "Test PIM prune reception from neighbor\n"
4709        "Interface\n"
4710        "Neighbor holdtime\n"
4711        "Upstream neighbor unicast destination address\n"
4712        "Downstream neighbor unicast source address\n"
4713        "Multicast group address\n"
4714        "Unicast source address\n")
4715 {
4716   return recv_joinprune(vty, argv, 0 /* src_is_join=false */);
4717 }
4718
4719 DEFUN (test_pim_receive_upcall,
4720        test_pim_receive_upcall_cmd,
4721        "test pim receive upcall (nocache|wrongvif|wholepkt) <0-65535> A.B.C.D A.B.C.D",
4722        "Test\n"
4723        "Test PIM protocol\n"
4724        "Test PIM message reception\n"
4725        "Test reception of kernel upcall\n"
4726        "NOCACHE kernel upcall\n"
4727        "WRONGVIF kernel upcall\n"
4728        "WHOLEPKT kernel upcall\n"
4729        "Input interface vif index\n"
4730        "Multicast group address\n"
4731        "Multicast source address\n")
4732 {
4733   struct igmpmsg msg;
4734   const char *upcall_type;
4735   const char *group_str;
4736   const char *source_str;
4737   int result;
4738
4739   upcall_type = argv[0];
4740
4741   if (upcall_type[0] == 'n')
4742     msg.im_msgtype = IGMPMSG_NOCACHE;
4743   else if (upcall_type[1] == 'r')
4744     msg.im_msgtype = IGMPMSG_WRONGVIF;
4745   else if (upcall_type[1] == 'h')
4746     msg.im_msgtype = IGMPMSG_WHOLEPKT;
4747   else {
4748     vty_out(vty, "Unknown kernel upcall type: %s%s",
4749             upcall_type, VTY_NEWLINE);
4750     return CMD_WARNING;
4751   }
4752
4753   msg.im_vif = atoi(argv[1]);
4754
4755   /* Group address */
4756   group_str = argv[2];
4757   result = inet_pton(AF_INET, group_str, &msg.im_dst);
4758   if (result <= 0) {
4759     vty_out(vty, "Bad group address %s: errno=%d: %s%s",
4760             group_str, errno, safe_strerror(errno), VTY_NEWLINE);
4761     return CMD_WARNING;
4762   }
4763
4764   /* Source address */
4765   source_str = argv[3];
4766   result = inet_pton(AF_INET, source_str, &msg.im_src);
4767   if (result <= 0) {
4768     vty_out(vty, "Bad source address %s: errno=%d: %s%s",
4769             source_str, errno, safe_strerror(errno), VTY_NEWLINE);
4770     return CMD_WARNING;
4771   }
4772
4773   msg.im_mbz = 0; /* Must be zero */
4774
4775   result = pim_mroute_msg(-1, (char *) &msg, sizeof(msg));
4776   if (result) {
4777     vty_out(vty, "pim_mroute_msg(len=%zu) returned failure: %d%s",
4778             sizeof(msg), result, VTY_NEWLINE);
4779     return CMD_WARNING;
4780   }
4781
4782   return CMD_SUCCESS;
4783 }
4784
4785 void pim_cmd_init()
4786 {
4787   install_node (&pim_global_node, pim_global_config_write);       /* PIM_NODE */
4788   install_node (&interface_node, pim_interface_config_write); /* INTERFACE_NODE */
4789
4790   install_element (CONFIG_NODE, &ip_multicast_routing_cmd);
4791   install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd);
4792   install_element (CONFIG_NODE, &ip_ssmpingd_cmd);
4793   install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); 
4794 #if 0
4795   install_element (CONFIG_NODE, &interface_cmd); /* from if.h */
4796 #else
4797   install_element (CONFIG_NODE, &pim_interface_cmd);
4798 #endif
4799   install_element (CONFIG_NODE, &no_interface_cmd); /* from if.h */
4800
4801   install_default (INTERFACE_NODE);
4802   install_element (INTERFACE_NODE, &interface_ip_igmp_cmd);
4803   install_element (INTERFACE_NODE, &interface_no_ip_igmp_cmd); 
4804   install_element (INTERFACE_NODE, &interface_ip_igmp_join_cmd);
4805   install_element (INTERFACE_NODE, &interface_no_ip_igmp_join_cmd); 
4806   install_element (INTERFACE_NODE, &interface_ip_igmp_query_interval_cmd);
4807   install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_interval_cmd); 
4808   install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_cmd);
4809   install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_cmd); 
4810   install_element (INTERFACE_NODE, &interface_ip_igmp_query_max_response_time_dsec_cmd);
4811   install_element (INTERFACE_NODE, &interface_no_ip_igmp_query_max_response_time_dsec_cmd); 
4812   install_element (INTERFACE_NODE, &interface_ip_pim_ssm_cmd);
4813   install_element (INTERFACE_NODE, &interface_no_ip_pim_ssm_cmd);
4814   install_element (INTERFACE_NODE, &interface_ip_pim_drprio_cmd);
4815   install_element (INTERFACE_NODE, &interface_no_ip_pim_drprio_cmd);
4816   install_element (INTERFACE_NODE, &interface_ip_pim_hello_cmd);
4817   install_element (INTERFACE_NODE, &interface_ip_pim_hello_hold_cmd);
4818   install_element (INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
4819
4820   // Static mroutes NEB
4821   install_element (INTERFACE_NODE, &interface_ip_mroute_cmd);
4822   install_element (INTERFACE_NODE, &interface_ip_mroute_source_cmd);
4823   install_element (INTERFACE_NODE, &interface_no_ip_mroute_cmd);
4824   install_element (INTERFACE_NODE, &interface_no_ip_mroute_source_cmd);
4825
4826   install_element (VIEW_NODE, &show_ip_igmp_interface_cmd);
4827   install_element (VIEW_NODE, &show_ip_igmp_join_cmd);
4828   install_element (VIEW_NODE, &show_ip_igmp_parameters_cmd);
4829   install_element (VIEW_NODE, &show_ip_igmp_groups_cmd);
4830   install_element (VIEW_NODE, &show_ip_igmp_groups_retransmissions_cmd);
4831   install_element (VIEW_NODE, &show_ip_igmp_sources_cmd);
4832   install_element (VIEW_NODE, &show_ip_igmp_sources_retransmissions_cmd);
4833   install_element (VIEW_NODE, &show_ip_igmp_querier_cmd);
4834   install_element (VIEW_NODE, &show_ip_pim_assert_cmd);
4835   install_element (VIEW_NODE, &show_ip_pim_assert_internal_cmd);
4836   install_element (VIEW_NODE, &show_ip_pim_assert_metric_cmd);
4837   install_element (VIEW_NODE, &show_ip_pim_assert_winner_metric_cmd);
4838   install_element (VIEW_NODE, &show_ip_pim_dr_cmd);
4839   install_element (VIEW_NODE, &show_ip_pim_hello_cmd);
4840   install_element (VIEW_NODE, &show_ip_pim_interface_cmd);
4841   install_element (VIEW_NODE, &show_ip_pim_join_cmd);
4842   install_element (VIEW_NODE, &show_ip_pim_jp_override_interval_cmd);
4843   install_element (VIEW_NODE, &show_ip_pim_lan_prune_delay_cmd);
4844   install_element (VIEW_NODE, &show_ip_pim_local_membership_cmd);
4845   install_element (VIEW_NODE, &show_ip_pim_neighbor_cmd);
4846   install_element (VIEW_NODE, &show_ip_pim_rpf_cmd);
4847   install_element (VIEW_NODE, &show_ip_pim_secondary_cmd);
4848   install_element (VIEW_NODE, &show_ip_pim_upstream_cmd);
4849   install_element (VIEW_NODE, &show_ip_pim_upstream_join_desired_cmd);
4850   install_element (VIEW_NODE, &show_ip_pim_upstream_rpf_cmd);
4851   install_element (VIEW_NODE, &show_ip_multicast_cmd);
4852   install_element (VIEW_NODE, &show_ip_mroute_cmd);
4853   install_element (VIEW_NODE, &show_ip_mroute_count_cmd);
4854   install_element (VIEW_NODE, &show_ip_rib_cmd);
4855   install_element (VIEW_NODE, &show_ip_ssmpingd_cmd);
4856   install_element (VIEW_NODE, &show_debugging_pim_cmd);
4857
4858   install_element (ENABLE_NODE, &clear_ip_interfaces_cmd);
4859   install_element (ENABLE_NODE, &clear_ip_igmp_interfaces_cmd);
4860   install_element (ENABLE_NODE, &clear_ip_mroute_cmd);
4861   install_element (ENABLE_NODE, &clear_ip_pim_interfaces_cmd);
4862   install_element (ENABLE_NODE, &clear_ip_pim_oil_cmd);
4863
4864   install_element (ENABLE_NODE, &test_igmp_receive_report_cmd);
4865   install_element (ENABLE_NODE, &test_pim_receive_assert_cmd);
4866   install_element (ENABLE_NODE, &test_pim_receive_dump_cmd);
4867   install_element (ENABLE_NODE, &test_pim_receive_hello_cmd);
4868   install_element (ENABLE_NODE, &test_pim_receive_join_cmd);
4869   install_element (ENABLE_NODE, &test_pim_receive_prune_cmd);
4870   install_element (ENABLE_NODE, &test_pim_receive_upcall_cmd);
4871
4872   install_element (ENABLE_NODE, &debug_igmp_cmd);
4873   install_element (ENABLE_NODE, &no_debug_igmp_cmd);
4874   install_element (ENABLE_NODE, &undebug_igmp_cmd);
4875   install_element (ENABLE_NODE, &debug_igmp_events_cmd);
4876   install_element (ENABLE_NODE, &no_debug_igmp_events_cmd);
4877   install_element (ENABLE_NODE, &undebug_igmp_events_cmd);
4878   install_element (ENABLE_NODE, &debug_igmp_packets_cmd);
4879   install_element (ENABLE_NODE, &no_debug_igmp_packets_cmd);
4880   install_element (ENABLE_NODE, &undebug_igmp_packets_cmd);
4881   install_element (ENABLE_NODE, &debug_igmp_trace_cmd);
4882   install_element (ENABLE_NODE, &no_debug_igmp_trace_cmd);
4883   install_element (ENABLE_NODE, &undebug_igmp_trace_cmd);
4884   install_element (ENABLE_NODE, &debug_mroute_cmd);
4885   install_element (ENABLE_NODE, &no_debug_mroute_cmd);
4886   install_element (ENABLE_NODE, &debug_static_cmd);
4887   install_element (ENABLE_NODE, &no_debug_static_cmd);
4888   install_element (ENABLE_NODE, &debug_pim_cmd);
4889   install_element (ENABLE_NODE, &no_debug_pim_cmd);
4890   install_element (ENABLE_NODE, &undebug_pim_cmd);
4891   install_element (ENABLE_NODE, &debug_pim_events_cmd);
4892   install_element (ENABLE_NODE, &no_debug_pim_events_cmd);
4893   install_element (ENABLE_NODE, &undebug_pim_events_cmd);
4894   install_element (ENABLE_NODE, &debug_pim_packets_cmd);
4895   install_element (ENABLE_NODE, &debug_pim_packets_filter_cmd);
4896   install_element (ENABLE_NODE, &no_debug_pim_packets_cmd);
4897   install_element (ENABLE_NODE, &no_debug_pim_packets_filter_cmd);
4898   install_element (ENABLE_NODE, &undebug_pim_packets_cmd);
4899   install_element (ENABLE_NODE, &debug_pim_packetdump_send_cmd);
4900   install_element (ENABLE_NODE, &no_debug_pim_packetdump_send_cmd);
4901   install_element (ENABLE_NODE, &undebug_pim_packetdump_send_cmd);
4902   install_element (ENABLE_NODE, &debug_pim_packetdump_recv_cmd);
4903   install_element (ENABLE_NODE, &no_debug_pim_packetdump_recv_cmd);
4904   install_element (ENABLE_NODE, &undebug_pim_packetdump_recv_cmd);
4905   install_element (ENABLE_NODE, &debug_pim_trace_cmd);
4906   install_element (ENABLE_NODE, &no_debug_pim_trace_cmd);
4907   install_element (ENABLE_NODE, &undebug_pim_trace_cmd);
4908   install_element (ENABLE_NODE, &debug_ssmpingd_cmd);
4909   install_element (ENABLE_NODE, &no_debug_ssmpingd_cmd);
4910   install_element (ENABLE_NODE, &undebug_ssmpingd_cmd);
4911   install_element (ENABLE_NODE, &debug_pim_zebra_cmd);
4912   install_element (ENABLE_NODE, &no_debug_pim_zebra_cmd);
4913   install_element (ENABLE_NODE, &undebug_pim_zebra_cmd);
4914
4915   install_element (CONFIG_NODE, &debug_igmp_cmd);
4916   install_element (CONFIG_NODE, &no_debug_igmp_cmd);
4917   install_element (CONFIG_NODE, &undebug_igmp_cmd);
4918   install_element (CONFIG_NODE, &debug_igmp_events_cmd);
4919   install_element (CONFIG_NODE, &no_debug_igmp_events_cmd);
4920   install_element (CONFIG_NODE, &undebug_igmp_events_cmd);
4921   install_element (CONFIG_NODE, &debug_igmp_packets_cmd);
4922   install_element (CONFIG_NODE, &no_debug_igmp_packets_cmd);
4923   install_element (CONFIG_NODE, &undebug_igmp_packets_cmd);
4924   install_element (CONFIG_NODE, &debug_igmp_trace_cmd);
4925   install_element (CONFIG_NODE, &no_debug_igmp_trace_cmd);
4926   install_element (CONFIG_NODE, &undebug_igmp_trace_cmd);
4927   install_element (CONFIG_NODE, &debug_mroute_cmd);
4928   install_element (CONFIG_NODE, &no_debug_mroute_cmd);
4929   install_element (CONFIG_NODE, &debug_static_cmd);
4930   install_element (CONFIG_NODE, &no_debug_static_cmd);
4931   install_element (CONFIG_NODE, &debug_pim_cmd);
4932   install_element (CONFIG_NODE, &no_debug_pim_cmd);
4933   install_element (CONFIG_NODE, &undebug_pim_cmd);
4934   install_element (CONFIG_NODE, &debug_pim_events_cmd);
4935   install_element (CONFIG_NODE, &no_debug_pim_events_cmd);
4936   install_element (CONFIG_NODE, &undebug_pim_events_cmd);
4937   install_element (CONFIG_NODE, &debug_pim_packets_cmd);
4938   install_element (CONFIG_NODE, &debug_pim_packets_filter_cmd);
4939   install_element (CONFIG_NODE, &no_debug_pim_packets_cmd);
4940   install_element (CONFIG_NODE, &no_debug_pim_packets_filter_cmd);
4941   install_element (CONFIG_NODE, &undebug_pim_packets_cmd);
4942   install_element (CONFIG_NODE, &debug_pim_trace_cmd);
4943   install_element (CONFIG_NODE, &no_debug_pim_trace_cmd);
4944   install_element (CONFIG_NODE, &undebug_pim_trace_cmd);
4945   install_element (CONFIG_NODE, &debug_ssmpingd_cmd);
4946   install_element (CONFIG_NODE, &no_debug_ssmpingd_cmd);
4947   install_element (CONFIG_NODE, &undebug_ssmpingd_cmd);
4948   install_element (CONFIG_NODE, &debug_pim_zebra_cmd);
4949   install_element (CONFIG_NODE, &no_debug_pim_zebra_cmd);
4950   install_element (CONFIG_NODE, &undebug_pim_zebra_cmd);
4951 }