In addition to IP broadcast and IP multicast for DTM node discovery, add support
for IP unicast to a list of peer IP addresses. The list of IP addresses is read
when DTM starts, either from a file or using a DNS query.
---
 00-README.conf                    |  24 +-
 src/dtm/dtmnd/Multicast.cc        | 594 ++++++++++++++++++++++++++++++--------
 src/dtm/dtmnd/Multicast.h         |  58 +++-
 src/dtm/dtmnd/dtm_node.cc         |   5 +
 src/dtm/dtmnd/dtm_node_sockets.cc |  44 +--
 src/dtm/dtmnd/dtmd.conf           |  35 ++-
 6 files changed, 608 insertions(+), 152 deletions(-)

diff --git a/00-README.conf b/00-README.conf
index b67da8ee7..8a2d6a146 100644
--- a/00-README.conf
+++ b/00-README.conf
@@ -76,12 +76,28 @@ address is presented.
 
 *******************************************************************************
 dtmd.conf
- 
-This file contains MDS/TCP configuration parameters.
-This file has to be edited only when you chose TCP as the mode of transport.
- 
+
+This file contains MDS/TCP configuration parameters. This file has to be edited
+only when you chose TCP as the mode of transport.
+
 The variable DTM_NODE_IP should be set to IP address of that local node
 
+To use IP multicast or unicast instead of broadcast, the variable 
DTM_MCAST_ADDR
+should be set to an IPv4/IPv6 multicast group address, or source of peer IP
+addresses for unicast
+
+* To use multicast, specify an IPv4 or IPv6 multicast group address
+* To use unicast, the string should start with "file:" followed by the path 
name
+  of a file containing a list of IP addresses (one per line), or start with
+  "dns:" followed by a DNS domain name, respectively.
+
+Examples:
+
+DTM_MCAST_ADDR=224.0.0.1
+DTM_MCAST_ADDR=ff02::1
+DTM_MCAST_ADDR=file:/var/lib/peer_ip_addresses.txt
+DTM_MCAST_ADDR=dns:peers.opensaf.org
+
 *******************************************************************************
 nid.conf
 
diff --git a/src/dtm/dtmnd/Multicast.cc b/src/dtm/dtmnd/Multicast.cc
index 922124a9c..1c674b239 100644
--- a/src/dtm/dtmnd/Multicast.cc
+++ b/src/dtm/dtmnd/Multicast.cc
@@ -26,7 +26,9 @@
 #include <cerrno>
 #include <cstdio>
 #include <cstring>
+#include <fstream>
 #include "base/logtrace.h"
+#include "base/osaf_utility.h"
 
 Multicast::Multicast(uint16_t cluster_id, uint32_t node_id,
                      in_port_t stream_port, in_port_t dgram_port,
@@ -45,45 +47,222 @@ Multicast::Multicast(uint16_t cluster_id, uint32_t node_id,
       multicast_address_{multicast_address},
       ifname_{ifname},
       scope_link_{scope_link},
-      dest_addr_size_{},
+      protocol_{GetProtocol(multicast_address)},
       dgram_sock_sndr{-1},
-      dgram_sock_rcvr{-1},
-      dest_addr_{} {
-  if (!multicast_address.empty()) {
-    /*
-       0
-       restricted to the same host
-       1
-       restricted to the same subnet
-       32
-       restricted to the same site
-       64
-       restricted to the same region
-       128
-       restricted to the same continent
-       255
-       unrestricted
-     */
-    uint32_t rc = dtm_dgram_mcast_sender(64); /*TODO */
-    if (rc == NCSCC_RC_SUCCESS) {
-      rc = dtm_dgram_mcast_listener();
-      if (rc != NCSCC_RC_SUCCESS) {
-        LOG_ER("DTM:Set up the initial mcast  receiver socket failed");
+      dgram_sock_rcvr{-1} {
+  switch (protocol_) {
+    case kBroadcast: {
+      uint32_t rc = dtm_dgram_bcast_sender();
+      if (rc == NCSCC_RC_SUCCESS) {
+        rc = dtm_dgram_bcast_listener();
+        if (rc != NCSCC_RC_SUCCESS) {
+          LOG_ER("DTM:Set up the initial bcast  receiver socket failed");
+        }
+      } else {
+        LOG_ER("DTM:Set up the initial bcast  sender socket failed rc: %d", 
rc);
+      }
+      break;
+    }
+    case kMulticast: {
+      uint32_t rc = dtm_dgram_mcast_sender(64); /*TODO */
+      if (rc == NCSCC_RC_SUCCESS) {
+        rc = dtm_dgram_mcast_listener();
+        if (rc != NCSCC_RC_SUCCESS) {
+          LOG_ER("DTM:Set up the initial mcast  receiver socket failed");
+        }
+      } else {
+        LOG_ER("DTM:Set up the initial mcast sender socket failed rc: %d", rc);
+      }
+      break;
+    }
+    case kFileUnicast: {
+      GetPeersFromFile(multicast_address.substr(5));
+      bool result = InitializeUnicastSender();
+      if (result) {
+        result = InitializeUnicastReceiver();
+        if (!result) {
+          LOG_ER("DTM:Set up the initial ucast  receiver socket failed");
+        }
+      } else {
+        LOG_ER("DTM:Set up the initial ucast  sender socket failed");
+      }
+      break;
+    }
+    case kDnsUnicast: {
+      GetPeersFromDns(multicast_address.substr(4));
+      bool result = InitializeUnicastSender();
+      if (result) {
+        result = InitializeUnicastReceiver();
+        if (!result) {
+          LOG_ER("DTM:Set up the initial ucast  receiver socket failed");
+        }
+      } else {
+        LOG_ER("DTM:Set up the initial ucast  sender socket failed");
+      }
+      break;
+    }
+  }
+
+  struct in_addr addr_ipv4;
+  struct in6_addr addr_ipv6;
+  int rc = -1;
+  if (address_family_ == AF_INET) {
+    rc = inet_pton(AF_INET, stream_address_.c_str(), &addr_ipv4);
+  } else if (address_family_ == AF_INET6) {
+    rc = inet_pton(AF_INET6, stream_address_.c_str(), &addr_ipv6);
+  }
+  unsigned ifindex = if_nametoindex(ifname_.c_str());
+  if (rc == 1) {
+    auto start = peers_.begin();
+    auto end = peers_.end();
+    while (start != end) {
+      bool found = false;
+      if (address_family_ == AF_INET &&
+          start->address()->sa_family == AF_INET) {
+        const struct sockaddr_in *peer =
+            reinterpret_cast<const struct sockaddr_in *>(start->address());
+        if (addr_ipv4.s_addr == peer->sin_addr.s_addr) found = true;
+      } else if (address_family_ == AF_INET6 &&
+                 start->address()->sa_family == AF_INET6) {
+        const struct sockaddr_in6 *peer =
+            reinterpret_cast<const struct sockaddr_in6 *>(start->address());
+        if (IN6_ARE_ADDR_EQUAL(&addr_ipv6, &peer->sin6_addr) &&
+            (!scope_link_ || ifindex == peer->sin6_scope_id))
+          found = true;
+      }
+      auto iter = start;
+      ++start;
+      if (found) peers_.erase(iter);
+    }
+  }
+  if (protocol_ == kFileUnicast || protocol_ == kDnsUnicast) {
+    LOG_NO("Number of unicast peers: %zu", static_cast<size_t>(peers_.size()));
+  }
+}
+
+Multicast::Protocol Multicast::GetProtocol(
+    const std::string &multicast_address) {
+  TRACE_ENTER();
+  Multicast::Protocol p;
+  if (multicast_address.empty()) {
+    p = kBroadcast;
+  } else if (multicast_address.compare(0, 5, "file:") == 0) {
+    p = kFileUnicast;
+  } else if (multicast_address.compare(0, 4, "dns:") == 0) {
+    p = kDnsUnicast;
+  } else {
+    p = kMulticast;
+  }
+  TRACE_LEAVE2("Protocol = %d", static_cast<int>(p));
+  return p;
+}
+
+bool Multicast::GetPeersFromFile(const std::string &path_name) {
+  std::ifstream str;
+  try {
+    str.open(path_name);
+    while (str.good()) {
+      std::string address;
+      std::getline(str, address);
+      if (!address.empty()) {
+        struct sockaddr_storage addr;
+        socklen_t len =
+            ParseAddress(address_family_, address, dgram_port_, &addr);
+        if (len != 0) {
+          if (peers_.emplace(reinterpret_cast<sockaddr *>(&addr), len).second) 
{
+            LOG_IN("Added IP '%s' from '%s'", address.c_str(),
+                   path_name.c_str());
+          } else {
+            LOG_WA("Duplicate IP '%s' in '%s'", address.c_str(),
+                   path_name.c_str());
+          }
+        }
       }
-    } else {
-      LOG_ER("DTM:Set up the initial mcast sender socket failed rc: %d", rc);
     }
+  } catch (std::ifstream::failure) {
+    LOG_ER("Caught std::ifstream::failure when reading file '%s', peers=%zu",
+           path_name.c_str(), static_cast<size_t>(peers_.size()));
+    peers_.clear();
+  }
+  if (peers_.empty()) {
+    LOG_ER("Failed to read peers from file '%s': fail=%d, peers=%zu",
+           path_name.c_str(), str.fail() ? 1 : 0,
+           static_cast<size_t>(peers_.size()));
+  }
+  return !peers_.empty();
+}
+
+socklen_t Multicast::ParseAddress(sa_family_t address_family,
+                                  const std::string &address, in_port_t port,
+                                  struct sockaddr_storage *addr) {
+  char local_port_str[8];
+  snprintf(local_port_str, sizeof(local_port_str), "%" PRIu16, port);
+
+  struct addrinfo addr_criteria {};
+  addr_criteria.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+  addr_criteria.ai_family = address_family;
+  addr_criteria.ai_socktype = SOCK_DGRAM;
+  addr_criteria.ai_protocol = IPPROTO_UDP;
+
+  struct addrinfo *res;
+  int rv = getaddrinfo(address.c_str(), local_port_str, &addr_criteria, &res);
+  socklen_t addrlen;
+  if (rv == 0) {
+    addrlen = res->ai_addrlen;
+    memcpy(addr, res->ai_addr, addrlen);
+    freeaddrinfo(res);
   } else {
-    uint32_t rc = dtm_dgram_bcast_sender();
-    if (rc == NCSCC_RC_SUCCESS) {
-      rc = dtm_dgram_bcast_listener();
-      if (rc != NCSCC_RC_SUCCESS) {
-        LOG_ER("DTM:Set up the initial bcast  receiver socket failed");
+    LOG_ER("getaddrinfo('%s', %s) failed: %s", address.c_str(), local_port_str,
+           gai_strerror(rv));
+    addrlen = 0;
+  }
+  return addrlen;
+}
+
+bool Multicast::GetPeersFromDns(const std::string &domain_name) {
+  char local_port_str[8];
+  snprintf(local_port_str, sizeof(local_port_str), "%" PRIu16, dgram_port_);
+
+  struct addrinfo addr_criteria {};
+  addr_criteria.ai_flags = AI_IDN | AI_NUMERICSERV;
+  addr_criteria.ai_family = address_family_;
+  addr_criteria.ai_socktype = SOCK_DGRAM;
+  addr_criteria.ai_protocol = IPPROTO_UDP;
+
+  struct addrinfo *res;
+  int rv =
+      getaddrinfo(domain_name.c_str(), local_port_str, &addr_criteria, &res);
+  if (rv == 0) {
+    for (struct addrinfo *p = res; p != nullptr; p = p->ai_next) {
+      char buf[INET6_ADDRSTRLEN];
+      const char *result = nullptr;
+      if (p->ai_family == AF_INET) {
+        struct sockaddr_in *addr =
+            reinterpret_cast<struct sockaddr_in *>(p->ai_addr);
+        result = inet_ntop(p->ai_family, &addr->sin_addr, buf, sizeof(buf));
+      } else if (p->ai_family == AF_INET6) {
+        struct sockaddr_in6 *addr =
+            reinterpret_cast<struct sockaddr_in6 *>(p->ai_addr);
+        result = inet_ntop(p->ai_family, &addr->sin6_addr, buf, sizeof(buf));
       }
-    } else {
-      LOG_ER("DTM:Set up the initial bcast  sender socket failed rc: %d", rc);
+      if (peers_.emplace(p->ai_addr, p->ai_addrlen).second) {
+        if (result != nullptr)
+          LOG_IN("Added IP '%s' from '%s'", result, domain_name.c_str());
+      } else {
+        if (result != nullptr)
+          LOG_WA("Duplicate IP '%s' from '%s'", result, domain_name.c_str());
+      }
+    }
+    freeaddrinfo(res);
+    if (peers_.empty()) {
+      LOG_ER("Failed to get any peers from domain name '%s'",
+             domain_name.c_str());
     }
+  } else {
+    LOG_ER("getaddrinfo('%s', %s) failed: %s", domain_name.c_str(),
+           local_port_str, gai_strerror(rv));
   }
+  return !peers_.empty();
 }
 
 Multicast::~Multicast() {
@@ -91,6 +270,162 @@ Multicast::~Multicast() {
   if (dgram_sock_rcvr >= 0) close(dgram_sock_rcvr);
 }
 
+bool Multicast::InitializeUnicastSender() {
+  TRACE_ENTER();
+
+  dgram_sock_sndr = socket(
+      address_family_, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_UDP);
+  if (dgram_sock_sndr < 0) {
+    LOG_ER("socket() failed: %s", strerror(errno));
+    TRACE_LEAVE();
+    return false;
+  }
+
+  if (address_family_ == AF_INET6) {
+    int v6only = 1;
+    if (setsockopt(dgram_sock_sndr, IPPROTO_IPV6, IPV6_V6ONLY, &v6only,
+                   sizeof(v6only)) < 0)
+      LOG_ER("setsockopt(IPV6_V6ONLY) failed: %s", strerror(errno));
+  }
+  TRACE_LEAVE();
+  return true;
+}
+
+bool Multicast::InitializeUnicastReceiver() {
+  struct addrinfo *addr_list = nullptr, *p;  // Criteria for address
+  int rv;
+  char ucast_addr_eth[INET6_ADDRSTRLEN + IFNAMSIZ];
+  TRACE_ENTER();
+
+  TRACE("DTM :dgram_port_rcvr : %" PRIu16, dgram_port_);
+  char local_port_str[8];
+  snprintf(local_port_str, sizeof(local_port_str), "%" PRIu16, dgram_port_);
+
+  dgram_sock_rcvr = -1;
+  struct addrinfo addr_criteria {};
+  addr_criteria.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV;
+  addr_criteria.ai_family = AF_UNSPEC;
+  addr_criteria.ai_socktype = SOCK_DGRAM;
+  addr_criteria.ai_protocol = IPPROTO_UDP;
+
+  TRACE("DTM :ip_addr : %s local_port_str :%s", stream_address_.c_str(),
+        local_port_str);
+  if (address_family_ == AF_INET) {
+    if ((rv = getaddrinfo(stream_address_.c_str(), local_port_str,
+                          &addr_criteria, &addr_list)) != 0) {
+      LOG_ER("DTM:Unable to getaddrinfo() for '%s': %s",
+             stream_address_.c_str(), gai_strerror(rv));
+      TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+      return NCSCC_RC_FAILURE;
+    }
+  } else if (address_family_ == AF_INET6) {
+    if (scope_link_) {
+      memset(ucast_addr_eth, 0, (INET6_ADDRSTRLEN + IFNAMSIZ));
+      sprintf(ucast_addr_eth, "%s%%%s", stream_address_.c_str(),
+              ifname_.c_str());
+      if ((rv = getaddrinfo(ucast_addr_eth, local_port_str, &addr_criteria,
+                            &addr_list)) != 0) {
+        LOG_ER("DTM:Unable to getaddrinfo() for '%s': %s", ucast_addr_eth,
+               gai_strerror(rv));
+        TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+        return NCSCC_RC_FAILURE;
+      }
+    } else {
+      if ((rv = getaddrinfo(stream_address_.c_str(), local_port_str,
+                            &addr_criteria, &addr_list)) != 0) {
+        LOG_ER("DTM:Unable to getaddrinfo() for '%s': %s",
+               stream_address_.c_str(), gai_strerror(rv));
+        TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+        return NCSCC_RC_FAILURE;
+      }
+    }
+  }
+
+  if (addr_list == nullptr) {
+    LOG_ER("DTM:Unable to get addr_list ");
+    TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+    return NCSCC_RC_FAILURE;
+  }
+
+  /* results and bind to the first we can */
+  p = addr_list;
+  bool bound = false;
+  for (; p; p = p->ai_next) {
+    TRACE("DTM :family : %d, socktype : %d, protocol :%d", p->ai_family,
+          p->ai_socktype, p->ai_protocol);
+    if (address_family_ != p->ai_family) {
+      continue;
+    }
+
+    if (p->ai_family == AF_INET) {
+      void *addr;
+      char ipstr[INET6_ADDRSTRLEN];
+      struct sockaddr_in *ipv4 =
+          reinterpret_cast<struct sockaddr_in *>(p->ai_addr);
+      addr = &(ipv4->sin_addr);
+      inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
+      if (strcasecmp(ipstr, stream_address_.c_str()) != 0) {
+        continue;
+      } else
+        TRACE("DTM: DGRAM Socket bound to  = %s\n", ipstr);
+    } else if (p->ai_family == AF_INET6) {
+      void *addr;
+      char ipstr[INET6_ADDRSTRLEN];
+      struct sockaddr_in6 *ipv6 =
+          reinterpret_cast<struct sockaddr_in6 *>(p->ai_addr);
+      addr = &(ipv6->sin6_addr);
+      inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
+      if (strcasecmp(ipstr, stream_address_.c_str()) != 0) {
+        continue;
+      } else
+        TRACE("DTM: DGRAM Socket bound to  = %s\n", ipstr);
+    }
+    if ((dgram_sock_rcvr =
+             socket(p->ai_family, p->ai_socktype | SOCK_NONBLOCK | 
SOCK_CLOEXEC,
+                    p->ai_protocol)) == -1) {
+      LOG_ER("DTM:Socket creation failed (socket()) err :%s", strerror(errno));
+      TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+      continue;
+    }
+
+    int smode = 1;
+    if ((setsockopt(dgram_sock_rcvr, SOL_SOCKET, SO_REUSEADDR, &smode,
+                    sizeof(smode)) == -1)) {
+      LOG_ER("DTM : Error setsockpot: err :%s", strerror(errno));
+      freeaddrinfo(addr_list);
+      TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+      return NCSCC_RC_FAILURE;
+    }
+    if (p->ai_family == AF_INET6) {
+      int v6only = 1;
+      if (setsockopt(dgram_sock_rcvr, IPPROTO_IPV6, IPV6_V6ONLY, &v6only,
+                     sizeof(v6only)) < 0)
+        LOG_ER("setsockopt(IPV6_V6ONLY) failed: %s", strerror(errno));
+    }
+    if (bind(dgram_sock_rcvr, p->ai_addr, p->ai_addrlen) == -1) {
+      LOG_ER("DTM:Socket bind failed  err :%s", strerror(errno));
+      close(dgram_sock_rcvr);
+      TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+      perror("listener: bind");
+      freeaddrinfo(addr_list);
+      return NCSCC_RC_FAILURE;
+    } else {
+      bound = true;
+      break;
+    }
+  }
+
+  /* Free address structure(s) allocated by getaddrinfo() */
+  freeaddrinfo(addr_list);
+  if (bound != true) {
+    TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+    return NCSCC_RC_FAILURE;
+  } else {
+    TRACE_LEAVE2("rc :%d", NCSCC_RC_SUCCESS);
+    return NCSCC_RC_SUCCESS;
+  }
+}
+
 /**
  * Function for sending the bcast
  *
@@ -104,13 +439,14 @@ uint32_t Multicast::dtm_dgram_bcast_sender() {
   TRACE_ENTER();
 
   dgram_sock_sndr = -1;
-  dest_addr_size_ = 0;
-  memset(&dest_addr_, 0, sizeof(dest_addr_));
+  socklen_t dest_addr_size = 0;
+  struct sockaddr_storage dest_addr;
 
   if (address_family_ == AF_INET) {
     /* Holder for bcast_dest_address address */
     struct sockaddr_in *bcast_sender_addr_in =
-        reinterpret_cast<struct sockaddr_in *>(&dest_addr_);
+        reinterpret_cast<struct sockaddr_in *>(&dest_addr);
+    memset(bcast_sender_addr_in, 0, sizeof(struct sockaddr_in));
     bcast_sender_addr_in->sin_family = AF_INET;
     bcast_sender_addr_in->sin_port = htons(dgram_port_);
     TRACE("DTM:  IP address : %s  Bcast address : %s sa_family : %d ",
@@ -125,11 +461,12 @@ uint32_t Multicast::dtm_dgram_bcast_sender() {
 
     memset(bcast_sender_addr_in->sin_zero, '\0',
            sizeof(bcast_sender_addr_in->sin_zero));
-    dest_addr_size_ = sizeof(struct sockaddr_in);
+    dest_addr_size = sizeof(struct sockaddr_in);
   } else if (address_family_ == AF_INET6) {
     /* Holder for bcast_dest_address address */
     struct sockaddr_in6 *bcast_sender_addr_in6 =
-        reinterpret_cast<struct sockaddr_in6 *>(&dest_addr_);
+        reinterpret_cast<struct sockaddr_in6 *>(&dest_addr);
+    memset(bcast_sender_addr_in6, 0, sizeof(struct sockaddr_in6));
     bcast_sender_addr_in6->sin6_family = AF_INET6;
     bcast_sender_addr_in6->sin6_port = htons(dgram_port_);
     bcast_sender_addr_in6->sin6_flowinfo = 0;
@@ -138,16 +475,22 @@ uint32_t Multicast::dtm_dgram_bcast_sender() {
           stream_address_.c_str(), dgram_address_.c_str(), address_family_);
     inet_pton(AF_INET6, dgram_address_.c_str(),
               &bcast_sender_addr_in6->sin6_addr);
-    dest_addr_size_ = sizeof(struct sockaddr_in6);
+    dest_addr_size = sizeof(struct sockaddr_in6);
   } else {
     LOG_ER("DTM : dgram_enable_bcast failed");
     TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
     return NCSCC_RC_FAILURE;
   }
+  if (peers_.emplace(reinterpret_cast<sockaddr *>(&dest_addr), dest_addr_size)
+          .second) {
+    LOG_IN("Added broadcast IP '%s'", dgram_address_.c_str());
+  } else {
+    osaf_abort(peers_.size());
+  }
 
   /* Create socket for sending/receiving datagrams */
   dgram_sock_sndr =
-      socket(dest_addr_.ss_family, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
+      socket(dest_addr.ss_family, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
              IPPROTO_UDP);
   if (dgram_sock_sndr == -1) {
     LOG_ER("DTM :socket create  failederr :%s", strerror(errno));
@@ -165,8 +508,12 @@ uint32_t Multicast::dtm_dgram_bcast_sender() {
   }
 
   if (address_family_ == AF_INET6) {
+    int v6only = 1;
+    if (setsockopt(dgram_sock_sndr, IPPROTO_IPV6, IPV6_V6ONLY, &v6only,
+                   sizeof(v6only)) < 0)
+      LOG_ER("setsockopt(IPV6_V6ONLY) failed: %s", strerror(errno));
     struct sockaddr_in6 *bcast_sender_addr_in6 =
-        reinterpret_cast<struct sockaddr_in6 *>(&dest_addr_);
+        reinterpret_cast<struct sockaddr_in6 *>(&dest_addr);
     int yes = 1;
     if (setsockopt(dgram_sock_sndr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &yes,
                    sizeof(yes)) < 0) {
@@ -183,8 +530,7 @@ uint32_t Multicast::dtm_dgram_bcast_sender() {
       return NCSCC_RC_FAILURE;
     }
 
-    unsigned int ifindex;
-    ifindex = if_nametoindex(ifname_.c_str());
+    unsigned ifindex = if_nametoindex(ifname_.c_str());
     if (setsockopt(dgram_sock_sndr, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex,
                    sizeof(ifindex)) < 0) {
       LOG_ER("DTM :setsockopt(IPV6_MULTICAST_IF) failed err :%s ifname :%d",
@@ -239,6 +585,12 @@ uint32_t Multicast::dgram_enable_bcast(int sock_desc) {
  * Function to send the mcast message
  *
  * @param dtms_cb mcast_ttl
+ *  0 restricted to the same host
+ *  1 restricted to the same subnet
+ *  32 restricted to the same site
+ *  64 restricted to the same region
+ *  128 restricted to the same continent
+ *  255 unrestricted
  *
  * @return NCSCC_RC_SUCCESS
  * @return NCSCC_RC_FAILURE
@@ -246,43 +598,39 @@ uint32_t Multicast::dgram_enable_bcast(int sock_desc) {
  */
 uint32_t Multicast::dtm_dgram_mcast_sender(int mcast_ttl) {
   /* Construct the serv address structure */
-  struct addrinfo addr_criteria;  // Criteria for address match
-  char local_port_str[INET6_ADDRSTRLEN];
   int rv;
   TRACE_ENTER();
 
   dgram_sock_sndr = -1;
 
-  TRACE("DTM :dgram_port_rcvr :%d", dgram_port_);
-  snprintf(local_port_str, sizeof(local_port_str), "%d", (dgram_port_));
+  TRACE("DTM :dgram_port_rcvr : %" PRIu16, dgram_port_);
+  char local_port_str[8];
+  snprintf(local_port_str, sizeof(local_port_str), "%" PRIu16, dgram_port_);
 
-  memset(&addr_criteria, 0, sizeof(addr_criteria)); /* Zero out structure */
-  addr_criteria.ai_family = AF_UNSPEC;              /* v4 or v6 is OK */
-  addr_criteria.ai_socktype = SOCK_DGRAM;           /* Only datagram sockets */
-  addr_criteria.ai_protocol = IPPROTO_UDP;          /* Only UDP please */
-  addr_criteria.ai_flags |= AI_NUMERICHOST; /* Don't try to resolve address */
+  struct addrinfo addr_criteria {};
+  addr_criteria.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+  addr_criteria.ai_family = AF_UNSPEC;
+  addr_criteria.ai_socktype = SOCK_DGRAM;
+  addr_criteria.ai_protocol = IPPROTO_UDP;
 
   struct addrinfo *mcast_sender_addr;
+  char mcast_addr_eth[INET6_ADDRSTRLEN + IFNAMSIZ];
+  memset(mcast_addr_eth, 0, (INET6_ADDRSTRLEN + IFNAMSIZ));
   /* For link-local address, need to set sin6_scope_id to match the
      device index of the network device on it has to connecct */
   if (scope_link_) {
-    char mcast_addr_eth[INET6_ADDRSTRLEN + IFNAMSIZ];
-    memset(mcast_addr_eth, 0, (INET6_ADDRSTRLEN + IFNAMSIZ));
-    sprintf(mcast_addr_eth, "%s%%%s", multicast_address_.c_str(),
-            ifname_.c_str());
-    rv = getaddrinfo(mcast_addr_eth, local_port_str, &addr_criteria,
-                     &mcast_sender_addr);
-    TRACE("DTM :mcast_addr : %s local_port_str :%s", mcast_addr_eth,
-          local_port_str);
+    snprintf(mcast_addr_eth, sizeof(mcast_addr_eth), "%s%%%s",
+             multicast_address_.c_str(), ifname_.c_str());
   } else {
-    rv = getaddrinfo(multicast_address_.c_str(), local_port_str, 
&addr_criteria,
-                     &mcast_sender_addr);
-    TRACE("DTM :mcast_addr : %s local_port_str :%s", 
multicast_address_.c_str(),
-          local_port_str);
+    snprintf(mcast_addr_eth, sizeof(mcast_addr_eth), "%s",
+             multicast_address_.c_str());
   }
+  rv = getaddrinfo(mcast_addr_eth, local_port_str, &addr_criteria,
+                   &mcast_sender_addr);
+  TRACE("DTM :mcast_addr : %s local_port_str :%s", mcast_addr_eth,
+        local_port_str);
   if (rv != 0) {
-    LOG_ER("DTM:Unable to getaddrinfo() rtn_val :%d err :%s", rv,
-           strerror(errno));
+    LOG_ER("DTM:Unable to getaddrinfo(): %s", gai_strerror(rv));
     TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
     return NCSCC_RC_FAILURE;
   }
@@ -319,12 +667,14 @@ uint32_t Multicast::dtm_dgram_mcast_sender(int mcast_ttl) 
{
     return NCSCC_RC_FAILURE;
   }
 
-  size_t addrlen = mcast_sender_addr->ai_addrlen;
-  if (addrlen > sizeof(dest_addr_)) {
-    LOG_ER("getaddrinfo() returned too large address: %zu", addrlen);
-    addrlen = sizeof(dest_addr_);
+  if (peers_
+          .emplace(reinterpret_cast<sockaddr *>(mcast_sender_addr->ai_addr),
+                   mcast_sender_addr->ai_addrlen)
+          .second) {
+    LOG_IN("Added broadcast IP '%s'", mcast_addr_eth);
+  } else {
+    osaf_abort(peers_.size());
   }
-  memcpy(&dest_addr_, mcast_sender_addr->ai_addr, addrlen);
 
   freeaddrinfo(mcast_sender_addr);
 
@@ -363,6 +713,10 @@ uint32_t Multicast::dgram_set_mcast_ttl(int mcast_ttl, int 
family) {
   /* Set TTL of mcast packet. Unfortunately this requires */
   /* address-family-specific code */
   if (family == AF_INET6) {  // v6-specific
+    int v6only = 1;
+    if (setsockopt(dgram_sock_sndr, IPPROTO_IPV6, IPV6_V6ONLY, &v6only,
+                   sizeof(v6only)) < 0)
+      LOG_ER("setsockopt(IPV6_V6ONLY) failed: %s", strerror(errno));
     /* The v6 mcast TTL socket option requires that the value be */
     /* passed in as an integer */
     if (setsockopt(dgram_sock_sndr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
@@ -372,8 +726,7 @@ uint32_t Multicast::dgram_set_mcast_ttl(int mcast_ttl, int 
family) {
       TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
       return NCSCC_RC_FAILURE;
     }
-    unsigned int ifindex;
-    ifindex = if_nametoindex(ifname_.c_str());
+    unsigned ifindex = if_nametoindex(ifname_.c_str());
     if (setsockopt(dgram_sock_sndr, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex,
                    sizeof(ifindex)) < 0) {
       LOG_ER("DTM :setsockopt(IPV6_MULTICAST_IF) failed err :%s ifname :%d",
@@ -404,15 +757,19 @@ bool Multicast::Send() {
   Message msg{cluster_id_,  node_id_,        !multicast_address_.empty(),
               stream_port_, address_family_, stream_address_};
   bool success = true;
-  ssize_t num_bytes =
-      sendto(dgram_sock_sndr, &msg, sizeof(msg), 0,
-             reinterpret_cast<struct sockaddr *>(&dest_addr_), 
dest_addr_size_);
-  if (num_bytes < 0) {
-    LOG_ER("sendto() failed: %s ", strerror(errno));
-    success = false;
-  } else if (static_cast<size_t>(num_bytes) != sizeof(msg)) {
-    LOG_ER("sendto() sent unexpected number of bytes %zd", num_bytes);
-    success = false;
+  for (const auto &addr : peers_) {
+    ssize_t num_bytes;
+    do {
+      num_bytes = sendto(dgram_sock_sndr, &msg, sizeof(msg), 0, addr.address(),
+                         addr.length());
+    } while (num_bytes < 0 && errno == EINTR);
+    if (num_bytes < 0) {
+      LOG_ER("sendto() failed: %s ", strerror(errno));
+      success = false;
+    } else if (static_cast<size_t>(num_bytes) != sizeof(msg)) {
+      LOG_ER("sendto() sent unexpected number of bytes %zd", num_bytes);
+      success = false;
+    }
   }
 
   TRACE_LEAVE2("success: %d", success ? 1 : 0);
@@ -515,22 +872,21 @@ uint32_t Multicast::dgram_join_mcast_group(
  */
 uint32_t Multicast::dtm_dgram_mcast_listener() {
   /* Construct the serv address structure */
-  struct addrinfo addr_criteria; /* Criteria for address match */
-  char local_port_str[INET6_ADDRSTRLEN];
   int rv;
   struct addrinfo *addr_list; /* Holder serv address */
   TRACE_ENTER();
 
-  TRACE("DTM :dgram_port_rcvr :%d", dgram_port_);
+  TRACE("DTM :dgram_port_rcvr : %" PRIu16, dgram_port_);
+  char local_port_str[8];
   snprintf(local_port_str, sizeof(local_port_str), "%" PRIu16, dgram_port_);
 
   dgram_sock_rcvr = -1;
 
-  memset(&addr_criteria, 0, sizeof(addr_criteria)); /* Zero out structure */
-  addr_criteria.ai_family = AF_UNSPEC;              /* v4 or v6 is OK */
-  addr_criteria.ai_socktype = SOCK_DGRAM;           /* Only datagram sockets */
-  addr_criteria.ai_protocol = IPPROTO_UDP;          /* Only UDP protocol */
-  addr_criteria.ai_flags |= AI_NUMERICHOST; /* Don't try to resolve address */
+  struct addrinfo addr_criteria {};
+  addr_criteria.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+  addr_criteria.ai_family = AF_UNSPEC;
+  addr_criteria.ai_socktype = SOCK_DGRAM;
+  addr_criteria.ai_protocol = IPPROTO_UDP;
 
   /* For link-local address, need to set sin6_scope_id to match the
      device index of the network device on it has to connecct */
@@ -550,8 +906,7 @@ uint32_t Multicast::dtm_dgram_mcast_listener() {
           local_port_str);
   }
   if (rv != 0) {
-    LOG_ER("DTM:Unable to getaddrinfo() rtn_val :%d err :%s", rv,
-           strerror(errno));
+    LOG_ER("DTM:Unable to getaddrinfo(): %s", gai_strerror(rv));
     TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
     return NCSCC_RC_FAILURE;
   }
@@ -583,6 +938,13 @@ uint32_t Multicast::dtm_dgram_mcast_listener() {
     return NCSCC_RC_FAILURE;
   }
 
+  if (address_family_ == AF_INET6) {
+    int v6only = 1;
+    if (setsockopt(dgram_sock_rcvr, IPPROTO_IPV6, IPV6_V6ONLY, &v6only,
+                   sizeof(v6only)) < 0)
+      LOG_ER("setsockopt(IPV6_V6ONLY) failed: %s", strerror(errno));
+  }
+
   if (bind(dgram_sock_rcvr, addr_list->ai_addr, addr_list->ai_addrlen) < 0) {
     LOG_ER("DTM : bind() failed err :%s ", strerror(errno));
     if (close(dgram_sock_rcvr) != 0 && errno != EINTR)
@@ -617,32 +979,29 @@ uint32_t Multicast::dtm_dgram_mcast_listener() {
  *
  */
 uint32_t Multicast::dtm_dgram_bcast_listener() {
-  struct addrinfo addr_criteria, *addr_list = nullptr,
-                                 *p;  // Criteria for address
-  char local_port_str[INET6_ADDRSTRLEN];
+  struct addrinfo *addr_list = nullptr, *p;  // Criteria for address
   int rv;
   char bcast_addr_eth[INET6_ADDRSTRLEN + IFNAMSIZ];
   TRACE_ENTER();
 
-  TRACE("DTM :dgram_port_rcvr :%d", dgram_port_);
-  snprintf(local_port_str, sizeof(local_port_str), "%d", (dgram_port_));
+  TRACE("DTM :dgram_port_rcvr : %" PRIu16, dgram_port_);
+  char local_port_str[8];
+  snprintf(local_port_str, sizeof(local_port_str), "%" PRIu16, dgram_port_);
 
   dgram_sock_rcvr = -1;
-  /*  Construct the server address structure */
-  memset(&addr_criteria, 0, sizeof(addr_criteria));  // Zero out structure
-  addr_criteria.ai_family = AF_UNSPEC;               // Any address family
-  addr_criteria.ai_flags = AI_PASSIVE;      // Accept on any address/port
-  addr_criteria.ai_socktype = SOCK_DGRAM;   // Only datagram socket
-  addr_criteria.ai_protocol = IPPROTO_UDP;  // Only UDP socket
-  addr_criteria.ai_flags |= AI_NUMERICHOST;
+  struct addrinfo addr_criteria {};
+  addr_criteria.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV;
+  addr_criteria.ai_family = AF_UNSPEC;
+  addr_criteria.ai_socktype = SOCK_DGRAM;
+  addr_criteria.ai_protocol = IPPROTO_UDP;
 
   TRACE("DTM :ip_addr : %s local_port_str :%s", stream_address_.c_str(),
         local_port_str);
   if (address_family_ == AF_INET) {
     if ((rv = getaddrinfo(dgram_address_.c_str(), local_port_str,
                           &addr_criteria, &addr_list)) != 0) {
-      LOG_ER("DTM:Unable to getaddrinfo() rtn_val :%d err :%s", rv,
-             strerror(errno));
+      LOG_ER("DTM:Unable to getaddrinfo() for '%s': %s", 
dgram_address_.c_str(),
+             gai_strerror(rv));
       TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
       return NCSCC_RC_FAILURE;
     }
@@ -653,16 +1012,16 @@ uint32_t Multicast::dtm_dgram_bcast_listener() {
               ifname_.c_str());
       if ((rv = getaddrinfo(bcast_addr_eth, local_port_str, &addr_criteria,
                             &addr_list)) != 0) {
-        LOG_ER("DTM:Unable to getaddrinfo() rtn_val :%d err :%s", rv,
-               strerror(errno));
+        LOG_ER("DTM:Unable to getaddrinfo() for '%s': %s", bcast_addr_eth,
+               gai_strerror(rv));
         TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
         return NCSCC_RC_FAILURE;
       }
     } else {
       if ((rv = getaddrinfo(dgram_address_.c_str(), local_port_str,
                             &addr_criteria, &addr_list)) != 0) {
-        LOG_ER("DTM:Unable to getaddrinfo() rtn_val :%d err :%s", rv,
-               strerror(errno));
+        LOG_ER("DTM:Unable to getaddrinfo() for '%s': %s",
+               dgram_address_.c_str(), gai_strerror(rv));
         TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
         return NCSCC_RC_FAILURE;
       }
@@ -677,8 +1036,7 @@ uint32_t Multicast::dtm_dgram_bcast_listener() {
 
   /* results and bind to the first we can */
   p = addr_list;
-  bool binded = false;
-  unsigned int ifindex;
+  bool bound = false;
 
   for (; p; p = p->ai_next) {
     TRACE("DTM :family : %d, socktype : %d, protocol :%d", p->ai_family,
@@ -697,7 +1055,7 @@ uint32_t Multicast::dtm_dgram_bcast_listener() {
       if (strcasecmp(ipstr, dgram_address_.c_str()) != 0) {
         continue;
       } else
-        TRACE("DTM: DGRAM Socket binded to  = %s\n", ipstr);
+        TRACE("DTM: DGRAM Socket bound to  = %s\n", ipstr);
     } else if (p->ai_family == AF_INET6) {
       void *addr;
       char ipstr[INET6_ADDRSTRLEN];
@@ -708,7 +1066,7 @@ uint32_t Multicast::dtm_dgram_bcast_listener() {
       if (strcasecmp(ipstr, dgram_address_.c_str()) != 0) {
         continue;
       } else
-        TRACE("DTM: DGRAM Socket binded to  = %s\n", ipstr);
+        TRACE("DTM: DGRAM Socket bound to  = %s\n", ipstr);
     }
     if ((dgram_sock_rcvr =
              socket(p->ai_family, p->ai_socktype | SOCK_NONBLOCK | 
SOCK_CLOEXEC,
@@ -727,9 +1085,13 @@ uint32_t Multicast::dtm_dgram_bcast_listener() {
       return NCSCC_RC_FAILURE;
     }
     if (p->ai_family == AF_INET6) {
+      int v6only = 1;
+      if (setsockopt(dgram_sock_rcvr, IPPROTO_IPV6, IPV6_V6ONLY, &v6only,
+                     sizeof(v6only)) < 0)
+        LOG_ER("setsockopt(IPV6_V6ONLY) failed: %s", strerror(errno));
       struct sockaddr_in6 *ipv6 =
           reinterpret_cast<struct sockaddr_in6 *>(p->ai_addr);
-      ifindex = if_nametoindex(ifname_.c_str());
+      unsigned ifindex = if_nametoindex(ifname_.c_str());
       ipv6->sin6_scope_id = ifindex;
       if (setsockopt(dgram_sock_rcvr, IPPROTO_IPV6, IPV6_MULTICAST_IF, 
&ifindex,
                      sizeof(ifindex)) < 0) {
@@ -763,14 +1125,14 @@ uint32_t Multicast::dtm_dgram_bcast_listener() {
       freeaddrinfo(addr_list);
       return NCSCC_RC_FAILURE;
     } else {
-      binded = true;
+      bound = true;
       break;
     }
   }
 
   /* Free address structure(s) allocated by getaddrinfo() */
   freeaddrinfo(addr_list);
-  if (binded != true) {
+  if (bound != true) {
     TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
     return NCSCC_RC_FAILURE;
   } else {
diff --git a/src/dtm/dtmnd/Multicast.h b/src/dtm/dtmnd/Multicast.h
index e3b90f1b6..01d818639 100644
--- a/src/dtm/dtmnd/Multicast.h
+++ b/src/dtm/dtmnd/Multicast.h
@@ -21,6 +21,8 @@
 #include <sys/socket.h>
 #include <cstddef>
 #include <cstdint>
+#include <cstring>
+#include <set>
 #include <string>
 
 // The Multicast class implements a mechanism to send the DTM node discovery
@@ -42,7 +44,8 @@ class Multicast {
     char stream_address[kInet6AddrStrlen];
   };
 
-  // Construct an instance of Multicast, using the supplied configuration 
parameters.
+  // Construct an instance of Multicast, using the supplied configuration
+  // parameters.
   Multicast(uint16_t cluster_id, uint32_t node_id, in_port_t stream_port,
             in_port_t dgram_port, sa_family_t address_family,
             const std::string& stream_address, const std::string& 
dgram_address,
@@ -67,6 +70,48 @@ class Multicast {
   int fd() { return dgram_sock_rcvr; }
 
  private:
+  class Peer {
+   public:
+    Peer(const struct sockaddr* addr, socklen_t length)
+        : address_{new uint8_t[length]}, length_{length} {
+      memcpy(address_, addr, length);
+    }
+    Peer(const Peer& peer)
+        : address_{new uint8_t[peer.length_]}, length_{peer.length_} {
+      memcpy(address_, peer.address_, peer.length_);
+    }
+    Peer(Peer&& peer) : address_{peer.address_}, length_{peer.length_} {}
+    ~Peer() { delete[] address_; }
+    Peer& operator=(const Peer& peer) {
+      if (&peer != this) {
+        address_ = new uint8_t[peer.length_];
+        length_ = peer.length_;
+        memcpy(address_, peer.address_, peer.length_);
+      }
+      return *this;
+    }
+    Peer& operator=(Peer&& peer) {
+      address_ = peer.address_;
+      length_ = peer.length_;
+      return *this;
+    }
+    bool operator<(const Peer& peer) const {
+      return length_ == peer.length_
+                 ? (memcmp(address_, peer.address_, length_) < 0)
+                 : (length_ < peer.length_);
+    }
+    const struct sockaddr* address() const {
+      return reinterpret_cast<sockaddr*>(address_);
+    }
+    socklen_t length() const { return length_; }
+
+   private:
+    uint8_t* address_;
+    socklen_t length_;
+  };
+  enum Protocol { kBroadcast, kMulticast, kFileUnicast, kDnsUnicast };
+  bool InitializeUnicastSender();
+  bool InitializeUnicastReceiver();
   uint32_t dtm_dgram_bcast_sender();
   uint32_t dgram_enable_bcast(int sock_desc);
   uint32_t dtm_dgram_mcast_sender(int mcast_ttl);
@@ -74,6 +119,12 @@ class Multicast {
   uint32_t dgram_join_mcast_group(struct addrinfo* mcast_receiver_addr);
   uint32_t dtm_dgram_mcast_listener();
   uint32_t dtm_dgram_bcast_listener();
+  static Protocol GetProtocol(const std::string& multicast_address);
+  bool GetPeersFromFile(const std::string& path_name);
+  bool GetPeersFromDns(const std::string& domain_name);
+  static socklen_t ParseAddress(sa_family_t address_family,
+                                const std::string& address, in_port_t port,
+                                struct sockaddr_storage* addr);
 
   uint16_t cluster_id_;
   uint32_t node_id_;
@@ -85,12 +136,11 @@ class Multicast {
   std::string multicast_address_;
   std::string ifname_;
   bool scope_link_;
+  Protocol protocol_;
+  std::set<Peer> peers_;
 
-  socklen_t dest_addr_size_;  // Holder for bcast_dest_address size ip v4 or v6
-                              // address
   int dgram_sock_sndr;
   int dgram_sock_rcvr;
-  struct sockaddr_storage dest_addr_;
 };
 
 #endif  // DTM_DTMND_MULTICAST_H_
diff --git a/src/dtm/dtmnd/dtm_node.cc b/src/dtm/dtmnd/dtm_node.cc
index 66f728c74..92cd60ace 100644
--- a/src/dtm/dtmnd/dtm_node.cc
+++ b/src/dtm/dtmnd/dtm_node.cc
@@ -27,6 +27,7 @@
 #include <cstdlib>
 #include <cstring>
 #include "base/ncsencdec_pub.h"
+#include "base/osaf_utility.h"
 #include "dtm/dtmnd/Multicast.h"
 #include "dtm/dtmnd/dtm.h"
 #include "dtm/dtmnd/dtm_inter.h"
@@ -452,6 +453,10 @@ void node_discovery_process(void *arg) {
       /* descriptor. */
       /*******************************************************/
       if (close_conn) {
+        if (node == &dgram_sock_rcvr || node == &stream_sock ||
+            node == &mbx_fd) {
+          osaf_abort(node->comm_socket);
+        }
         close_conn = false;
         RemoveNodeFromEpoll(dtms_cb, node);
         dtm_comm_socket_close(node);
diff --git a/src/dtm/dtmnd/dtm_node_sockets.cc 
b/src/dtm/dtmnd/dtm_node_sockets.cc
index 59cf12a0d..2b49b988d 100644
--- a/src/dtm/dtmnd/dtm_node_sockets.cc
+++ b/src/dtm/dtmnd/dtm_node_sockets.cc
@@ -22,6 +22,7 @@
 #include <netinet/tcp.h>
 #include <sys/socket.h>
 #include <unistd.h>
+#include <cerrno>
 #include <cstring>
 #include "base/ncsencdec_pub.h"
 #include "base/usrbuf.h"
@@ -35,6 +36,8 @@
 #define MYPORT "6900"
 #define MAXBUFLEN 100
 
+#define MAXPENDING 20
+
 /**
  * Close the socketr descriptors
  *
@@ -350,30 +353,35 @@ done:
  * @return NCSCC_RC_FAILURE
  *
  */
-#define MAXPENDING 20
-
 static uint32_t stream_sock_bind(DTM_INTERNODE_CB *dtms_cb,
                                  struct addrinfo *stream_addr) {
   /* Bind to the local address and set socket to list */
   TRACE_ENTER();
-  if ((bind(dtms_cb->stream_sock, stream_addr->ai_addr,
-            stream_addr->ai_addrlen) == 0) &&
-      (listen(dtms_cb->stream_sock, MAXPENDING) == 0)) {
-    /* get local address of socket */
-    struct sockaddr_storage local_addr;
-    socklen_t addr_size = sizeof(local_addr);
-    if (getsockname(dtms_cb->stream_sock,
-                    reinterpret_cast<struct sockaddr *>(&local_addr),
-                    &addr_size) < 0) {
-      LOG_ER("DTM : getsockname() failed err :%s", strerror(errno));
-      TRACE_LEAVE2("rc :%d", NCSCC_RC_FAILURE);
+  if (bind(dtms_cb->stream_sock, stream_addr->ai_addr,
+           stream_addr->ai_addrlen) == 0) {
+    if (listen(dtms_cb->stream_sock, MAXPENDING) == 0) {
+      /* get local address of socket */
+      struct sockaddr_storage local_addr;
+      socklen_t addr_size = sizeof(local_addr);
+      if (getsockname(dtms_cb->stream_sock,
+                      reinterpret_cast<struct sockaddr *>(&local_addr),
+                      &addr_size) < 0) {
+        LOG_ER("DTM : getsockname() failed err :%s", strerror(errno));
+        TRACE_LEAVE2("rc: %d", NCSCC_RC_FAILURE);
+        return NCSCC_RC_FAILURE;
+      }
+      TRACE("DTM : Binding done for : %d", dtms_cb->stream_sock);
+    } else {
+      LOG_ER("listen(%d) failed with errno %d", dtms_cb->stream_sock, errno);
+      TRACE_LEAVE2("rc: %d", NCSCC_RC_FAILURE);
       return NCSCC_RC_FAILURE;
     }
-
-    TRACE("DTM : Binding done for : %d", dtms_cb->stream_sock);
+  } else {
+    LOG_ER("bind(%d) failed with errno %d", dtms_cb->stream_sock, errno);
+    TRACE_LEAVE2("rc: %d", NCSCC_RC_FAILURE);
+    return NCSCC_RC_FAILURE;
   }
-
-  TRACE_LEAVE2("rc :%d", NCSCC_RC_SUCCESS);
+  TRACE_LEAVE2("rc: %d", NCSCC_RC_SUCCESS);
   return NCSCC_RC_SUCCESS;
 }
 
@@ -422,7 +430,7 @@ uint32_t dtm_stream_nonblocking_listener(DTM_INTERNODE_CB 
*dtms_cb) {
   } else {
     rv = getaddrinfo(dtms_cb->ip_addr.c_str(), local_port_str, &addr_criteria,
                      &addr_list);
-    TRACE("DTM :ip_addr : %s local_port_str -%s", dtms_cb->ip_addr.c_str(),
+    TRACE("DTM :ip_addr : %s local_port_str :%s", dtms_cb->ip_addr.c_str(),
           local_port_str);
   }
   if (rv != 0) {
diff --git a/src/dtm/dtmnd/dtmd.conf b/src/dtm/dtmnd/dtmd.conf
index 50661fd52..08530b808 100644
--- a/src/dtm/dtmnd/dtmd.conf
+++ b/src/dtm/dtmnd/dtmd.conf
@@ -8,6 +8,9 @@
 # Uncomment the next line to enable trace
 #args="--tracemask=0xffffffff"
 
+# Uncomment the next line to enable info level logging
+#args="--loglevel=info"
+
 # Healthcheck keys
 export DTM_ENV_HEALTHCHECK_KEY="Default"
 
@@ -19,9 +22,21 @@ DTM_CLUSTER_ID=1
 # Mandatory
 DTM_NODE_IP=10.130.100.114
 
-# Multicast IP of the self node 
-# DTMSv
-# Optional
+# IPv4/IPv6 multicast group address, or source of peer IP addresses for unicast
+#
+# Set DTM_MCAST_ADDR to a non-empty string to use multicast or unicast instead
+# of broadcast.
+#
+# * To use multicast, specify an IPv4 or IPv6 multicast group address
+# * To use unicast, the string should start with "file:" followed
+#   by the path name of a file containing a list of IP addresses (one per 
line),
+#   or start with "dns:" followed by a DNS domain name, respectively.
+#
+# Examples:
+#DTM_MCAST_ADDR=224.0.0.1
+#DTM_MCAST_ADDR=ff02::1
+#DTM_MCAST_ADDR=file:/var/lib/peer_ip_addresses.txt
+#DTM_MCAST_ADDR=dns:peers.opensaf.org
 DTM_MCAST_ADDR=
 
 # tcp_listening_port: The TCP port that the DTMSv listens on
@@ -40,7 +55,7 @@ DTM_UDP_BCAST_REV_PORT=6900
 #
 # bcast_freq: frequencey (in milliseconds) between broadcasts during initial
 # discovery
-DTM_BCAST_FRE_MSECS=250 
+DTM_BCAST_FRE_MSECS=250
 
 # cont_bcast_int: interval (in milliseconds) between broadcasts after initial
 # discovery has completed
@@ -59,19 +74,19 @@ DTM_INI_DIS_TIMEOUT_SECS=5
 DTM_SKEEPALIVE=1
 
 #
-# tcp_keepalive_time: The time (in seconds) the connection needs to remain 
+# tcp_keepalive_time: The time (in seconds) the connection needs to remain
 # idle before TCP starts sending keepalive probes
 # Optional
 DTM_TCP_KEEPIDLE_TIME=2
 
 #
-# tcp_keepalive_intvl: The time (in seconds) between individual keepalive 
+# tcp_keepalive_intvl: The time (in seconds) between individual keepalive
 # probes.
 # Optional
 DTM_TCP_KEEPALIVE_INTVL=1
 
 #
-# tcp_keepalive_probes: The  maximum number of keepalive probes TCP should 
+# tcp_keepalive_probes: The  maximum number of keepalive probes TCP should
 # send before dropping the connection.
 # Optional
 DTM_TCP_KEEPALIVE_PROBES=2
@@ -83,7 +98,7 @@ DTM_TCP_KEEPALIVE_PROBES=2
 # Decreasing the user timeouts allows applications to "fail fast" if so 
desired.
 # Otherwise it may take upto 20 minutes with the current system
 #  defaults in a normal WAN environment.
-# This option, TCP_USER_TIMEOUT will override keepalive 
+# This option, TCP_USER_TIMEOUT will override keepalive
 # to determine when to close a connection due to keepalive failure.
 # kept to 1.5 sec to match other transport protocols supported Opensaf
 DTM_TCP_USER_TIMEOUT=1500
@@ -98,10 +113,10 @@ DTM_TCP_USER_TIMEOUT=1500
 # IMP NOTE : If DTM_SOCK_SND_RCV_BUF_SIZE  is configured according to 
application requirements ,
 #it is also mandatory to  export `MDS_SOCK_SND_RCV_BUF_SIZE=` with  the same 
value of
 #for example if set as DTM_SOCK_SND_RCV_BUF_SIZE=126976 need to do :
-#export MDS_SOCK_SND_RCV_BUF_SIZE=126976 
+#export MDS_SOCK_SND_RCV_BUF_SIZE=126976
 DTM_SOCK_SND_RCV_BUF_SIZE=65536
 
 #
 #The maximum processes allowed per node
-#Used to Set the dtm intra node maximum allowed processes 
+#Used to Set the dtm intra node maximum allowed processes
 DTM_INTRANODE_MAX_PROCESSES=100
-- 
2.13.3


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to