382 lines
12 KiB
Plaintext
382 lines
12 KiB
Plaintext
--- 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)))",
|