diff --git a/include/ldap.h b/include/ldap.h
index 499d096aa0a9da940a5d39fc2b66727bf0e7466c..16c33432c89bc9adba1fa92af66013e577d34047 100644
--- a/include/ldap.h
+++ b/include/ldap.h
@@ -463,7 +463,7 @@ struct timeval;
 LDAP_F int ldap_get_option LDAP_P((LDAP *ld, int option, void *outvalue));
 LDAP_F int ldap_set_option LDAP_P((LDAP *ld, int option, void *invalue));
 
-/* Not yet */
+/* in controls.c */
 LDAP_F void ldap_control_free LDAP_P(( LDAPControl *ctrl ));
 LDAP_F void ldap_controls_free LDAP_P(( LDAPControl **ctrls ));
   
diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in
index 013b2e4976163ffe961206e61827a949d8ee363e..cb14f22a0c20e11c6b3afc10dc5f17555684a679 100644
--- a/libraries/libldap/Makefile.in
+++ b/libraries/libldap/Makefile.in
@@ -6,14 +6,14 @@ XLIBRARY = ../libldap.a
 
 PROGRAMS = apitest ltest ttest
 
-SRCS	= bind.c open.c result.c error.c compare.c search.c \
+SRCS	= bind.c controls.c open.c result.c error.c compare.c search.c \
 	modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
 	getfilter.c sbind.c kbind.c unbind.c friendly.c cldap.c \
 	free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
 	getdn.c getentry.c getattr.c getvalues.c addentry.c \
 	request.c getdxbyname.c os-ip.c url.c charset.c \
 	init.c options.c strdup.c util-int.c
-OBJS	= bind.lo open.lo result.lo error.lo compare.lo search.lo \
+OBJS	= bind.lo controls.lo open.lo result.lo error.lo compare.lo search.lo \
 	modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
 	getfilter.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \
 	free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \
diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h
index 9fc14c3e67c3d1f0bcd90fc039a3ba1174255e5b..d9c77df4254c6c0e6e7367a95a7b951d9031ad9b 100644
--- a/libraries/libldap/ldap-int.h
+++ b/libraries/libldap/ldap-int.h
@@ -77,14 +77,18 @@ struct ldapoptions {
 
 	int		ldo_debug;
 
+	int		ldo_defport;
 	char*	ldo_defbase;
 	char*	ldo_defhost;
-	int		ldo_defport;
 
 	int		ldo_cldaptries;	/* connectionless search retry count */
 	int		ldo_cldaptimeout;/* time between retries */
 	int		ldo_refhoplimit;	/* limit on referral nesting */
 
+	/* LDAPv3 server and client controls */
+	LDAPControl	**ldo_server_controls;
+	LDAPControl **ldo_client_controls;
+	
 	LDAP_BOOLEANS ldo_booleans;	/* boolean options */
 };
 
@@ -237,6 +241,12 @@ void ldap_add_request_to_cache LDAP_P(( LDAP *ld, unsigned long msgtype,
 void ldap_add_result_to_cache LDAP_P(( LDAP *ld, LDAPMessage *result ));
 int ldap_check_cache LDAP_P(( LDAP *ld, unsigned long msgtype, BerElement *request ));
 
+/*
+ * in controls.c
+ */
+LDAPControl *ldap_control_dup LDAP_P(( LDAPControl *ctrl ));
+LDAPControl **ldap_controls_dup LDAP_P(( LDAPControl **ctrl ));
+
 /*
  * in dsparse.c
  */
diff --git a/libraries/libldap/options.c b/libraries/libldap/options.c
index 0fd9ef5c70ce506c4450c2da43f3be73ef85d83d..5037dc619db26099147dd718c1fd19813ec43088 100644
--- a/libraries/libldap/options.c
+++ b/libraries/libldap/options.c
@@ -142,18 +142,22 @@ ldap_get_option(
 		return 0;
 
 	case LDAP_OPT_SERVER_CONTROLS:
-		/* not yet supported */
-		break;
+		* (LDAPControl ***) outvalue =
+			ldap_controls_dup( lo->ldo_server_controls );
+
+		return 0;
 
 	case LDAP_OPT_CLIENT_CONTROLS:
-		/* not yet supported */
-		break;
+		* (LDAPControl ***) outvalue =
+			ldap_controls_dup( lo->ldo_client_controls );
+
+		return 0;
 
 	case LDAP_OPT_HOST_NAME:
 		/*
 		 * draft-ietf-ldapext-ldap-c-api-01 doesn't state
-		 * whether client to have to free host names or no,
-		 * we do
+		 * whether caller has to free host names or not,
+		 * we do.
 		 */
 
 		* (char **) outvalue = ldap_strdup(lo->ldo_defhost);
@@ -183,6 +187,7 @@ ldap_get_option(
 		} else {
 			* (char **) outvalue = ldap_strdup(ld->ld_error);
 		}
+
 		return 0;
 
 	case LDAP_OPT_API_FEATURE_INFO: {
@@ -281,12 +286,42 @@ ldap_set_option(
 		} return 0;
 
 	case LDAP_OPT_SERVER_CONTROLS: {
-			/* not yet supported */
-		} break;
+			LDAPControl **controls = (LDAPControl **) invalue;
+
+			ldap_controls_free( lo->ldo_server_controls );
+
+			if( controls == NULL || *controls == NULL ) {
+				lo->ldo_server_controls = NULL;
+				return 0;
+			}
+				
+			lo->ldo_server_controls =
+				ldap_controls_dup( (LDAPControl **) invalue );
+
+			if(lo->ldo_server_controls == NULL) {
+				/* memory allocation error ? */
+				break;
+			}
+		} return 0;
 
 	case LDAP_OPT_CLIENT_CONTROLS: {
-			/* not yet supported */
-		} break;
+			LDAPControl **controls = (LDAPControl **) invalue;
+
+			ldap_controls_free( lo->ldo_client_controls );
+
+			if( controls == NULL || *controls == NULL ) {
+				lo->ldo_client_controls = NULL;
+				return 0;
+			}
+				
+			lo->ldo_client_controls =
+				ldap_controls_dup( (LDAPControl **) invalue );
+
+			if(lo->ldo_client_controls == NULL) {
+				/* memory allocation error ? */
+				break;
+			}
+		} return 0;
 
 	case LDAP_OPT_HOST_NAME: {
 			char* host = (char *) invalue;
@@ -341,7 +376,7 @@ ldap_set_option(
 				free(ld->ld_error);
 			}
 
-			ld->ld_error = strdup(err);
+			ld->ld_error = ldap_strdup(err);
 		} return 0;
 
 	case LDAP_OPT_API_FEATURE_INFO:
diff --git a/libraries/libldap_r/Makefile.in b/libraries/libldap_r/Makefile.in
index f5a28dba9a9d4cdf0f4141c830adfbd71563d117..e8d5f69b0ebe841027390d50204b79e54681b888 100644
--- a/libraries/libldap_r/Makefile.in
+++ b/libraries/libldap_r/Makefile.in
@@ -8,14 +8,14 @@ PROGRAMS = apitest ltest ttest
 
 XXDIR = ../libldap
 XXSRCS	= apitest.c test.c tmpltest.c \
-	bind.c open.c result.c error.c compare.c search.c \
+	bind.c controls.c open.c result.c error.c compare.c search.c \
 	modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
 	getfilter.c sbind.c kbind.c unbind.c friendly.c cldap.c \
 	free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
 	getdn.c getentry.c getattr.c getvalues.c addentry.c \
 	request.c getdxbyname.c os-ip.c url.c charset.c \
 	init.c options.c strdup.c util-int.c
-OBJS	= bind.lo open.lo result.lo error.lo compare.lo search.lo \
+OBJS	= bind.lo controls.lo open.lo result.lo error.lo compare.lo search.lo \
 	modify.lo add.lo modrdn.lo delete.lo abandon.lo ufn.lo cache.lo \
 	getfilter.lo sbind.lo kbind.lo unbind.lo friendly.lo cldap.lo \
 	free.lo disptmpl.lo srchpref.lo dsparse.lo tmplout.lo sort.lo \