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 
pim_if_membership_clear(struct interface * ifp)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  */
pim_if_membership_refresh(struct interface * ifp)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 
pim_show_assert(struct vty * vty)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 
pim_show_assert_internal(struct vty * vty)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 
pim_show_assert_metric(struct vty * vty)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 
pim_show_assert_winner_metric(struct vty * vty)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 
pim_show_membership(struct vty * vty)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 
igmp_show_interfaces(struct vty * vty)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 
igmp_show_interface_join(struct vty * vty)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 
show_interface_address(struct vty * vty)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 
pim_show_dr(struct vty * vty)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 
pim_show_hello(struct vty * vty)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 
pim_show_interfaces(struct vty * vty)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 
pim_show_join(struct vty * vty)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 
pim_show_neighbors(struct vty * vty)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 
pim_show_lan_prune_delay(struct vty * vty)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 
pim_show_jp_override_interval(struct vty * vty)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 
pim_show_neighbors_secondary(struct vty * vty)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 
pim_show_upstream(struct vty * vty)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 
pim_show_join_desired(struct vty * vty)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 
pim_show_upstream_rpf(struct vty * vty)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 
show_rpf_refresh_stats(struct vty * vty,time_t now)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 
show_scan_oil_stats(struct vty * vty,time_t now)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 
pim_show_rpf(struct vty * vty)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 
igmp_show_querier(struct vty * vty)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 
igmp_show_groups(struct vty * vty)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 
igmp_show_group_retransmission(struct vty * vty)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 
igmp_show_parameters(struct vty * vty)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 
igmp_show_sources(struct vty * vty)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 
igmp_show_source_retransmission(struct vty * vty)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 
clear_igmp_interfaces()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 
clear_pim_interfaces()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 
clear_interfaces()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 
mroute_add_all()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 
mroute_del_all()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 
static_mroute_add_all()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 
static_mroute_del_all()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 
show_multicast_interfaces(struct vty * vty)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 
show_mroute(struct vty * vty)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 
show_mroute_count(struct vty * vty)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 
show_ssmpingd(struct vty * vty)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  */
igmp_sock_query_interval_reconfig(struct igmp_sock * igmp)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 
igmp_sock_query_reschedule(struct igmp_sock * igmp)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 
change_query_interval(struct pim_interface * pim_ifp,int query_interval)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 
change_query_max_response_time(struct pim_interface * pim_ifp,int query_max_response_time_dsec)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 
find_igmp_sock_by_fd(int fd)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 
hexval(uint8_t ch)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 
recv_joinprune(struct vty * vty,const char * argv[],int src_is_join)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 
pim_cmd_init()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 }
4952