[pim] Skeleton for ssmpingd support
diff --git a/pimd/Makefile.am b/pimd/Makefile.am
index c722b7e..57bd31a 100644
--- a/pimd/Makefile.am
+++ b/pimd/Makefile.am
@@ -53,7 +53,7 @@
 	pim_oil.c pim_zlookup.c pim_pim.c pim_tlv.c pim_neighbor.c \
 	pim_hello.c pim_ifchannel.c pim_join.c pim_assert.c \
 	pim_msg.c pim_upstream.c pim_rpf.c pim_rand.c pim_macro.c \
-	pim_igmp_join.c
+	pim_igmp_join.c pim_ssmpingd.c
 
 noinst_HEADERS = \
 	pimd.h pim_version.h pim_cmd.h pim_signals.h pim_iface.h \
@@ -62,7 +62,7 @@
 	pim_oil.h pim_zlookup.h pim_pim.h pim_tlv.h pim_neighbor.h \
 	pim_hello.h pim_ifchannel.h pim_join.h pim_assert.h \
 	pim_msg.h pim_upstream.h pim_rpf.h pim_rand.h pim_macro.h \
-	pim_igmp_join.h
+	pim_igmp_join.h pim_ssmpingd.h
 
 pimd_SOURCES = \
 	pim_main.c $(libpim_a_SOURCES)
diff --git a/pimd/TODO b/pimd/TODO
index 6ed98c0..dc2ece5 100644
--- a/pimd/TODO
+++ b/pimd/TODO
@@ -354,4 +354,7 @@
     http://www.ietf.org/internet-drafts/draft-ietf-mboned-lightweight-igmpv3-mldv2-05.txt
     http://www.ietf.org/html.charters/mboned-charter.html
 
+T41 ssmping
+    http://www.venaas.no/multicast/ssmping/
+
 -x-
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 5b47f3b..692c2fc 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -47,6 +47,7 @@
 #include "pim_upstream.h"
 #include "pim_rpf.h"
 #include "pim_macro.h"
+#include "pim_ssmpingd.h"
 
 static struct cmd_node pim_global_node = {
   PIM_NODE,
@@ -2200,6 +2201,63 @@
   return CMD_SUCCESS;
 }
 
+DEFUN (ip_ssmpingd,
+       ip_ssmpingd_cmd,
+       "ip ssmpingd [A.B.C.D]",
+       IP_STR
+       SSMPINGD_STR
+       "Source address\n")
+{
+  int result;
+  struct in_addr source_addr;
+  const char *source_str = (argc > 0) ? argv[0] : "0.0.0.0";
+
+  result = inet_pton(AF_INET, source_str, &source_addr);
+  if (result <= 0) {
+    vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
+	    source_str, errno, safe_strerror(errno), VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  result = pim_ssmpingd_start(source_addr);
+  if (result) {
+    vty_out(vty, "%% Failure starting ssmpingd for source %s: %d%s",
+	    source_str, result, VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_ssmpingd,
+       no_ip_ssmpingd_cmd,
+       "no ip ssmpingd [A.B.C.D]",
+       NO_STR
+       IP_STR
+       SSMPINGD_STR
+       "Source address\n")
+{
+  int result;
+  struct in_addr source_addr;
+  const char *source_str = (argc > 0) ? argv[0] : "0.0.0.0";
+
+  result = inet_pton(AF_INET, source_str, &source_addr);
+  if (result <= 0) {
+    vty_out(vty, "%% Bad source address %s: errno=%d: %s%s",
+	    source_str, errno, safe_strerror(errno), VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  result = pim_ssmpingd_stop(source_addr);
+  if (result) {
+    vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d%s",
+	    source_str, result, VTY_NEWLINE);
+    return CMD_WARNING;
+  }
+
+  return CMD_SUCCESS;
+}
+
 DEFUN (interface_ip_igmp,
        interface_ip_igmp_cmd,
        "ip igmp",
@@ -3788,6 +3846,8 @@
 
   install_element (CONFIG_NODE, &ip_multicast_routing_cmd);
   install_element (CONFIG_NODE, &no_ip_multicast_routing_cmd);
+  install_element (CONFIG_NODE, &ip_ssmpingd_cmd);
+  install_element (CONFIG_NODE, &no_ip_ssmpingd_cmd); 
 #if 0
   install_element (CONFIG_NODE, &interface_cmd); /* from if.h */
 #else
diff --git a/pimd/pim_cmd.h b/pimd/pim_cmd.h
index c2bb61b..f3b2f96 100644
--- a/pimd/pim_cmd.h
+++ b/pimd/pim_cmd.h
@@ -27,6 +27,7 @@
 #define IGMP_STR                               "IGMP information\n"
 #define IGMP_GROUP_STR                         "IGMP groups information\n"
 #define IGMP_SOURCE_STR                        "IGMP sources information\n"
+#define SSMPINGD_STR                           "Enable ssmpingd operation\n"
 #define IFACE_PIM_STR                          "Enable PIM SSM operation\n"
 #define IFACE_IGMP_STR                         "Enable IGMP operation\n"
 #define IFACE_IGMP_QUERY_INTERVAL_STR          "IGMP host query interval\n"
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 009f87c..7806c80 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -38,6 +38,7 @@
 #include "pim_ifchannel.h"
 #include "pim_rand.h"
 #include "pim_sock.h"
+#include "pim_ssmpingd.h"
 
 static void pim_if_igmp_join_del_all(struct interface *ifp);
 
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h
index cfdb8eb..0a702c2 100644
--- a/pimd/pim_iface.h
+++ b/pimd/pim_iface.h
@@ -29,6 +29,7 @@
 #include "vty.h"
 
 #include "pim_igmp.h"
+#include "pim_upstream.h"
 
 #define PIM_IF_MASK_PIM                             (1 << 0)
 #define PIM_IF_MASK_IGMP                            (1 << 1)
diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c
new file mode 100644
index 0000000..e4b16aa
--- /dev/null
+++ b/pimd/pim_ssmpingd.c
@@ -0,0 +1,45 @@
+/*
+  PIM for Quagga
+  Copyright (C) 2008  Everton da Silva Marques
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING; if not, write to the
+  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+  MA 02110-1301 USA
+  
+  $QuaggaId: $Format:%an, %ai, %h$ $
+*/
+
+#include "pim_ssmpingd.h"
+#include "pim_time.h"
+#include "pimd.h"
+
+void pim_ssmpingd_init()
+{
+}
+
+void pim_ssmpingd_destroy()
+{
+  if (qpim_ssmpingd_list)
+    list_free(qpim_ssmpingd_list);
+}
+
+int pim_ssmpingd_start(struct in_addr source_addr)
+{
+  return 0;
+}
+
+int pim_ssmpingd_stop(struct in_addr source_addr)
+{
+  return 0;
+}
diff --git a/pimd/pim_ssmpingd.h b/pimd/pim_ssmpingd.h
new file mode 100644
index 0000000..32563ae
--- /dev/null
+++ b/pimd/pim_ssmpingd.h
@@ -0,0 +1,45 @@
+/*
+  PIM for Quagga
+  Copyright (C) 2008  Everton da Silva Marques
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING; if not, write to the
+  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+  MA 02110-1301 USA
+  
+  $QuaggaId: $Format:%an, %ai, %h$ $
+*/
+
+#ifndef PIM_SSMPINGD_H
+#define PIM_SSMPINGD_H
+
+#include <zebra.h>
+
+#include "if.h"
+
+#include "pim_iface.h"
+
+struct ssmpingd_sock {
+  int            sock_fd;     /* socket */
+  struct thread *t_sock_read; /* thread for reading socket */
+  struct in_addr source;      /* source address */
+  int64_t        creation;    /* timestamp of socket creation */
+  int64_t        requests;    /* counter */
+};
+
+void pim_ssmpingd_init(void);
+void pim_ssmpingd_destroy(void);
+int pim_ssmpingd_start(struct in_addr source_addr);
+int pim_ssmpingd_stop(struct in_addr source_addr);
+
+#endif /* PIM_SSMPINGD_H */
diff --git a/pimd/pimd.c b/pimd/pimd.c
index f1a084f..220604d 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -35,6 +35,7 @@
 #include "pim_upstream.h"
 #include "pim_rand.h"
 #include "pim_rpf.h"
+#include "pim_ssmpingd.h"
 
 const char *const PIM_ALL_SYSTEMS      = MCAST_ALL_SYSTEMS;
 const char *const PIM_ALL_ROUTERS      = MCAST_ALL_ROUTERS;
@@ -58,9 +59,12 @@
 int64_t                   qpim_rpf_cache_refresh_events = 0;
 int64_t                   qpim_rpf_cache_refresh_last =  0;
 struct in_addr            qpim_inaddr_any;
+struct list              *qpim_ssmpingd_list = 0;
 
 static void pim_free()
 {
+  pim_ssmpingd_destroy();
+
   if (qpim_channel_oil_list)
     list_free(qpim_channel_oil_list);
 
@@ -120,6 +124,7 @@
 
   pim_if_init();
   pim_cmd_init();
+  pim_ssmpingd_init();
 }
 
 void pim_terminate()
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 6ee91e7..bdf83b4 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -84,6 +84,7 @@
 int64_t                   qpim_rpf_cache_refresh_events;
 int64_t                   qpim_rpf_cache_refresh_last;
 struct in_addr            qpim_inaddr_any;
+struct list              *qpim_ssmpingd_list; /* list of struct ssmpingd_sock */
 
 #define PIM_JP_HOLDTIME (qpim_t_periodic * 7 / 2)