diff -uNr ruby-ldap-0.8.3.orig/conn.c ruby-ldap-0.8.3/conn.c
--- ruby-ldap-0.8.3.orig/conn.c	2004-02-16 03:55:41.000000000 -0800
+++ ruby-ldap-0.8.3/conn.c	2004-11-13 01:05:26.434285432 -0800
@@ -9,6 +9,7 @@
 #include <unistd.h>
 
 static VALUE rb_ldap_sort_obj = Qnil;
+extern VALUE rb_ldap_control_new2(LDAPControl *ctl);
 
 VALUE rb_cLDAP_Conn;
 
@@ -358,6 +359,11 @@
     /* optdata = (void*)rb_ldap_get_apiinfo(data); */
     break;
 #endif
+#ifdef LDAP_OPT_SERVER_CONTROLS
+  case LDAP_OPT_SERVER_CONTROLS:
+    optdata = rb_ldap_get_controls(data);
+    break;
+#endif
   default:
     rb_notimplement();
   }
@@ -709,18 +715,59 @@
 }
 
 VALUE
+rb_ldap_parse_result(LDAP *cldap, LDAPMessage *cmsg)
+{
+    int rc, err, i;
+    char **referrals;
+    LDAPControl **serverctrls;
+    VALUE refs, ctls, ary;
+
+    refs = rb_ary_new();
+    ctls = rb_ary_new();
+    ary = rb_ary_new();
+
+    rc = ldap_parse_result(cldap, cmsg, &err, NULL, NULL,
+			   &referrals, &serverctrls, 0);
+    Check_LDAP_Result(rc);
+    Check_LDAP_Result(err);
+
+    if( referrals ) {
+      for( i=0; referrals[i]; i++ ){
+        rb_ary_push(refs, rb_str_new2(referrals[i]));
+      }
+    }
+
+    if( serverctrls ) {
+      for( i=0; serverctrls[i]; i++ ){
+        rb_ary_push(ctls, rb_ldap_control_new2(serverctrls[i]));
+      }
+    }
+
+    rb_ary_push(ary, refs);
+    rb_ary_push(ary, ctls);
+
+    return ary;
+}
+
+VALUE
 rb_ldap_conn_search_s(int argc, VALUE argv[], VALUE self)
 {
     RB_LDAP_DATA *ldapdata;
     LDAPMessage *cmsg;
     LDAP *cldap;
     LDAPMessage *e;
+    VALUE rc_ary = Qnil;
 
     rb_ldap_conn_search_i(argc, argv, self, &ldapdata, &cmsg);
     cldap = ldapdata->ldap;
 
     if( ldapdata->err == LDAP_SUCCESS ){
 	void *pass_data[] = {(void*)cldap, (void*)cmsg};
+
+	rc_ary = rb_ldap_parse_result(cldap, cmsg);
+	rb_iv_set(self, "@referrals", rb_ary_shift(rc_ary));
+	rb_iv_set(self, "@controls", rb_ary_shift(rc_ary));
+
 	rb_ensure(rb_ldap_conn_search_b, (VALUE)pass_data,
 		  rb_ldap_msgfree, (VALUE)cmsg);
     };
@@ -758,6 +805,7 @@
   LDAPMessage *e;
   LDAP *cldap;
   VALUE ary = Qnil;
+  VALUE rc_ary = Qnil;
 
   rb_ldap_conn_search_i(argc, argv, self, &ldapdata, &cmsg);
   cldap = ldapdata->ldap;
@@ -765,6 +813,11 @@
   ary = rb_ary_new();
   if( ldapdata->err == LDAP_SUCCESS ){
       void *pass_data[] = {(void*)cldap, (void*)cmsg, (void*)ary};
+
+      rc_ary = rb_ldap_parse_result(cldap, cmsg);
+      rb_iv_set(self, "@referrals", rb_ary_shift(rc_ary));
+      rb_iv_set(self, "@controls", rb_ary_shift(rc_ary));
+
       rb_ensure(rb_ldap_conn_search2_b, (VALUE)pass_data,
 		rb_ldap_msgfree, (VALUE)cmsg);
   }
@@ -1206,6 +1259,8 @@
   rb_ldap_sort_obj = Qnil;
 
   rb_cLDAP_Conn = rb_define_class_under(rb_mLDAP,"Conn",rb_cData);
+  rb_define_attr(rb_cLDAP_Conn, "referrals", 1, 0);
+  rb_define_attr(rb_cLDAP_Conn, "controls", 1, 0);
 #if RUBY_VERSION_CODE < 170
   rb_define_singleton_method(rb_cLDAP_Conn,"new",rb_ldap_class_new,-1);
 #endif
diff -uNr ruby-ldap-0.8.3.orig/ldap.c ruby-ldap-0.8.3/ldap.c
--- ruby-ldap-0.8.3.orig/ldap.c	2003-11-15 20:55:14.000000000 -0800
+++ ruby-ldap-0.8.3/ldap.c	2004-11-13 01:01:38.245975328 -0800
@@ -479,6 +479,11 @@
 #endif
 #undef rb_ldap_define_auth_method
 
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+  rb_define_const(rb_mLDAP,"LDAP_CONTROL_PAGEDRESULTS",
+		  rb_str_new2(LDAP_CONTROL_PAGEDRESULTS));
+#endif
+
 #define rb_ldap_define_const(c) rb_define_const(rb_mLDAP,#c,INT2NUM(c))
   rb_ldap_define_const(LDAP_MOD_ADD);
   rb_ldap_define_const(LDAP_MOD_DELETE);
diff -uNr ruby-ldap-0.8.3.orig/misc.c ruby-ldap-0.8.3/misc.c
--- ruby-ldap-0.8.3.orig/misc.c	2004-11-13 01:09:31.213073400 -0800
+++ ruby-ldap-0.8.3/misc.c	2004-11-13 01:01:38.246975176 -0800
@@ -94,6 +94,40 @@
   }
 }
 
+/* Identical to rb_ldap_control_new, but does not define a routine with which
+   to free memory. This should be called only by rb_ldap_parse_result().
+ */
+VALUE
+rb_ldap_control_new2(LDAPControl *ctl)
+{
+  int len;
+  VALUE val, oid, critical;
+
+  if( !ctl ){
+    return Qnil;
+  }
+  else{
+    return Data_Wrap_Struct(rb_cLDAP_Control, 0, 0, ctl);
+  }
+}
+
+/* This is called by #initialize_copy and is using for duping/cloning. */
+VALUE
+rb_ldap_control_copy(VALUE copy, VALUE orig)
+{
+  LDAPControl *orig_ctl, *copy_ctl;
+
+  /*
+  rb_raise(rb_eTypeError, "can't dup/clone LDAP::Control class");
+  */
+
+  Data_Get_Struct(orig, LDAPControl, orig_ctl);
+  Data_Get_Struct(copy, LDAPControl, copy_ctl);
+  memcpy(copy_ctl, orig_ctl, (size_t)sizeof(LDAPControl));
+
+  return copy;
+}
+
 static VALUE
 rb_ldap_control_s_allocate(VALUE klass)
 {
@@ -382,6 +416,7 @@
 			     rb_ldap_control_s_new, -1);
 #endif
   rb_define_method(rb_cLDAP_Control, "initialize", rb_ldap_control_initialize, -1);
+  rb_define_method(rb_cLDAP_Control, "initialize_copy", rb_ldap_control_copy, 1);
   rb_define_method(rb_cLDAP_Control, "inspect", rb_ldap_control_inspect, 0);
   rb_define_method(rb_cLDAP_Control, "oid", rb_ldap_control_oid, -1);
   rb_define_method(rb_cLDAP_Control, "oid=", rb_ldap_control_oid, -1);
