1/*	$NetBSD: operational.c,v 1.1.1.3 2010/12/12 15:23:25 adam Exp $	*/
2
3/* OpenLDAP: pkg/ldap/servers/slapd/back-sql/operational.c,v 1.21.2.8 2010/04/19 16:53:04 quanah Exp */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1999-2010 The OpenLDAP Foundation.
7 * Portions Copyright 1999 Dmitry Kovalev.
8 * Portions Copyright 2002 Pierangelo Masarati.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted only as authorized by the OpenLDAP
13 * Public License.
14 *
15 * A copy of this license is available in the file LICENSE in the
16 * top-level directory of the distribution or, alternatively, at
17 * <http://www.OpenLDAP.org/license.html>.
18 */
19/* ACKNOWLEDGEMENTS:
20 * This work was initially developed by Dmitry Kovalev for inclusion
21 * by OpenLDAP Software.  Additional significant contributors include
22 * Pierangelo Masarati.
23 */
24
25#include "portable.h"
26
27#include <stdio.h>
28#include <sys/types.h>
29
30#include "slap.h"
31#include "proto-sql.h"
32#include "lutil.h"
33
34/*
35 * sets the supported operational attributes (if required)
36 */
37
38Attribute *
39backsql_operational_entryUUID( backsql_info *bi, backsql_entryID *id )
40{
41	int			rc;
42	struct berval		val, nval;
43	AttributeDescription	*desc = slap_schema.si_ad_entryUUID;
44	Attribute		*a;
45
46	backsql_entryUUID( bi, id, &val, NULL );
47
48	rc = (*desc->ad_type->sat_equality->smr_normalize)(
49			SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
50			desc->ad_type->sat_syntax,
51			desc->ad_type->sat_equality,
52			&val, &nval, NULL );
53	if ( rc != LDAP_SUCCESS ) {
54		ber_memfree( val.bv_val );
55		return NULL;
56	}
57
58	a = attr_alloc( desc );
59
60	a->a_numvals = 1;
61	a->a_vals = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
62	a->a_vals[ 0 ] = val;
63	BER_BVZERO( &a->a_vals[ 1 ] );
64
65	a->a_nvals = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
66	a->a_nvals[ 0 ] = nval;
67	BER_BVZERO( &a->a_nvals[ 1 ] );
68
69	return a;
70}
71
72Attribute *
73backsql_operational_entryCSN( Operation *op )
74{
75	char		csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ];
76	struct berval	entryCSN;
77	Attribute	*a;
78
79	a = attr_alloc( slap_schema.si_ad_entryCSN );
80	a->a_numvals = 1;
81	a->a_vals = ch_malloc( 2 * sizeof( struct berval ) );
82	BER_BVZERO( &a->a_vals[ 1 ] );
83
84#ifdef BACKSQL_SYNCPROV
85	if ( op->o_sync && op->o_tag == LDAP_REQ_SEARCH && op->o_private != NULL ) {
86		assert( op->o_private != NULL );
87
88		entryCSN = *((struct berval *)op->o_private);
89
90	} else
91#endif /* BACKSQL_SYNCPROV */
92	{
93		entryCSN.bv_val = csnbuf;
94		entryCSN.bv_len = sizeof( csnbuf );
95		slap_get_csn( op, &entryCSN, 0 );
96	}
97
98	ber_dupbv( &a->a_vals[ 0 ], &entryCSN );
99
100	a->a_nvals = a->a_vals;
101
102	return a;
103}
104
105int
106backsql_operational(
107	Operation	*op,
108	SlapReply	*rs )
109{
110
111	backsql_info 	*bi = (backsql_info*)op->o_bd->be_private;
112	SQLHDBC 	dbh = SQL_NULL_HDBC;
113	int		rc = 0;
114	Attribute	**ap;
115	enum {
116		BACKSQL_OP_HASSUBORDINATES = 0,
117		BACKSQL_OP_ENTRYUUID,
118		BACKSQL_OP_ENTRYCSN,
119
120		BACKSQL_OP_LAST
121	};
122	int		get_conn = BACKSQL_OP_LAST,
123			got[ BACKSQL_OP_LAST ] = { 0 };
124
125	Debug( LDAP_DEBUG_TRACE, "==>backsql_operational(): entry \"%s\"\n",
126			rs->sr_entry->e_nname.bv_val, 0, 0 );
127
128	for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
129		if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
130			get_conn--;
131			got[ BACKSQL_OP_HASSUBORDINATES ] = 1;
132
133		} else if ( (*ap)->a_desc == slap_schema.si_ad_entryUUID ) {
134			get_conn--;
135			got[ BACKSQL_OP_ENTRYUUID ] = 1;
136
137		} else if ( (*ap)->a_desc == slap_schema.si_ad_entryCSN ) {
138			get_conn--;
139			got[ BACKSQL_OP_ENTRYCSN ] = 1;
140		}
141	}
142
143	if ( !get_conn ) {
144		return 0;
145	}
146
147	rc = backsql_get_db_conn( op, &dbh );
148	if ( rc != LDAP_SUCCESS ) {
149		Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
150			"could not get connection handle - exiting\n",
151			0, 0, 0 );
152		return 1;
153	}
154
155	if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
156			&& !got[ BACKSQL_OP_HASSUBORDINATES ]
157			&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL )
158	{
159		rc = backsql_has_children( op, dbh, &rs->sr_entry->e_nname );
160
161		switch( rc ) {
162		case LDAP_COMPARE_TRUE:
163		case LDAP_COMPARE_FALSE:
164			*ap = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE );
165			assert( *ap != NULL );
166			ap = &(*ap)->a_next;
167			rc = 0;
168			break;
169
170		default:
171			Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
172				"has_children failed( %d)\n", rc, 0, 0 );
173			return 1;
174		}
175	}
176
177	if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryUUID, rs->sr_attrs ) )
178			&& !got[ BACKSQL_OP_ENTRYUUID ]
179			&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID ) == NULL )
180	{
181		backsql_srch_info	bsi = { 0 };
182
183		rc = backsql_init_search( &bsi, &rs->sr_entry->e_nname,
184				LDAP_SCOPE_BASE,
185				(time_t)(-1), NULL, dbh, op, rs, NULL,
186				BACKSQL_ISF_GET_ID );
187		if ( rc != LDAP_SUCCESS ) {
188			Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
189				"could not retrieve entry ID - no such entry\n",
190				0, 0, 0 );
191			return 1;
192		}
193
194		*ap = backsql_operational_entryUUID( bi, &bsi.bsi_base_id );
195
196		(void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
197
198		if ( bsi.bsi_attrs != NULL ) {
199			op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx );
200		}
201
202		if ( *ap == NULL ) {
203			Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
204				"could not retrieve entryUUID\n",
205				0, 0, 0 );
206			return 1;
207		}
208
209		ap = &(*ap)->a_next;
210	}
211
212	if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryCSN, rs->sr_attrs ) )
213			&& !got[ BACKSQL_OP_ENTRYCSN ]
214			&& attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryCSN ) == NULL )
215	{
216		*ap = backsql_operational_entryCSN( op );
217		if ( *ap == NULL ) {
218			Debug( LDAP_DEBUG_TRACE, "backsql_operational(): "
219				"could not retrieve entryCSN\n",
220				0, 0, 0 );
221			return 1;
222		}
223
224		ap = &(*ap)->a_next;
225	}
226
227	Debug( LDAP_DEBUG_TRACE, "<==backsql_operational(%d)\n", rc, 0, 0);
228
229	return rc;
230}
231
232