diff --git a/libraries/liblutil/ntservice.c b/libraries/liblutil/ntservice.c
index 5672dedc120b93619cadfefa40adb16e8f760285..f07fb7cb2093e19187a7075dbf514cc020bfc98b 100644
--- a/libraries/liblutil/ntservice.c
+++ b/libraries/liblutil/ntservice.c
@@ -315,7 +315,7 @@ void *getRegParam( char *svc, char *value )
 	return (void*)NULL;
 }
 
-void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, short port, int udp )
+void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *urls )
 {
 	char *Inserts[5];
 	WORD i = 0, j;
@@ -326,12 +326,11 @@ void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, short po
 	Inserts[i] = (char *)malloc( 20 );
 	itoa( slap_debug, Inserts[i++], 10 );
 	Inserts[i++] = ldap_pvt_strdup( configfile );
-	Inserts[i] = (char *)malloc( 20 );
-	itoa( port, Inserts[i++], 10 );
-	Inserts[i++] = ldap_pvt_strdup( udp ? "udp" : "tcp" );
+	Inserts[i++] = ldap_pvt_strdup( urls );
 	Inserts[i++] = ldap_pvt_strdup( is_NT_Service ? "svc" : "cmd" );
 
-	ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, MSG_SLAPD_STARTED, NULL, i, 0, Inserts, NULL );
+	ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
+		MSG_SLAPD_STARTED, NULL, i, 0, Inserts, NULL );
 
 	for ( j = 0; j < i; j++ )
 		ldap_memfree( Inserts[j] );
@@ -345,7 +344,8 @@ void LogSlapdStoppedEvent( char *svc )
 	HANDLE hEventLog;
 	
 	hEventLog = RegisterEventSource( NULL, svc );
-	ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0, MSG_SLAPD_STOPPED, NULL, 0, 0, NULL, NULL );
+	ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
+		MSG_SLAPD_STOPPED, NULL, 0, 0, NULL, NULL );
 	DeregisterEventSource( hEventLog );
 }
 
diff --git a/libraries/liblutil/slapdmsg.mc b/libraries/liblutil/slapdmsg.mc
index 2c6c88367c37de52b3ccbd0615e26632f26032ff..694a93efb64e24ca658372aa77ffe194635224aa 100644
--- a/libraries/liblutil/slapdmsg.mc
+++ b/libraries/liblutil/slapdmsg.mc
@@ -15,7 +15,7 @@ Severity=Informational
 SymbolicName=MSG_SLAPD_STARTED
 Facility=Application
 Language=English
-OpenLDAP SLAPD service started. debuglevel=%1, conffile=%2, port=%3, ip=%4, mode=%5
+OpenLDAP SLAPD service started. debuglevel=%1, conffile=%2, urls=%3, mode=%4
 .
 
 
diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c
index 5d1eedb4401e8e8b06d8edf397190b25fd6dbc8d..cd3dad0018bc84f78df65780842e6240fb71b932 100644
--- a/servers/slapd/acl.c
+++ b/servers/slapd/acl.c
@@ -123,15 +123,17 @@ acl_get_applicable(
 
 	/* check for a backend-specific acl that matches the entry */
 	for ( i = 1, a = be->be_acl; a != NULL; a = a->acl_next, i++ ) {
-		if (a->acl_dnpat != NULL) {
+		if (a->acl_dn_pat != NULL) {
 			Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n", 
-				i, a->acl_dnpat, (int) a->acl_dnre.re_nsub);
+				i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub);
 
-			if (regexec(&a->acl_dnre, edn, nmatch, matches, 0))
+			if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
 				continue;
-			else
+
+			} else {
 				Debug( LDAP_DEBUG_TRACE, "=> acl_get:[%d]  backend ACL match\n",
 					i, 0, 0);
+			}
 		}
 
 		if ( a->acl_filter != NULL ) {
@@ -154,12 +156,13 @@ acl_get_applicable(
 
 	/* check for a global acl that matches the entry */
 	for ( i = 1, a = global_acl; a != NULL; a = a->acl_next, i++ ) {
-		if (a->acl_dnpat != NULL) {
-			Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n", 
-				i, a->acl_dnpat, (int) a->acl_dnre.re_nsub);
+		if (a->acl_dn_pat != NULL) {
+			Debug( LDAP_DEBUG_TRACE, "=> dn pat: [%d] %s nsub: %d\n", 
+				i, a->acl_dn_pat, (int) a->acl_dn_re.re_nsub);
 
-			if (regexec(&a->acl_dnre, edn, nmatch, matches, 0)) {
+			if (regexec(&a->acl_dn_re, edn, nmatch, matches, 0)) {
 				continue;
+
 			} else {
 				Debug( LDAP_DEBUG_TRACE, "=> acl_get: [%d] global ACL match\n",
 					i, 0, 0);
@@ -213,8 +216,6 @@ acl_access_allowed(
 {
 	int		i;
 	Access	*b;
-	Attribute	*at;
-	struct berval	bv;
 	int		default_access;
 
 	Debug( LDAP_DEBUG_ACL,
@@ -243,83 +244,97 @@ acl_access_allowed(
 		return( default_access >= access );
 	}
 
-	if ( op->o_ndn != NULL ) {
-		bv.bv_val = op->o_ndn;
-		bv.bv_len = strlen( bv.bv_val );
-	}
-
 	for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) {
-		if ( b->a_dnpat != NULL ) {
-			Debug( LDAP_DEBUG_TRACE, "<= check a_dnpat: %s\n",
-				b->a_dnpat, 0, 0);
+		/* AND <who> clauses */
+		if ( b->a_dn_pat != NULL ) {
+			Debug( LDAP_DEBUG_TRACE, "<= check a_dn_pat: %s\n",
+				b->a_dn_pat, 0, 0);
 			/*
 			 * if access applies to the entry itself, and the
 			 * user is bound as somebody in the same namespace as
 			 * the entry, OR the given dn matches the dn pattern
 			 */
-			if ( strcasecmp( b->a_dnpat, "anonymous" ) == 0 && 
-				(op->o_ndn == NULL || *(op->o_ndn) == '\0' ) ) 
+			if ( strcasecmp( b->a_dn_pat, "anonymous" ) == 0 ) {
+				if (op->o_ndn != NULL && op->o_ndn[0] != '\0' ) {
+					continue;
+				}
+
+			} else if ( strcasecmp( b->a_dn_pat, "self" ) == 0 ) {
+				if( op->o_ndn == NULL || op->o_ndn[0] == '\0' ) {
+					continue;
+				}
+				
+				if ( e->e_dn == NULL || strcmp( edn, op->o_ndn ) != 0 ) {
+					continue;
+				}
+
+			} else if ( strcmp( b->a_dn_pat, ".*" ) != 0 &&
+				!regex_matches( b->a_dn_pat, op->o_ndn, edn, matches ) )
 			{
-				Debug( LDAP_DEBUG_ACL,
-				"<= acl_access_allowed: matched by clause #%d access %s\n",
-				    i, ACL_GRANT(b->a_access, access)
-						? "granted" : "denied", 0 );
+				continue;
+			}
+		}
 
-				return ACL_GRANT(b->a_access, access );
+		if ( b->a_url_pat != NULL ) {
+			Debug( LDAP_DEBUG_ARGS, "<= check a_url_pat: %s\n",
+				b->a_url_pat, 0, 0 );
 
-			} else if ( strcasecmp( b->a_dnpat, "self" ) == 0 && 
-				op->o_ndn != NULL && *(op->o_ndn) && e->e_dn != NULL ) 
+			if ( strcmp( b->a_url_pat, ".*" ) != 0 &&
+				!regex_matches( b->a_url_pat, conn->c_listener_url,
+				edn, matches ) ) 
 			{
-				if ( strcmp( edn, op->o_ndn ) == 0 ) {
-					Debug( LDAP_DEBUG_ACL,
-					"<= acl_access_allowed: matched by clause #%d access %s\n",
-					    i, ACL_GRANT(b->a_access, access)
-							? "granted" : "denied", 0 );
+				continue;
+			}
+		}
 
-					return ACL_GRANT(b->a_access, access );
-				}
-			} else {
-				if ( regex_matches( b->a_dnpat, op->o_ndn, edn, matches ) ) {
-					Debug( LDAP_DEBUG_ACL,
-				    "<= acl_access_allowed: matched by clause #%d access %s\n",
-				    i, ACL_GRANT(b->a_access, access)
-						? "granted" : "denied", 0 );
+		if ( b->a_domain_pat != NULL ) {
+			Debug( LDAP_DEBUG_ARGS, "<= check a_domain_pat: %s\n",
+				b->a_domain_pat, 0, 0 );
 
-					return ACL_GRANT(b->a_access, access );
-				}
+			if ( strcmp( b->a_domain_pat, ".*" ) != 0 &&
+				!regex_matches( b->a_domain_pat, conn->c_peer_domain,
+				edn, matches ) ) 
+			{
+				continue;
 			}
 		}
-		if ( b->a_addrpat != NULL ) {
-			if ( regex_matches( b->a_addrpat, conn->c_client_addr,
+
+		if ( b->a_peername_pat != NULL ) {
+			Debug( LDAP_DEBUG_ARGS, "<= check a_peername_path: %s\n",
+				b->a_peername_pat, 0, 0 );
+
+			if ( strcmp( b->a_peername_pat, ".*" ) != 0 &&
+				!regex_matches( b->a_peername_pat, conn->c_peer_name,
 				edn, matches ) )
 			{
-				Debug( LDAP_DEBUG_ACL,
-				    "<= acl_access_allowed: matched by clause #%d access %s\n",
-				    i, ACL_GRANT(b->a_access, access)
-						? "granted" : "denied", 0 );
-
-				return ACL_GRANT(b->a_access, access );
+				continue;
 			}
 		}
-		if ( b->a_domainpat != NULL ) {
-			Debug( LDAP_DEBUG_ARGS, "<= check a_domainpath: %s\n",
-				b->a_domainpat, 0, 0 );
-			if ( regex_matches( b->a_domainpat, conn->c_client_name,
-				edn, matches ) ) 
-			{
-				Debug( LDAP_DEBUG_ACL,
-				    "<= acl_access_allowed: matched by clause #%d access %s\n",
-				    i, ACL_GRANT(b->a_access, access)
-						? "granted" : "denied", 0 );
 
-				return ACL_GRANT(b->a_access, access );
+		if ( b->a_sockname_pat != NULL ) {
+			Debug( LDAP_DEBUG_ARGS, "<= check a_sockname_path: %s\n",
+				b->a_sockname_pat, 0, 0 );
+
+			if ( strcmp( b->a_sockname_pat, ".*" ) != 0 &&
+				!regex_matches( b->a_sockname_pat, conn->c_sock_name,
+				edn, matches ) )
+			{
+				continue;
 			}
 		}
-		if ( b->a_dnattr != NULL && op->o_ndn != NULL ) {
-			Debug( LDAP_DEBUG_ARGS, "<= check a_dnattr: %s\n",
-				b->a_dnattr, 0, 0);
-			/* see if asker is listed in dnattr */
-			if ( (at = attr_find( e->e_attrs, b->a_dnattr )) != NULL && 
+
+		if ( b->a_dn_at != NULL && op->o_ndn != NULL ) {
+			Attribute	*at;
+			struct berval	bv;
+
+			Debug( LDAP_DEBUG_ARGS, "<= check a_dn_at: %s\n",
+				b->a_dn_at, 0, 0);
+
+			bv.bv_val = op->o_ndn;
+			bv.bv_len = strlen( bv.bv_val );
+
+			/* see if asker is listed in dnattr */ 
+			if ( (at = attr_find( e->e_attrs, b->a_dn_at )) != NULL &&
 				value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 )
 			{
 				if ( ACL_IS_SELF(b->a_access) && 
@@ -328,30 +343,15 @@ acl_access_allowed(
 					continue;
 				}
 
-				Debug( LDAP_DEBUG_ACL,
-				    "<= acl_acces_allowed: matched by clause #%d access %s\n",
-				    i, ACL_GRANT(b->a_access, access)
-						? "granted" : "denied", 0 );
-
-				return ACL_GRANT(b->a_access, access );
-			}
-
 			/* asker not listed in dnattr - check for self access */
-			if ( ! ACL_IS_SELF(b->a_access) || val == NULL ||
+			} else if ( ! ACL_IS_SELF(b->a_access) || val == NULL ||
 				value_cmp( &bv, val, at->a_syntax, 2 ) != 0 )
 			{
 				continue;
 			}
-
-			Debug( LDAP_DEBUG_ACL,
-				"<= acl_access_allowed: matched by clause #%d (self) access %s\n",
-			    i, ACL_GRANT(b->a_access, access)
-					? "granted" : "denied", 0 );
-
-			return ACL_GRANT(b->a_access, access );
 		}
 
-		if ( b->a_group != NULL && op->o_ndn != NULL ) {
+		if ( b->a_group_pat != NULL && op->o_ndn != NULL ) {
 			char buf[1024];
 
 			/* b->a_group is an unexpanded entry name, expanded it should be an 
@@ -359,18 +359,23 @@ acl_access_allowed(
 			 * the values in the attribute group
 			 */
 			/* see if asker is listed in dnattr */
-			string_expand(buf, sizeof(buf), b->a_group, edn, matches);
+			string_expand(buf, sizeof(buf), b->a_group_pat, edn, matches);
 			(void) dn_normalize_case(buf);
 
 			if (backend_group(be, e, buf, op->o_ndn,
-				b->a_group_oc, b->a_group_at) == 0)
+				b->a_group_oc, b->a_group_at) != 0)
 			{
-				Debug( LDAP_DEBUG_ACL,
-					"<= acl_access_allowed: matched by clause #%d (group) access granted\n",
-					i, 0, 0 );
-				return ACL_GRANT(b->a_access, access );
+				continue;
 			}
 		}
+
+		Debug( LDAP_DEBUG_ACL,
+			"<= acl_access_allowed: matched by clause #%d access %s\n",
+			i,
+			ACL_GRANT(b->a_access, access) ? "granted" : "denied",
+			0 );
+
+		return ACL_GRANT(b->a_access, access );
 	}
 
 	Debug( LDAP_DEBUG_ACL,
diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c
index f527199b083f003ed5f703eda67a83728e6a9b0d..0aaf463d1f0a34de96574a955e55270ffe9e45a7 100644
--- a/servers/slapd/aclparse.c
+++ b/servers/slapd/aclparse.c
@@ -109,18 +109,7 @@ parse_acl(
 				}
 
 				if ( strcasecmp( argv[i], "*" ) == 0 ) {
-					int e;
-					if ((e = regcomp( &a->acl_dnre, ".*",
-						REG_EXTENDED|REG_ICASE)))
-					{
-						char buf[512];
-						regerror(e, &a->acl_dnre, buf, sizeof(buf));
-						fprintf( stderr,
-							"%s: line %d: regular expression \"%s\" bad because of %s\n",
-							fname, lineno, right, buf );
-						acl_usage();
-					}
-					a->acl_dnpat = ch_strdup( ".*" );
+					a->acl_dn_pat = ch_strdup( ".*" );
 					continue;
 				}
 
@@ -140,27 +129,30 @@ parse_acl(
 						    fname, lineno, right );
 						acl_usage();
 					}
+
 				} else if ( strcasecmp( left, "dn" ) == 0 ) {
 					int e;
-					if ((e = regcomp(&a->acl_dnre, right,
+
+					if ((e = regcomp(&a->acl_dn_re, right,
 						REG_EXTENDED|REG_ICASE))) {
 						char buf[512];
-						regerror(e, &a->acl_dnre, buf, sizeof(buf));
+						regerror(e, &a->acl_dn_re, buf, sizeof(buf));
 						fprintf( stderr,
 				"%s: line %d: regular expression \"%s\" bad because of %s\n",
 							fname, lineno, right, buf );
 						acl_usage();
 
 					} else {
-						a->acl_dnpat = dn_upcase(ch_strdup( right ));
+						a->acl_dn_pat = ch_strdup( right );
 					}
-				} else if ( strncasecmp( left, "attr", 4 )
-				    == 0 ) {
+
+				} else if ( strncasecmp( left, "attr", 4 ) == 0 ) {
 					char	**alist;
 
 					alist = str2charray( right, "," );
 					charray_merge( &a->acl_attrs, alist );
 					charray_free( alist );
+
 				} else {
 					fprintf( stderr,
 						"%s: line %d: expecting <what> got \"%s\"\n",
@@ -191,87 +183,148 @@ parse_acl(
 			}
 
 			/* get <who> */
-			split( argv[i], '=', &left, &right );
-			if ( strcasecmp( argv[i], "*" ) == 0 ) {
-				b->a_dnpat = ch_strdup( ".*" );
-			} else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
-				b->a_dnpat = ch_strdup( "anonymous" );
-			} else if ( strcasecmp( argv[i], "self" ) == 0 ) {
-				b->a_dnpat = ch_strdup( "self" );
-			} else if ( strcasecmp( left, "dn" ) == 0 ) {
-				regtest(fname, lineno, right);
-				b->a_dnpat = dn_upcase( ch_strdup( right ) );
-			} else if ( strcasecmp( left, "dnattr" ) == 0 ) {
-				b->a_dnattr = ch_strdup( right );
-
-			} else if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) {
-				char *name = NULL;
-				char *value = NULL;
-
-				/* format of string is "group/objectClassValue/groupAttrName" */
-				if ((value = strchr(left, '/')) != NULL) {
-					*value++ = '\0';
-					if (value && *value
-						&& (name = strchr(value, '/')) != NULL)
-					{
-						*name++ = '\0';
+			for ( ; i < argc; i++ ) {
+				char* pat;
+				split( argv[i], '=', &left, &right );
+
+				if ( strcasecmp( argv[i], "*" ) == 0 ) {
+					pat = ch_strdup( ".*" );
+				} else if ( strcasecmp( argv[i], "anonymous" ) == 0 ) {
+					pat = ch_strdup( "anonymous" );
+				} else if ( strcasecmp( argv[i], "self" ) == 0 ) {
+					pat = ch_strdup( "self" );
+				} else if ( strcasecmp( left, "dn" ) == 0 ) {
+					regtest(fname, lineno, right);
+					pat = ch_strdup( right );
+				}
+
+				if( pat != NULL ) {
+					if( b->a_dn_pat != NULL ) {
+						fprintf( stderr,
+						    "%s: line %d: dn pattern already specified.\n",
+						    fname, lineno );
+						acl_usage();
+					}
+
+					b->a_dn_pat = pat;
+					continue;
+				}
+
+				if ( strcasecmp( left, "dnattr" ) == 0 ) {
+					if( b->a_dn_pat != NULL ) {
+						fprintf( stderr,
+							"%s: line %d: dnaddr already specified.\n",
+							fname, lineno );
+						acl_usage();
 					}
+
+					b->a_dn_at = ch_strdup( right );
+					continue;
 				}
 
-				regtest(fname, lineno, right);
-				b->a_group = dn_upcase(ch_strdup( right ));
+				if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) {
+					char *name = NULL;
+					char *value = NULL;
 
-				if (value && *value) {
-					b->a_group_oc = ch_strdup(value);
-					*--value = '/';
-				} else {
-					b->a_group_oc = ch_strdup("groupOfNames");
+					if( b->a_group_pat != NULL ) {
+						fprintf( stderr,
+							"%s: line %d: group pattern already specified.\n",
+							fname, lineno );
+						acl_usage();
+					}
+
+					/* format of string is "group/objectClassValue/groupAttrName" */
+					if ((value = strchr(left, '/')) != NULL) {
+						*value++ = '\0';
+						if (value && *value
+							&& (name = strchr(value, '/')) != NULL)
+						{
+							*name++ = '\0';
+						}
+					}
 
-					if (name && *name) {
-						b->a_group_at = ch_strdup(name);
-						*--name = '/';
+					regtest(fname, lineno, right);
+					b->a_group_pat = ch_strdup( right );
 
+					if (value && *value) {
+						b->a_group_oc = ch_strdup(value);
+						*--value = '/';
 					} else {
-						b->a_group_at = ch_strdup("member");
+						b->a_group_oc = ch_strdup("groupOfNames");
+
+						if (name && *name) {
+							b->a_group_at = ch_strdup(name);
+							*--name = '/';
+
+						} else {
+							b->a_group_at = ch_strdup("member");
+						}
 					}
+					continue;
 				}
 
-			} else if ( strcasecmp( left, "domain" ) == 0 ) {
-				char	*s;
-				regtest(fname, lineno, right);
-				b->a_domainpat = ch_strdup( right );
+				if ( strcasecmp( left, "peername" ) == 0 ) {
+					if( b->a_peername_pat != NULL ) {
+						fprintf( stderr,
+							"%s: line %d: peername pattern already specified.\n",
+							fname, lineno );
+						acl_usage();
+					}
 
-				/* normalize the domain */
-				for ( s = b->a_domainpat; *s; s++ ) {
-					*s = TOLOWER( (unsigned char) *s );
+					regtest(fname, lineno, right);
+					b->a_peername_pat = ch_strdup( right );
+					continue;
 				}
-			} else if ( strcasecmp( left, "addr" ) == 0 ) {
-				regtest(fname, lineno, right);
-				b->a_addrpat = ch_strdup( right );
-			} else {
-				fprintf( stderr,
-				    "%s: line %d: expecting <who> got \"%s\"\n",
-				    fname, lineno, left );
-				acl_usage();
-			}
 
-			if ( ++i == argc ) {
-				fprintf( stderr,
-			    "%s: line %d: premature eol: expecting <access>\n",
-				    fname, lineno );
-				acl_usage();
-			}
+				if ( strcasecmp( left, "sockname" ) == 0 ) {
+					if( b->a_sockname_pat != NULL ) {
+						fprintf( stderr,
+							"%s: line %d: sockname pattern already specified.\n",
+							fname, lineno );
+						acl_usage();
+					}
 
-			/* get <access> */
-			split( argv[i], '=', &left, &right );
-			if ( ACL_IS_INVALID(ACL_SET(b->a_access,str2access( left ))) ) {
-				fprintf( stderr,
-			    "%s: line %d: expecting <access> got \"%s\"\n",
-				    fname, lineno, left );
-				acl_usage();
-			}
-			access_append( &a->acl_access, b );
+					regtest(fname, lineno, right);
+					b->a_sockname_pat = ch_strdup( right );
+					continue;
+				}
 
+				if ( strcasecmp( left, "domain" ) == 0 ) {
+					if( b->a_domain_pat != NULL ) {
+						fprintf( stderr,
+							"%s: line %d: domain pattern already specified.\n",
+							fname, lineno );
+						acl_usage();
+					}
+
+					regtest(fname, lineno, right);
+					b->a_domain_pat = ch_strdup( right );
+					continue;
+				}
+
+				if ( strcasecmp( left, "url" ) == 0 ) {
+					if( b->a_url_pat != NULL ) {
+						fprintf( stderr,
+							"%s: line %d: url pattern already specified.\n",
+							fname, lineno );
+						acl_usage();
+					}
+
+					regtest(fname, lineno, right);
+					b->a_url_pat = ch_strdup( right );
+					continue;
+				}
+
+				/* get <access> */
+				if ( ACL_IS_INVALID(ACL_SET(b->a_access, str2access( left ))) ) {
+					fprintf( stderr,
+					"%s: line %d: expecting <access> got \"%s\"\n",
+						fname, lineno, left );
+					acl_usage();
+				}
+				access_append( &a->acl_access, b );
+				break;
+			}
 		} else {
 			fprintf( stderr,
 		    "%s: line %d: expecting \"to\" or \"by\" got \"%s\"\n",
@@ -377,9 +430,10 @@ acl_usage( void )
 		"<what> ::= * | [dn=<regex>] [filter=<ldapfilter>] [attrs=<attrlist>]\n"
 		"<attrlist> ::= <attr> | <attr> , <attrlist>\n"
 		"<attr> ::= <attrname> | entry | children\n"
-		"<who> ::= * | anonymous | self | dn=<regex> | addr=<regex>\n"
-			"\t| domain=<regex> | dnattr=<dnattrname>\n"
-			"\t| group[/<objectclass>[/<attrname>]]=<regex>\n"
+		"<who> ::= * | anonymous | self | dn=<regex>\n"
+			"\t| dnattr=<attrname> | group[/<objectclass>[/<attrname>]]=<regex>\n"
+			"\t| peername=<regex> | sockname=<regex>\n"
+			"\t| domain=<regex> | sockurl=<regex>\n"
 		"<access> ::= [self]{none|auth|compare|search|read|write}\n"
 		);
 	exit( 1 );
@@ -424,29 +478,49 @@ print_access( Access *b )
 {
 	fprintf( stderr, "\tby" );
 
-	if ( b->a_dnpat != NULL ) {
-		if( strcmp(b->a_dnpat, "anonymous") == 0 ) {
+	if ( b->a_dn_pat != NULL ) {
+		if( strcmp(b->a_dn_pat, "anonymous") == 0 ) {
 			fprintf( stderr, " anonymous" );
-		} else if( strcmp(b->a_dnpat, "self") == 0 ) {
+
+		} else if( strcmp(b->a_dn_pat, "self") == 0 ) {
 			fprintf( stderr, " self" );
+
 		} else {
-			fprintf( stderr, " dn=%s", b->a_dnpat );
+			fprintf( stderr, " dn=%s", b->a_dn_pat );
 		}
-	} else if ( b->a_addrpat != NULL ) {
-		fprintf( stderr, " addr=%s", b->a_addrpat );
-	} else if ( b->a_domainpat != NULL ) {
-		fprintf( stderr, " domain=%s", b->a_domainpat );
-	} else if ( b->a_dnattr != NULL ) {
-		fprintf( stderr, " dnattr=%s", b->a_dnattr );
-	} else if ( b->a_group != NULL ) {
-		fprintf( stderr, " group: %s", b->a_group );
+	}
+
+	if ( b->a_dn_at != NULL ) {
+		fprintf( stderr, " dnattr=%s", b->a_dn_at );
+	}
+
+	if ( b->a_group_pat != NULL ) {
+		fprintf( stderr, " group: %s", b->a_group_pat );
+
 		if ( b->a_group_oc ) {
 			fprintf( stderr, " objectClass: %s", b->a_group_oc );
+
 			if ( b->a_group_at ) {
 				fprintf( stderr, " attributeType: %s", b->a_group_at );
 			}
 		}
     }
+
+	if ( b->a_peername_pat != NULL ) {
+		fprintf( stderr, " peername=%s", b->a_peername_pat );
+	}
+	if ( b->a_sockname_pat != NULL ) {
+		fprintf( stderr, " sockname=%s", b->a_sockname_pat );
+	}
+
+	if ( b->a_domain_pat != NULL ) {
+		fprintf( stderr, " domain=%s", b->a_domain_pat );
+	}
+
+	if ( b->a_url_pat != NULL ) {
+		fprintf( stderr, " url=%s", b->a_url_pat );
+	}
+
 	fprintf( stderr, "\n" );
 }
 
@@ -464,9 +538,9 @@ print_acl( AccessControl *a )
 		fprintf(  stderr," filter=" );
 		filter_print( a->acl_filter );
 	}
-	if ( a->acl_dnpat != NULL ) {
+	if ( a->acl_dn_pat != NULL ) {
 		fprintf( stderr, " dn=" );
-		fprintf( stderr, a->acl_dnpat );
+		fprintf( stderr, a->acl_dn_pat );
 	}
 	if ( a->acl_attrs != NULL ) {
 		int	first = 1;
diff --git a/servers/slapd/attr.c b/servers/slapd/attr.c
index 014fe649de39798a882c67bb4d6b0cbbb5fbcb2d..8e3112200bf99c96797bc4776f39c2869615172d 100644
--- a/servers/slapd/attr.c
+++ b/servers/slapd/attr.c
@@ -40,15 +40,9 @@ attr_free( Attribute *a )
 char *
 attr_normalize( char *s )
 {
-	char	*save;
-
 	assert( s != NULL );
 
-	for ( save = s; *s; s++ ) {
-		*s = TOLOWER( (unsigned char) *s );
-	}
-
-	return( save );
+	return( str2lower( s ) );
 }
 
 /*
diff --git a/servers/slapd/back-passwd/search.c b/servers/slapd/back-passwd/search.c
index 231d6648692ed6f2abc99cacc1306265f084ef30..cb1b9f4b29daaa0f23a935ba38bb81c9e1232fdd 100644
--- a/servers/slapd/back-passwd/search.c
+++ b/servers/slapd/back-passwd/search.c
@@ -183,9 +183,7 @@ passwd_back_search(
 			goto done;
 		}
 
-		for( s = user; *s ; s++ ) {
-			*s = TOLOWER( *s );
-		}
+		user = str2lower( user );
 
 		if ( (pw = getpwnam( user )) == NULL ) {
 			matched = parent;
@@ -270,8 +268,7 @@ pw2entry( Backend *be, struct passwd *pw, char *rdn )
 			strncpy(buf, val.bv_val, i);
 			s = buf+i;
 			strcpy(s, pw->pw_name);
-			if (islower(*s))
-				*s = toupper(*s);
+			*s = TOUPPER(*s);
 			strcat(s, val.bv_val+i+1);
 			val.bv_val = buf;
 		}
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index f05fd086916cf01fa49ed3ec74e2f07de255831d..5ffb42cfff054e43c005155d4b0a7be31726f3ad 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -222,7 +222,7 @@ read_config( char *fname )
 				char *dn = ch_strdup( cargv[1] );
 				(void) dn_normalize( dn );
 				charray_add( &be->be_suffix, dn );
-				(void) dn_upcase( dn );
+				(void) str2upper( dn );
 				charray_add( &be->be_nsuffix, dn );
 				free( dn );
 			}
diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
index a5476ad0b3022e9588698d6323cbfbdd06c5c479..036dde765f4a998cf8642098941b1f6e1c720f20 100644
--- a/servers/slapd/connection.c
+++ b/servers/slapd/connection.c
@@ -271,14 +271,21 @@ static void connection_return( Connection *c )
 
 long connection_init(
 	ber_socket_t s,
-	const char* name,
-	const char* addr,
+	const char* url,
+	const char* dnsname,
+	const char* peername,
+	const char* sockname,
 	int use_tls )
 {
 	unsigned long id;
 	Connection *c;
+
 	assert( connections != NULL );
 
+	assert( dnsname != NULL );
+	assert( peername != NULL );
+	assert( sockname != NULL );
+
 #ifndef HAVE_TLS
 	assert( !use_tls );
 #endif
@@ -341,8 +348,12 @@ long connection_init(
     if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
         c->c_dn = NULL;
         c->c_cdn = NULL;
-        c->c_client_name = NULL;
-        c->c_client_addr = NULL;
+
+		c->c_listener_url = NULL;
+		c->c_peer_domain = NULL;
+        c->c_peer_name = NULL;
+        c->c_sock_name = NULL;
+
         c->c_ops = NULL;
         c->c_pending_ops = NULL;
 		c->c_authmech = NULL;
@@ -363,15 +374,19 @@ long connection_init(
     assert( c->c_struct_state == SLAP_C_UNUSED );
     assert(	c->c_dn == NULL );
     assert(	c->c_cdn == NULL );
-    assert( c->c_client_name == NULL );
-    assert( c->c_client_addr == NULL );
+    assert( c->c_listener_url == NULL );
+    assert( c->c_peer_domain == NULL );
+    assert( c->c_peer_name == NULL );
+    assert( c->c_sock_name == NULL );
     assert( c->c_ops == NULL );
     assert( c->c_pending_ops == NULL );
 	assert( c->c_authmech == NULL );
 	assert( c->c_authstate == NULL );
 
-    c->c_client_name = ch_strdup( name == NULL ? "" : name );
-    c->c_client_addr = ch_strdup( addr );
+	c->c_listener_url = ch_strdup( url  );
+	c->c_peer_domain = ch_strdup( dnsname  );
+    c->c_peer_name = ch_strdup( peername  );
+    c->c_sock_name = ch_strdup( sockname );
 
     c->c_n_ops_received = 0;
     c->c_n_ops_executing = 0;
@@ -389,8 +404,8 @@ long connection_init(
 
     if( ber_pvt_sb_set_nonblock( c->c_sb, 1 ) < 0 ) {
         Debug( LDAP_DEBUG_ANY,
-            "connection_init(%d, %s, %s): set nonblocking failed\n",
-            s, c->c_client_name, c->c_client_addr);
+            "connection_init(%d, %s): set nonblocking failed\n",
+            s, c->c_peer_name,0 );
     }
 
     id = c->c_connid = conn_nextid++;
@@ -439,13 +454,21 @@ connection_destroy( Connection *c )
 		free(c->c_cdn);
 		c->c_cdn = NULL;
 	}
-	if(c->c_client_name != NULL) {
-		free(c->c_client_name);
-		c->c_client_name = NULL;
+	if(c->c_listener_url != NULL) {
+		free(c->c_listener_url);
+		c->c_listener_url = NULL;
+	}
+	if(c->c_peer_domain != NULL) {
+		free(c->c_peer_domain);
+		c->c_peer_domain = NULL;
+	}
+	if(c->c_peer_name != NULL) {
+		free(c->c_peer_name);
+		c->c_peer_name = NULL;
 	}
-	if(c->c_client_addr != NULL) {
-		free(c->c_client_addr);
-		c->c_client_addr = NULL;
+	if(c->c_sock_name != NULL) {
+		free(c->c_sock_name);
+		c->c_sock_name = NULL;
 	}
 	if(c->c_authmech != NULL ) {
 		free(c->c_authmech);
diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c
index a007fa1f5e8976536ee454fd65abd419820ceae4..3de1106ecf457f5366613331d58cb13993508422 100644
--- a/servers/slapd/daemon.c
+++ b/servers/slapd/daemon.c
@@ -26,6 +26,7 @@ ber_socket_t dtblsize;
 
 typedef struct slap_listener {
 	char* sl_url;
+	char* sl_name;
 #ifdef HAVE_TLS
 	int		sl_is_tls;
 #endif
@@ -204,6 +205,7 @@ open_listener(
 	Listener l;
 	Listener *li;
 	LDAPURLDesc *lud;
+	char *s;
 
 	rc = ldap_url_parse( url, &lud );
 
@@ -235,6 +237,8 @@ open_listener(
 	}
 #endif
 
+	port = lud->lud_port;
+
 	(void) memset( (void*) &l.sl_addr, '\0', sizeof(l.sl_addr) );
 
 	l.sl_addr.sin_family = AF_INET;
@@ -248,20 +252,12 @@ open_listener(
 	} else {
 		/* host or address was specified */
 
-		if( isdigit( lud->lud_host[0] ) ) {
 #ifdef HAVE_WINSOCK
-			if(!(l.sl_addr.sin_addr.S_un.S_addr = inet_addr(lud->lud_host)))
+		if((l.sl_addr.sin_addr.S_un.S_addr = inet_addr(lud->lud_host)) == INADDR_NONE)
 #else
-			if(!inet_aton(lud->lud_host, &l.sl_addr.sin_addr))
+		if(!inet_aton(lud->lud_host, &l.sl_addr.sin_addr))
 #endif  
-			{
-				Debug( LDAP_DEBUG_ANY, "invalid address (%s) in URL: %s",
-					lud->lud_host, url, 0);
-				ldap_free_urldesc( lud );
-				return NULL;
-			}
-
-		} else {
+		{
 			struct hostent *he = gethostbyname( lud->lud_host );
 			if( he == NULL ) {
 				Debug( LDAP_DEBUG_ANY, "invalid host (%s) in URL: %s",
@@ -348,6 +344,11 @@ open_listener(
 
 	l.sl_url = ch_strdup( url );
 
+	l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
+	s = inet_ntoa( l.sl_addr.sin_addr );
+	sprintf( l.sl_name, "IP=%s:%d",
+		s != NULL ? s : "unknown" , port );
+
 	li = ch_malloc( sizeof( Listener ) );
 	*li = l;
 
@@ -505,9 +506,6 @@ slapd_daemon_task(
 		struct timeval		zero;
 		struct timeval		*tvp;
 
-		char	*client_name;
-		char	*client_addr;
-
 		if( global_idletimeout > 0 && difftime(
 			last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
 			now ) < 0 )
@@ -624,6 +622,11 @@ slapd_daemon_task(
 			socklen_t len = sizeof(from);
 			long id;
 
+			char	*dnsname;
+			char	*peeraddr;
+
+			char	peername[sizeof("IP:255.255.255.255:65336")];
+
 			if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
 				continue;
 
@@ -669,47 +672,50 @@ slapd_daemon_task(
 				(long) s, 0, 0 );
 
 			len = sizeof(from);
-			if ( getpeername( s, (struct sockaddr *) &from, &len ) == 0 ) {
-				client_addr = inet_ntoa( from.sin_addr );
 
-#if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
-				hp = gethostbyaddr( (char *)
-				    &(from.sin_addr.s_addr),
-				    sizeof(from.sin_addr.s_addr), AF_INET );
+			if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
+				int err = errno;
+				Debug( LDAP_DEBUG_ANY,
+					"daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
+					(long) s, err,
+				    err >= 0 && err < sys_nerr ?
+				    sys_errlist[err] : "unknown" );
+				slapd_close(s);
+				continue;
+			}
 
-				if(hp) {
-					char *p;
-					client_name = hp->h_name;
+			peeraddr = inet_ntoa( from.sin_addr );
+			sprintf( peername, "IP:%s:%d",
+				peeraddr != NULL ? peeraddr : "unknown",
+				(unsigned) ntohs( from.sin_port ) );
 
-					/* normalize the domain */
-					for ( p = client_name; *p; p++ ) {
-						*p = TOLOWER( (unsigned char) *p );
-					}
+#if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
+			hp = gethostbyaddr( (char *)
+			    &(from.sin_addr.s_addr),
+			    sizeof(from.sin_addr.s_addr), AF_INET );
 
-				} else {
-					client_name = NULL;
-				}
-#else
-				client_name = NULL;
-#endif
+			if(hp) {
+				dnsname = str2lower( hp->h_name );
 
 			} else {
-				client_name = NULL;;
-				client_addr = NULL;
+				dnsname = NULL;
 			}
+#else
+			dnsname = NULL;
+#endif
 
 #ifdef HAVE_TCPD
-			if(!hosts_ctl("slapd",
-				client_name != NULL ? client_name : STRING_UNKNOWN,
-				client_addr != NULL ? client_addr : STRING_UNKNOWN,
-				STRING_UNKNOWN))
+			if( !hosts_ctl("slapd",
+				dnsname != NULL ? dnsname : STRING_UNKNOWN,
+				peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
+				STRING_UNKNOWN ))
 			{
 				/* DENY ACCESS */
 				Statslog( LDAP_DEBUG_ANY,
 			   	 "fd=%ld connection from %s (%s) denied.\n",
 			   	 	(long) s,
-					client_name == NULL ? "unknown" : client_name,
-					client_addr == NULL ? "unknown" : client_addr,
+					dnsname != NULL ? dnsname : "unknown",
+					peeraddr != NULL ? peeraddr : "unknown",
 			   	  0, 0 );
 
 				slapd_close(s);
@@ -717,7 +723,10 @@ slapd_daemon_task(
 			}
 #endif /* HAVE_TCPD */
 
-			if( (id = connection_init(s, client_name, client_addr,
+			if( (id = connection_init(s,
+				slap_listeners[l]->sl_url,
+				dnsname, peername,
+				slap_listeners[l]->sl_name,
 #ifdef HAVE_TLS
 				slap_listeners[l]->sl_is_tls
 #else
@@ -728,8 +737,8 @@ slapd_daemon_task(
 				Debug( LDAP_DEBUG_ANY,
 					"daemon: connection_init(%ld, %s, %s) failed.\n",
 					(long) s,
-					client_name == NULL ? "unknown" : client_name,
-					client_addr == NULL ? "unknown" : client_addr);
+					peername,
+					slap_listeners[l]->sl_name );
 				slapd_close(s);
 				continue;
 			}
@@ -737,8 +746,8 @@ slapd_daemon_task(
 			Statslog( LDAP_DEBUG_STATS,
 				"daemon: conn=%d fd=%ld connection from %s (%s) accepted.\n",
 				id, (long) s,
-				client_name == NULL ? "unknown" : client_name,
-				client_addr == NULL ? "unknown" : client_addr,
+				peername,
+				slap_listeners[l]->sl_name,
 				0 );
 
 			slapd_add( s );
diff --git a/servers/slapd/dn.c b/servers/slapd/dn.c
index 4f28d164b8989490de6b653ce3aa95a3328986c9..b9e249711796b59544046a22c849fa3b35d102a1 100644
--- a/servers/slapd/dn.c
+++ b/servers/slapd/dn.c
@@ -131,17 +131,11 @@ dn_normalize( char *dn )
 char *
 dn_normalize_case( char *dn )
 {
-	char	*s;
-
 	/* normalize format */
 	dn_normalize( dn );
 
-	/* normalize case */
-	for ( s = dn; *s; s++ ) {
-		*s = TOUPPER( (unsigned char) *s );
-	}
-
-	return( dn );
+	/* and upper case it */
+	return( str2upper( dn ) );
 }
 
 /*
@@ -331,16 +325,29 @@ dn_type( char *dn )
 }
 
 char *
-dn_upcase( char *dn )
+str2upper( char *str )
 {
 	char    *s;
 
 	/* normalize case */
-	for ( s = dn; *s; s++ ) {
+	for ( s = str; *s; s++ ) {
 		*s = TOUPPER( (unsigned char) *s );
 	}
 
-	return( dn );
+	return( str );
+}
+
+char *
+str2lower( char *str )
+{
+	char    *s;
+
+	/* normalize case */
+	for ( s = str; *s; s++ ) {
+		*s = TOLOWER( (unsigned char) *s );
+	}
+
+	return( str );
 }
 
 
diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c
index 855a2e8dc047852be6fd9064b114e79851f7c99a..dff72f9690e8daaceae5d550f4025002310b3f62 100644
--- a/servers/slapd/monitor.c
+++ b/servers/slapd/monitor.c
@@ -104,7 +104,7 @@ monitor_info( Connection *conn, Operation *op )
 			": %ld/%ld/%ld "
 			": %s%s%s%s%s%s "
 			": %s : %s : %s "
-			": %s : %s",
+			": %s : %s : %s : %s ",
 
 			c->c_connid,
 			(long) c->c_protocol,
@@ -123,8 +123,11 @@ monitor_info( Connection *conn, Operation *op )
 			c->c_bind_in_progress ? "S" : "",
 
 		    c->c_cdn ? c->c_cdn : "<anonymous>",
-		    c->c_client_addr ? c->c_client_addr : "unknown",
-		    c->c_client_name ? c->c_client_name : "unknown",
+
+			c->c_listener_url,
+		    c->c_peer_domain,
+		    c->c_peer_name,
+		    c->c_sock_name,
 
 		    buf2,
 			buf3
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 44d5d8fba5f88c4085b490d580959b6b1d9e704d..3e90384d7e3cccf50d6d40f32c3ecb0fce305760 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -148,7 +148,10 @@ int connections_timeout_idle LDAP_P((time_t));
 
 long connection_init LDAP_P((
 	ber_socket_t s,
-	const char* name, const char* addr,
+	const char* url,
+	const char* dnsname,
+	const char* peername,
+	const char* sockname,
 	int use_tls ));
 
 void connection_closing LDAP_P(( Connection *c ));
@@ -174,7 +177,8 @@ char * dn_parent LDAP_P(( Backend *be, char *dn ));
 char * dn_rdn LDAP_P(( Backend *be, char *dn ));
 int dn_issuffix LDAP_P(( char *dn, char *suffix ));
 int dn_type LDAP_P(( char *dn ));
-char * dn_upcase LDAP_P(( char *dn ));
+char * str2upper LDAP_P(( char *str ));
+char * str2lower LDAP_P(( char *str ));
 char * rdn_attr_value LDAP_P(( char * rdn ));
 char * rdn_attr_type LDAP_P(( char * rdn ));
 void build_new_dn LDAP_P(( char ** new_dn, char *e_dn, char * p_dn,
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index ee971e115c9ac252da201bd1ff8706865ae028e5..1eee373e038302f5d4fb83d6d164c9d7d1b1113d 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -230,13 +230,17 @@ typedef struct slap_access {
 
 	int			a_access;
 
-	char		*a_dnpat;
-	char		*a_addrpat;
-	char		*a_domainpat;
-	char		*a_dnattr;
+	char		*a_dn_pat;
+	char		*a_dn_at;
+
+	char		*a_peername_pat;
+	char		*a_sockname_pat;
+
+	char		*a_domain_pat;
+	char		*a_url_pat;
 
 	/* ACL Groups */
-	char		*a_group;
+	char		*a_group_pat;
 	char		*a_group_oc;
 	char		*a_group_at;
 
@@ -247,8 +251,8 @@ typedef struct slap_access {
 typedef struct slap_acl {
 	/* "to" part: the entries this acl applies to */
 	Filter		*acl_filter;
-	regex_t		acl_dnre;
-	char		*acl_dnpat;
+	regex_t		acl_dn_re;
+	char		*acl_dn_pat;
 	char		**acl_attrs;
 
 	/* "by" part: list of who has what access to the entries */
@@ -579,8 +583,11 @@ typedef struct slap_conn {
 	time_t		c_starttime;	/* when the connection was opened */
 	time_t		c_activitytime;	/* when the connection was last used */
 	unsigned long		c_connid;	/* id of this connection for stats*/
-	char		*c_client_addr;	/* address of client */
-	char		*c_client_name;	/* name of client */
+
+	char		*c_listener_url;	/* listener URL */
+	char		*c_peer_domain;	/* DNS name of client */
+	char		*c_peer_name;	/* peer name (trans=addr:port) */
+	char		*c_sock_name;	/* sock name (trans=addr:port) */
 
 	/* only can be changed by binding thread */
 	int		c_bind_in_progress;	/* multi-op bind in progress */