[pim] igmpv3: specific query interval set to 1 second (RFC 3376 8.8.)
[pim] pim messages: encoded source address format with Sparse bit=1 (RFC 4601 4.9.1.)
[pim] and Mask Len MUST be equal to 32
[pim] dr election: new traces
[pim] fix triggered_hello_delay_msec randomization
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index b3df018..009f87c 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -85,9 +85,10 @@
   pim_ifp->options                           = 0;
   pim_ifp->mroute_vif_index                  = -1;
 
-  pim_ifp->igmp_default_robustness_variable  = IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
-  pim_ifp->igmp_default_query_interval       = IGMP_GENERAL_QUERY_INTERVAL;
-  pim_ifp->igmp_query_max_response_time_dsec = IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
+  pim_ifp->igmp_default_robustness_variable           = IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
+  pim_ifp->igmp_default_query_interval                = IGMP_GENERAL_QUERY_INTERVAL;
+  pim_ifp->igmp_query_max_response_time_dsec          = IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
+  pim_ifp->igmp_specific_query_max_response_time_dsec = IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
 
   /*
     RFC 3376: 8.3. Query Response Interval
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h
index 6ce866b..bc99aaf 100644
--- a/pimd/pim_iface.h
+++ b/pimd/pim_iface.h
@@ -57,11 +57,12 @@
   int            mroute_vif_index;
   struct in_addr primary_address; /* remember addr to detect change */
 
-  int          igmp_default_robustness_variable;   /* IGMPv3 QRV */
-  int          igmp_default_query_interval;        /* IGMPv3 secs between general queries */
-  int          igmp_query_max_response_time_dsec;  /* IGMPv3 Max Response Time in dsecs */
-  struct list *igmp_socket_list;                   /* list of struct igmp_sock */
-  struct list *igmp_join_list;                     /* list of struct igmp_join */
+  int          igmp_default_robustness_variable;            /* IGMPv3 QRV */
+  int          igmp_default_query_interval;                 /* IGMPv3 secs between general queries */
+  int          igmp_query_max_response_time_dsec;           /* IGMPv3 Max Response Time in dsecs for general queries */
+  int          igmp_specific_query_max_response_time_dsec;  /* IGMPv3 Max Response Time in dsecs for specific queries */
+  struct list *igmp_socket_list;                            /* list of struct igmp_sock */
+  struct list *igmp_join_list;                              /* list of struct igmp_join */
 
   int            pim_sock_fd;       /* PIM socket file descriptor */
   struct thread *t_pim_sock_read;   /* thread for reading PIM socket */
diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h
index 656147f..95e60bf 100644
--- a/pimd/pim_igmp.h
+++ b/pimd/pim_igmp.h
@@ -55,13 +55,16 @@
 #define IGMP_V3_GROUP_RECORD_SOURCE_OFFSET     (8)
 
 /* RFC 3376: 8.1. Robustness Variable - Default: 2 */
-#define IGMP_DEFAULT_ROBUSTNESS_VARIABLE  (2)
+#define IGMP_DEFAULT_ROBUSTNESS_VARIABLE           (2)
 
 /* RFC 3376: 8.2. Query Interval - Default: 125 seconds */
-#define IGMP_GENERAL_QUERY_INTERVAL       (125)
+#define IGMP_GENERAL_QUERY_INTERVAL                (125)
 
 /* RFC 3376: 8.3. Query Response Interval - Default: 100 deciseconds */
-#define IGMP_QUERY_MAX_RESPONSE_TIME_DSEC (100)
+#define IGMP_QUERY_MAX_RESPONSE_TIME_DSEC          (100)
+
+/* RFC 3376: 8.8. Last Member Query Interval - Default: 10 deciseconds */
+#define IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC (10)
 
 struct igmp_join {
   struct in_addr group_addr;
diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c
index 3ff04c9..3d3ee7a 100644
--- a/pimd/pim_igmpv3.c
+++ b/pimd/pim_igmpv3.c
@@ -1006,7 +1006,7 @@
   pim_ifp = igmp->interface->info;
 
   lmqc      = igmp->querier_robustness_variable;
-  lmqi_msec = 100 * pim_ifp->igmp_query_max_response_time_dsec;
+  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
   lmqt_msec = lmqc * lmqi_msec;
 
   /*
@@ -1042,7 +1042,7 @@
 				 0 /* num_sources_tosend */,
 				 group->group_addr /* dst_addr */,
 				 group->group_addr /* group_addr */,
-				 pim_ifp->igmp_query_max_response_time_dsec,
+				 pim_ifp->igmp_specific_query_max_response_time_dsec,
 				 s_flag,
 				 igmp->querier_robustness_variable,
 				 igmp->querier_query_interval);
@@ -1090,7 +1090,7 @@
   pim_ifp = igmp->interface->info;
 
   lmqc      = igmp->querier_robustness_variable;
-  lmqi_msec = 100 * pim_ifp->igmp_query_max_response_time_dsec;
+  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
   lmqt_msec = lmqc * lmqi_msec;
 
   /* Scan all group sources */
@@ -1163,7 +1163,7 @@
 				       num_sources_tosend1,
 				       group->group_addr,
 				       group->group_addr,
-				       pim_ifp->igmp_query_max_response_time_dsec,
+				       pim_ifp->igmp_specific_query_max_response_time_dsec,
 				       1 /* s_flag */,
 				       igmp->querier_robustness_variable,
 				       igmp->querier_query_interval);
@@ -1205,7 +1205,7 @@
 				     num_sources_tosend2,
 				     group->group_addr,
 				     group->group_addr,
-				     pim_ifp->igmp_query_max_response_time_dsec,
+				     pim_ifp->igmp_specific_query_max_response_time_dsec,
 				     0 /* s_flag */,
 				     igmp->querier_robustness_variable,
 				     igmp->querier_query_interval);
@@ -1290,7 +1290,7 @@
   igmp = group->group_igmp_sock;
   pim_ifp = igmp->interface->info;
 
-  lmqi_msec = 100 * pim_ifp->igmp_query_max_response_time_dsec;
+  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
 
   if (PIM_DEBUG_IGMP_TRACE) {
     char group_str[100];
@@ -1359,7 +1359,7 @@
   pim_ifp = igmp->interface->info;
 
   lmqc      = igmp->querier_robustness_variable;
-  lmqi_msec = 100 * pim_ifp->igmp_query_max_response_time_dsec;
+  lmqi_msec = 100 * pim_ifp->igmp_specific_query_max_response_time_dsec;
   lmqt_msec = lmqc * lmqi_msec;
 
   /*
@@ -1519,7 +1519,7 @@
   pim_ifp = ifp->info;
   ifname  = ifp->name;
 
-  lmqi_dsec = pim_ifp->igmp_query_max_response_time_dsec;
+  lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec;
   lmqc      = igmp->querier_robustness_variable;
   lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */
 
@@ -1554,7 +1554,7 @@
   pim_ifp = ifp->info;
   ifname  = ifp->name;
 
-  lmqi_dsec = pim_ifp->igmp_query_max_response_time_dsec;
+  lmqi_dsec = pim_ifp->igmp_specific_query_max_response_time_dsec;
   lmqc      = igmp->querier_robustness_variable;
   lmqt_msec = PIM_IGMP_LMQT_MSEC(lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */
 
diff --git a/pimd/pim_join.c b/pimd/pim_join.c
index ce4ec4e..6b46759 100644
--- a/pimd/pim_join.c
+++ b/pimd/pim_join.c
@@ -239,6 +239,19 @@
       if (addr_offset < 1) {
 	return -7;
       }
+
+	  /* 
+	    RFC 4601: 4.9.1  Encoded Source and Group Address Formats
+
+		Encoded-Source Address
+		(...)
+	    The mask length MUST be equal to the mask length in bits for the
+        given Address Family and Encoding Type (32 for IPv4 native and
+        128 for IPv6 native).  A router SHOULD ignore any messages
+        received with any other mask length.
+	  */
+	  if (msg_source_addr.prefixlen!=32) return;
+
       buf += addr_offset;
 
       recv_join(ifp, neigh, msg_holdtime,
@@ -257,6 +270,19 @@
       if (addr_offset < 1) {
 	return -8;
       }
+
+	  /* 
+	    RFC 4601: 4.9.1  Encoded Source and Group Address Formats
+
+		Encoded-Source Address
+		(...)
+	    The mask length MUST be equal to the mask length in bits for the
+        given Address Family and Encoding Type (32 for IPv4 native and
+        128 for IPv6 native).  A router SHOULD ignore any messages
+        received with any other mask length.
+	  */
+	  if (msg_source_addr.prefixlen!=32) return;
+
       buf += addr_offset;
 
       recv_prune(ifp, neigh, msg_holdtime,
diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c
index 76f78f8..1105eac 100644
--- a/pimd/pim_msg.c
+++ b/pimd/pim_msg.c
@@ -98,7 +98,7 @@
 
   buf[0] = PIM_MSG_ADDRESS_FAMILY_IPV4; /* addr family */
   buf[1] = '\0';    /* native encoding */
-  buf[2] = '\0';    /* reserved */
+  buf[2] = 4;       /* reserved = 0 | S bit = 1 | W bit = 0 | R bit = 0 */
   buf[3] = 32;      /* mask len */
   *(struct in_addr *)(buf + 4) = addr;
 
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index 67aa9d0..b4112ed 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -46,6 +46,10 @@
 
   pim_ifp->pim_dr_addr = pim_ifp->primary_address;
 
+  zlog_info("%s on interface %s",
+	      __PRETTY_FUNCTION__,
+	      ifp->name);
+
   for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
     if (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) {
       pim_ifp->pim_dr_addr = neigh->source_addr;
@@ -66,7 +70,15 @@
   pim_ifp->pim_dr_addr = pim_ifp->primary_address;
   dr_pri = pim_ifp->pim_dr_priority;
 
+  zlog_info("%s: dr pri %u on interface %s",
+	      __PRETTY_FUNCTION__,
+	      dr_pri, ifp->name);
+
+
   for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
+	zlog_info("%s: neigh pri %u addr %x if dr addr %x",
+	      __PRETTY_FUNCTION__,
+	      neigh->dr_priority, ntohl(neigh->source_addr.s_addr) , ntohl(pim_ifp->pim_dr_addr.s_addr) );
     if (
 	(neigh->dr_priority > dr_pri) ||
 	(
@@ -91,6 +103,8 @@
 {
   struct pim_interface *pim_ifp = ifp->info;
   struct in_addr old_dr_addr;
+  char dr_old_str[100];
+  char dr_new_str[100];
 
   pim_ifp->pim_dr_election_last = pim_time_monotonic_sec(); /* timestamp */
   ++pim_ifp->pim_dr_election_count;
@@ -104,16 +118,22 @@
     dr_election_by_pri(ifp);
   }
 
-  /* DR changed ? */
-  if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {
-    char dr_old_str[100];
-    char dr_new_str[100];
-    pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str));
-    pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str));
-    zlog_info("%s: DR was %s now is %s on interface %s",
+  pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str));
+  pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str));
+  zlog_info("%s: DR was %s now is %s on interface %s",
 	      __PRETTY_FUNCTION__,
 	      dr_old_str, dr_new_str, ifp->name);
 
+  /* DR changed ? */
+  if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {
+    /* char dr_old_str[100]; */
+    /* char dr_new_str[100]; */
+    /* pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str)); */
+    /* pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str)); */
+    /* zlog_info("%s: DR was %s now is %s on interface %s", */
+	      /* __PRETTY_FUNCTION__, */
+	      /* dr_old_str, dr_new_str, ifp->name); */
+
     pim_if_update_join_desired(pim_ifp);
     pim_if_update_could_assert(ifp);
     pim_if_update_assert_tracking_desired(ifp);
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index dd78b90..9b6dc35 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -674,7 +674,7 @@
 
   THREAD_TIMER_MSEC_ON(master, pim_ifp->t_pim_hello_timer,
 		       on_pim_hello_send,
-		       ifp, triggered_hello_delay_msec);
+		       ifp, random_msec);
 }
 
 int pim_sock_add(struct interface *ifp)