1/*	$NetBSD: txn.c,v 1.3 2021/08/14 16:14:56 christos Exp $	*/
2
3/* $OpenLDAP$ */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 2006-2021 The OpenLDAP Foundation.
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 program was originally developed by Kurt D. Zeilenga for inclusion
19 * in OpenLDAP Software.
20 */
21
22/*
23 * LDAPv3 Transactions (draft-zeilenga-ldap-txn)
24 */
25
26#include <sys/cdefs.h>
27__RCSID("$NetBSD: txn.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
28
29#include "portable.h"
30
31#include <stdio.h>
32#include <ac/stdlib.h>
33
34#include <ac/socket.h>
35#include <ac/string.h>
36#include <ac/time.h>
37
38#include "ldap-int.h"
39#include "ldap_log.h"
40
41int
42ldap_txn_start(
43	LDAP *ld,
44	LDAPControl **sctrls,
45	LDAPControl **cctrls,
46	int *msgidp )
47{
48	return ldap_extended_operation( ld, LDAP_EXOP_TXN_START,
49		NULL, sctrls, cctrls, msgidp );
50}
51
52int
53ldap_txn_start_s(
54	LDAP *ld,
55	LDAPControl **sctrls,
56	LDAPControl **cctrls,
57	struct berval **txnid )
58{
59	assert( txnid != NULL );
60
61	return ldap_extended_operation_s( ld, LDAP_EXOP_TXN_START,
62		NULL, sctrls, cctrls, NULL, txnid );
63}
64
65int
66ldap_txn_end(
67	LDAP *ld,
68	int commit,
69	struct berval *txnid,
70	LDAPControl **sctrls,
71	LDAPControl **cctrls,
72	int *msgidp )
73{
74	int rc;
75	BerElement *txnber = NULL;
76	struct berval *txnval = NULL;
77
78	assert( txnid != NULL );
79
80	txnber = ber_alloc_t( LBER_USE_DER );
81
82	if( commit ) {
83		ber_printf( txnber, "{ON}", txnid );
84	} else {
85		ber_printf( txnber, "{bON}", commit, txnid );
86	}
87
88	ber_flatten( txnber, &txnval );
89
90	rc = ldap_extended_operation( ld, LDAP_EXOP_TXN_END,
91		txnval, sctrls, cctrls, msgidp );
92
93	ber_free( txnber, 1 );
94	return rc;
95}
96
97int
98ldap_txn_end_s(
99	LDAP *ld,
100	int commit,
101	struct berval *txnid,
102	LDAPControl **sctrls,
103	LDAPControl **cctrls,
104	int *retidp )
105{
106	int rc;
107	BerElement *txnber = NULL;
108	struct berval *txnval = NULL;
109	struct berval *retdata = NULL;
110
111	if ( retidp != NULL ) *retidp = -1;
112
113	txnber = ber_alloc_t( LBER_USE_DER );
114
115	if( commit ) {
116		ber_printf( txnber, "{ON}", txnid );
117	} else {
118		ber_printf( txnber, "{bON}", commit, txnid );
119	}
120
121	ber_flatten( txnber, &txnval );
122
123	rc = ldap_extended_operation_s( ld, LDAP_EXOP_TXN_END,
124		txnval, sctrls, cctrls, NULL, &retdata );
125
126	ber_free( txnber, 1 );
127
128	/* parse retdata */
129	if( retdata != NULL ) {
130		BerElement *ber;
131		ber_tag_t tag;
132		ber_int_t retid;
133
134		if( retidp == NULL ) goto done;
135
136		ber = ber_init( retdata );
137
138		if( ber == NULL ) {
139			rc = ld->ld_errno = LDAP_NO_MEMORY;
140			goto done;
141		}
142
143		tag = ber_scanf( ber, "i", &retid );
144		ber_free( ber, 1 );
145
146		if ( tag != LBER_INTEGER ) {
147			rc = ld->ld_errno = LDAP_DECODING_ERROR;
148			goto done;
149		}
150
151		*retidp = (int) retid;
152
153done:
154		ber_bvfree( retdata );
155	}
156
157	return rc;
158}
159