File dhcp-3.1.1-ldap-patch_failover-obj.dif of Package dhcp

--- server/ldap.c
+++ server/ldap.c	2009/01/15 15:42:21
@@ -106,6 +106,106 @@ x_strxform(char *dst, const char *src, s
 	return NULL;
 }
 
+static int
+get_host_entry(char *fqdnname, size_t fqdnname_size,
+               char *hostaddr, size_t hostaddr_size)
+{
+#if defined(MAXHOSTNAMELEN)
+  char   hname[MAXHOSTNAMELEN+1];
+#else
+  char   hname[65];
+#endif
+  struct hostent *hp;
+
+  if (NULL == fqdnname || 1 >= fqdnname_size)
+    return -1;
+
+  memset(hname, 0, sizeof(hname));
+  if (gethostname(hname, sizeof(hname)-1))
+    return -1;
+
+  if (NULL == (hp = gethostbyname(hname)))
+    return -1;
+
+  strncpy(fqdnname, hp->h_name, fqdnname_size-1);
+  fqdnname[fqdnname_size-1] = '\0';
+
+  if (hostaddr != NULL)
+    {
+      if (hp->h_addr != NULL)
+        {
+          struct in_addr *aptr = (struct in_addr *)hp->h_addr;
+#if defined(HAVE_INET_NTOP)
+          if (hostaddr_size >= INET_ADDRSTRLEN &&
+              inet_ntop(AF_INET, aptr, hostaddr, hostaddr_size) != NULL)
+            {
+              return 0;
+            }
+#else
+          char  *astr = inet_ntoa(*aptr);
+          size_t alen = strlen(astr);
+          if (astr && alen > 0 && hostaddr_size > alen)
+            {
+              strncpy(hostaddr, astr, hostaddr_size-1);
+              hostaddr[hostaddr_size-1] = '\0';
+              return 0;
+            }
+#endif
+        }
+      return -1;
+    }
+  return 0;
+}
+
+static int
+get_host_address(const char *hostname, char *hostaddr, size_t hostaddr_size)
+{
+  if (hostname && *hostname && hostaddr && hostaddr_size)
+    {
+      struct in_addr addr;
+
+#if defined(HAVE_INET_PTON)
+      if (inet_pton(AF_INET, hostname, &addr) == 0)
+#else
+      if (inet_aton(hostname, &addr) == 0)
+#endif
+        {
+          /* it is already IP address string */
+          if(strlen(hostname) < hostaddr_size)
+            {
+              strncpy(hostaddr, hostname, hostaddr_size-1);
+              hostaddr[hostaddr_size-1] = '\0';
+              return 0;
+            }
+        }
+      else
+        {
+          struct hostent *hp;
+          if ((hp = gethostbyname(hostname)) != NULL && hp->h_addr != NULL)
+            {
+              struct in_addr *aptr = (struct in_addr *)hp->h_addr;
+#if defined(HAVE_INET_NTOP)
+              if (hostaddr_size >= INET_ADDRSTRLEN &&
+                  inet_ntop(AF_INET, aptr, hostaddr, hostaddr_size) != NULL)
+                {
+                  return 0;
+                }
+#else
+              char  *astr = inet_ntoa(*aptr);
+              size_t alen = strlen(astr);
+              if (astr && alen > 0 && alen < hostaddr_size)
+                {
+                  strncpy(hostaddr, astr, hostaddr_size-1);
+                  hostaddr[hostaddr_size-1] = '\0';
+                  return 0;
+                }
+#endif
+            }
+        }
+    }
+  return -1;
+}
+
 static void
 ldap_parse_class (struct ldap_config_stack *item, struct parse *cfile)
 {
@@ -447,6 +547,220 @@ add_to_config_stack (LDAPMessage * res,
   ldap_stack = ns;
 }
 
+static void
+ldap_parse_failover (struct ldap_config_stack *item, struct parse *cfile)
+{
+  char **tempstr;
+  char nodename[257]="\0", fqdnname[257]="\0", fqdnaddr[64]="\0";
+  char srvaddr[2][64] = {"\0", "\0"};
+  int primary, split = 0;
+  struct utsname unme;
+
+  if(uname(&unme) == 0)
+    {
+      snprintf(nodename, sizeof(nodename), "%s", unme.nodename);
+    }
+  if (get_host_entry (fqdnname, sizeof(fqdnname), fqdnaddr, sizeof(fqdnaddr)))
+    {
+      log_info("Could not get fqdn and the IP address of the host");
+      return;
+    }
+
+  /*
+  ** when dhcpFailOverPrimaryServer or dhcpFailOverSecondaryServer
+  ** matches our IP address, the following valiables are set:
+  ** - primary is 1 when we are primary or 0 when we are secondary
+  ** - srvaddr[0] contains ip address of the primary
+  ** - srvaddr[1] contains ip address of the secondary
+  */
+  primary = -1;
+  if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverPrimaryServer")) != NULL)
+    {
+      if (strcasecmp (tempstr[0], fqdnaddr) == 0 ||
+          strcasecmp (tempstr[0], fqdnname) == 0 ||
+          strcasecmp (tempstr[0], nodename) == 0)
+        {
+          /* we are the primary */
+          primary = 1;
+          /* write primary address */
+          strncpy(srvaddr[0], fqdnaddr, sizeof(srvaddr[0])-1);
+          srvaddr[0][sizeof(srvaddr[0])-1] = '\0';
+        }
+      else
+        {
+          /* no match => don't set primary flag */
+          /* write primary address */
+          if (get_host_address (tempstr[0], srvaddr[0], sizeof(srvaddr[0])) != 0)
+            {
+              log_info("Can't resolve address of the primary failover server %s",
+                       tempstr[0]);
+              ldap_value_free (tempstr);
+              return;
+            }
+        }
+      ldap_value_free (tempstr);
+    }
+
+  if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverSecondaryServer")) != NULL)
+    {
+      if (strcasecmp (tempstr[0], fqdnaddr) == 0 ||
+          strcasecmp (tempstr[0], fqdnname) == 0 ||
+          strcasecmp (tempstr[0], nodename) == 0)
+        {
+          if (primary == 1)
+            {
+              log_info("Both, primary and secondary failover server"
+                       " attribute matches our hostname/address");
+              ldap_value_free (tempstr);
+              return;
+            }
+          /* we are the secondary */
+          primary = 0;
+          /* write secondary address */
+          strncpy(srvaddr[1], fqdnaddr, sizeof(srvaddr[1])-1);
+          srvaddr[1][sizeof(srvaddr[1])-1] = '\0';
+        }
+      else
+        {
+          /* no match => don't set primary flag */
+          /* write secondary address */
+          if (get_host_address (tempstr[0], srvaddr[1], sizeof(srvaddr[1])) != 0)
+            {
+                log_info("Can't resolve address of the secondary failover server %s",
+                         tempstr[0]);
+                ldap_value_free (tempstr);
+                return;
+            }
+        }
+      ldap_value_free (tempstr);
+    }
+
+  if (primary == -1 || srvaddr[0] == '\0' || srvaddr[1] == '\0')
+    {
+      log_error("Could not decide if the server type is primary"
+                " or secondary for failover peering.");
+      return;
+    }
+
+  if ((tempstr = ldap_get_values (ld, item->ldent, "cn")) != NULL)
+    {
+      x_strncat (cfile->inbuf, "failover peer \"", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
+      ldap_value_free (tempstr);
+    }
+  else
+    {
+      // ldap with disabled schema checks? fail to avoid syntax error.
+      log_error("Unable to find mandatory failover peering name attribute");
+      return;
+    }
+
+  if (primary)
+    x_strncat (cfile->inbuf, "primary;\n", LDAP_BUFFER_SIZE);
+  else
+    x_strncat (cfile->inbuf, "secondary;\n", LDAP_BUFFER_SIZE);
+
+  x_strncat (cfile->inbuf, "address ", LDAP_BUFFER_SIZE);
+  if (primary)
+    x_strncat (cfile->inbuf, srvaddr[0], LDAP_BUFFER_SIZE);
+  else
+    x_strncat (cfile->inbuf, srvaddr[1], LDAP_BUFFER_SIZE);
+  x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+
+  x_strncat (cfile->inbuf, "peer address ", LDAP_BUFFER_SIZE);
+  if (primary)
+    x_strncat (cfile->inbuf, srvaddr[1], LDAP_BUFFER_SIZE);
+  else
+    x_strncat (cfile->inbuf, srvaddr[0], LDAP_BUFFER_SIZE);
+  x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+
+  if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverPrimaryPort")) != NULL)
+    {
+      if (primary)
+        x_strncat (cfile->inbuf, "port ", LDAP_BUFFER_SIZE);
+      else
+        x_strncat (cfile->inbuf, "peer port ", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+      ldap_value_free (tempstr);
+    }
+  if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverSecondaryPort")) != NULL)
+    {
+      if (primary)
+        x_strncat (cfile->inbuf, "peer port ", LDAP_BUFFER_SIZE);
+      else
+        x_strncat (cfile->inbuf, "port ", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+      ldap_value_free (tempstr);
+    }
+
+  if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverResponseDelay")) != NULL)
+    {
+      x_strncat (cfile->inbuf, "max-response-delay ", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+      ldap_value_free (tempstr);
+    }
+
+  if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverUnackedUpdates")) != NULL)
+    {
+      x_strncat (cfile->inbuf, "max-unacked-updates ", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+      ldap_value_free (tempstr);
+    }
+
+  if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverLoadBalanceTime")) != NULL)
+    {
+      x_strncat (cfile->inbuf, "load balance max seconds ", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+      ldap_value_free (tempstr);
+    }
+
+  if (primary &&
+      (tempstr = ldap_get_values (ld, item->ldent, "dhcpMaxClientLeadTime")) != NULL)
+    {
+      x_strncat (cfile->inbuf, "mclt ", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+      ldap_value_free (tempstr);
+    }
+
+  if (primary &&
+      (tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverSplit")) != NULL)
+    {
+      x_strncat (cfile->inbuf, "split ", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+      split = 1;
+      ldap_value_free (tempstr);
+    }
+
+  if (primary && !split &&
+      (tempstr = ldap_get_values (ld, item->ldent, "dhcpFailOverHashBucketAssignment")) != NULL)
+    {
+      x_strncat (cfile->inbuf, "hba ", LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+      x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+      ldap_value_free (tempstr);
+    }
+
+  /*
+  ** Are there any other options can come here? If yes then we need to enable
+  ** dhcpStatements in the schema and apply them here as well.
+  **
+  if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpStatements")) != NULL)
+    {
+      ...
+      ldap_value_free (tempstr);
+    }
+  */
+
+  item->close_brace = 1;
+}
 
 static void
 ldap_stop()
@@ -1171,6 +1485,8 @@ ldap_generate_config_string (struct pars
         ldap_parse_key (entry, cfile);
       else if (strcasecmp (objectClass[i], "dhcpDnsZone") == 0)
         ldap_parse_zone (entry, cfile);
+      else if (strcasecmp (objectClass[i], "dhcpFailOverPeer") == 0)
+        ldap_parse_failover (entry, cfile);
       else if (strcasecmp (objectClass[i], "dhcpHost") == 0)
         {
           if (ldap_method == LDAP_METHOD_STATIC)
@@ -1356,32 +1672,6 @@ ldap_get_host_name (LDAPMessage * ent)
 }
 
 
-static int
-getfqhostname(char *fqhost, size_t size)
-{
-#if defined(MAXHOSTNAMELEN)
-  char   hname[MAXHOSTNAMELEN];
-#else
-  char   hname[65];
-#endif
-  struct hostent *hp;
-
-  if(NULL == fqhost || 1 >= size)
-    return -1;
-
-  memset(hname, 0, sizeof(hname));
-  if( gethostname(hname, sizeof(hname)-1))
-    return -1;
-
-  if(NULL == (hp = gethostbyname(hname)))
-    return -1;
-
-  strncpy(fqhost, hp->h_name, size-1);
-  fqhost[size-1] = '\0';
-  return 0;
-}
-
-
 isc_result_t
 ldap_read_config (void)
 {
@@ -1417,7 +1707,7 @@ ldap_read_config (void)
     }
   else
   {
-  if(0 == getfqhostname(fqdn, sizeof(fqdn)))
+  if(0 == get_host_entry(fqdn, sizeof(fqdn), NULL, 0))
     {
       snprintf (hfilter, sizeof (hfilter),
                 "(&(objectClass=dhcpServer)(|(cn=%s)(cn=%s)))",