1/* $OpenLDAP$ */
2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 2006-2011 The OpenLDAP Foundation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
9 * Public License.
10 *
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
14 */
15/* ACKNOWLEDGEMENTS:
16 * This program was orignally developed by Kurt D. Zeilenga for inclusion
17 * in OpenLDAP Software.
18 */
19
20/*
21 * LDAPv3 Transactions (draft-zeilenga-ldap-txn)
22 */
23
24#include "portable.h"
25
26#include <stdio.h>
27#include <ac/stdlib.h>
28
29#include <ac/socket.h>
30#include <ac/string.h>
31#include <ac/time.h>
32
33#include "ldap-int.h"
34#include "ldap_log.h"
35
36#ifdef LDAP_X_TXN
37int
38ldap_txn_start(
39	LDAP *ld,
40	LDAPControl **sctrls,
41	LDAPControl **cctrls,
42	int *msgidp )
43{
44	return ldap_extended_operation( ld, LDAP_EXOP_X_TXN_START,
45		NULL, sctrls, cctrls, msgidp );
46}
47
48int
49ldap_txn_start_s(
50	LDAP *ld,
51	LDAPControl **sctrls,
52	LDAPControl **cctrls,
53	struct berval **txnid )
54{
55	assert( txnid != NULL );
56
57	return ldap_extended_operation_s( ld, LDAP_EXOP_X_TXN_START,
58		NULL, sctrls, cctrls, NULL, txnid );
59}
60
61int
62ldap_txn_end(
63	LDAP *ld,
64	int commit,
65	struct berval *txnid,
66	LDAPControl **sctrls,
67	LDAPControl **cctrls,
68	int *msgidp )
69{
70	int rc;
71	BerElement *txnber = NULL;
72	struct berval *txnval = NULL;
73
74	assert( txnid != NULL );
75
76	txnber = ber_alloc_t( LBER_USE_DER );
77
78	if( commit ) {
79		ber_printf( txnber, "{ON}", txnid );
80	} else {
81		ber_printf( txnber, "{bON}", commit, txnid );
82	}
83
84	ber_flatten( txnber, &txnval );
85
86	rc = ldap_extended_operation( ld, LDAP_EXOP_X_TXN_END,
87		txnval, sctrls, cctrls, msgidp );
88
89	ber_free( txnber, 1 );
90	return rc;
91}
92
93int
94ldap_txn_end_s(
95	LDAP *ld,
96	int commit,
97	struct berval *txnid,
98	LDAPControl **sctrls,
99	LDAPControl **cctrls,
100	int *retidp )
101{
102	int rc;
103	BerElement *txnber = NULL;
104	struct berval *txnval = NULL;
105	struct berval *retdata = NULL;
106
107	if ( retidp != NULL ) *retidp = -1;
108
109	txnber = ber_alloc_t( LBER_USE_DER );
110
111	if( commit ) {
112		ber_printf( txnber, "{ON}", txnid );
113	} else {
114		ber_printf( txnber, "{bON}", commit, txnid );
115	}
116
117	ber_flatten( txnber, &txnval );
118
119	rc = ldap_extended_operation_s( ld, LDAP_EXOP_X_TXN_END,
120		txnval, sctrls, cctrls, NULL, &retdata );
121
122	ber_free( txnber, 1 );
123
124	/* parse retdata */
125	if( retdata != NULL ) {
126		BerElement *ber;
127		ber_tag_t tag;
128		ber_int_t retid;
129
130		if( retidp == NULL ) goto done;
131
132		ber = ber_init( retdata );
133
134		if( ber == NULL ) {
135			rc = ld->ld_errno = LDAP_NO_MEMORY;
136			goto done;
137		}
138
139		tag = ber_scanf( ber, "i", &retid );
140		ber_free( ber, 1 );
141
142		if ( tag != LBER_INTEGER ) {
143			rc = ld->ld_errno = LDAP_DECODING_ERROR;
144			goto done;
145		}
146
147		*retidp = (int) retid;
148
149done:
150		ber_bvfree( retdata );
151	}
152
153	return rc;
154}
155#endif
156