xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-dnssrv/referral.c (revision 27fd3f6531803adac12382d7643a9a492b576601)
1 /* referral.c - DNS SRV backend referral handler */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-dnssrv/referral.c,v 1.26.2.4 2008/02/11 23:26:46 kurt Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2000-2008 The OpenLDAP Foundation.
6  * Portions Copyright 2000-2003 Kurt D. Zeilenga.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was originally developed by Kurt D. Zeilenga for inclusion
19  * in OpenLDAP Software.
20  */
21 
22 #include "portable.h"
23 
24 #include <stdio.h>
25 
26 #include <ac/string.h>
27 #include <ac/socket.h>
28 
29 #include "slap.h"
30 #include "proto-dnssrv.h"
31 
32 int
33 dnssrv_back_referrals(
34     Operation	*op,
35     SlapReply	*rs )
36 {
37 	int i;
38 	int rc = LDAP_OTHER;
39 	char *domain = NULL;
40 	char *hostlist = NULL;
41 	char **hosts = NULL;
42 	BerVarray urls = NULL;
43 
44 	if ( BER_BVISEMPTY( &op->o_req_dn ) ) {
45 		/* FIXME: need some means to determine whether the database
46 		 * is a glue instance */
47 		if ( SLAP_GLUE_INSTANCE( op->o_bd ) ) {
48 			return LDAP_SUCCESS;
49 		}
50 
51 		rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed";
52 		return LDAP_UNWILLING_TO_PERFORM;
53 	}
54 
55 	if( get_manageDSAit( op ) ) {
56 		if( op->o_tag == LDAP_REQ_SEARCH ) {
57 			return LDAP_SUCCESS;
58 		}
59 
60 		rs->sr_text = "DNS SRV problem processing manageDSAit control";
61 		return LDAP_OTHER;
62 	}
63 
64 	if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) {
65 		rs->sr_err = LDAP_REFERRAL;
66 		rs->sr_ref = default_referral;
67 		send_ldap_result( op, rs );
68 		rs->sr_ref = NULL;
69 		return LDAP_REFERRAL;
70 	}
71 
72 	Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n",
73 		op->o_req_dn.bv_val, domain, 0 );
74 
75 	i = ldap_domain2hostlist( domain, &hostlist );
76 	if ( i ) {
77 		Debug( LDAP_DEBUG_TRACE,
78 			"DNSSRV: domain2hostlist(%s) returned %d\n",
79 			domain, i, 0 );
80 		rs->sr_text = "no DNS SRV RR available for DN";
81 		rc = LDAP_NO_SUCH_OBJECT;
82 		goto done;
83 	}
84 
85 	hosts = ldap_str2charray( hostlist, " " );
86 
87 	if( hosts == NULL ) {
88 		Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charrary error\n", 0, 0, 0 );
89 		rs->sr_text = "problem processing DNS SRV records for DN";
90 		goto done;
91 	}
92 
93 	for( i=0; hosts[i] != NULL; i++) {
94 		struct berval url;
95 
96 		url.bv_len = STRLENOF( "ldap://" ) + strlen( hosts[i] );
97 		url.bv_val = ch_malloc( url.bv_len + 1 );
98 
99 		strcpy( url.bv_val, "ldap://" );
100 		strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] );
101 
102 		if ( ber_bvarray_add( &urls, &url ) < 0 ) {
103 			free( url.bv_val );
104 			rs->sr_text = "problem processing DNS SRV records for DN";
105 			goto done;
106 		}
107 	}
108 
109 	Statslog( LDAP_DEBUG_STATS,
110 	    "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n",
111 	    op->o_log_prefix, op->o_protocol,
112 		op->o_req_dn.bv_val, urls[0].bv_val, 0 );
113 
114 	Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> url=\"%s\"\n",
115 		op->o_req_dn.bv_val, urls[0].bv_val, 0 );
116 
117 	rs->sr_ref = urls;
118 	send_ldap_error( op, rs, LDAP_REFERRAL,
119 		"DNS SRV generated referrals" );
120 	rs->sr_ref = NULL;
121 	rc = LDAP_REFERRAL;
122 
123 done:
124 	if( domain != NULL ) ch_free( domain );
125 	if( hostlist != NULL ) ch_free( hostlist );
126 	if( hosts != NULL ) ldap_charray_free( hosts );
127 	ber_bvarray_free( urls );
128 	return rc;
129 }
130