1/* references.c */
2/* $OpenLDAP$ */
3/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 *
5 * Copyright 1998-2011 The OpenLDAP Foundation.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
11 *
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
15 */
16
17#include "portable.h"
18
19#include <stdio.h>
20
21#include <ac/stdlib.h>
22
23#include <ac/socket.h>
24#include <ac/string.h>
25#include <ac/time.h>
26
27#include "ldap-int.h"
28
29LDAPMessage *
30ldap_first_reference( LDAP *ld, LDAPMessage *chain )
31{
32	assert( ld != NULL );
33	assert( LDAP_VALID( ld ) );
34	assert( chain != NULL );
35
36	return chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE
37		? chain
38		: ldap_next_reference( ld, chain );
39}
40
41LDAPMessage *
42ldap_next_reference( LDAP *ld, LDAPMessage *ref )
43{
44	assert( ld != NULL );
45	assert( LDAP_VALID( ld ) );
46	assert( ref != NULL );
47
48	for (
49		ref = ref->lm_chain;
50		ref != NULL;
51		ref = ref->lm_chain )
52	{
53		if( ref->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
54			return( ref );
55		}
56	}
57
58	return( NULL );
59}
60
61int
62ldap_count_references( LDAP *ld, LDAPMessage *chain )
63{
64	int	i;
65
66	assert( ld != NULL );
67	assert( LDAP_VALID( ld ) );
68
69	for ( i = 0; chain != NULL; chain = chain->lm_chain ) {
70		if( chain->lm_msgtype == LDAP_RES_SEARCH_REFERENCE ) {
71			i++;
72		}
73	}
74
75	return( i );
76}
77
78int
79ldap_parse_reference(
80	LDAP            *ld,
81	LDAPMessage     *ref,
82	char            ***referralsp,
83	LDAPControl     ***serverctrls,
84	int             freeit)
85{
86	BerElement be;
87	char **refs = NULL;
88	int rc;
89
90	assert( ld != NULL );
91	assert( LDAP_VALID( ld ) );
92	assert( ref !=  NULL );
93
94	if( ref->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) {
95		return LDAP_PARAM_ERROR;
96	}
97
98	/* make a private copy of BerElement */
99	AC_MEMCPY(&be, ref->lm_ber, sizeof(be));
100
101	if ( ber_scanf( &be, "{v" /*}*/, &refs ) == LBER_ERROR ) {
102		rc = LDAP_DECODING_ERROR;
103		goto free_and_return;
104	}
105
106	if ( serverctrls == NULL ) {
107		rc = LDAP_SUCCESS;
108		goto free_and_return;
109	}
110
111	if ( ber_scanf( &be, /*{*/ "}" ) == LBER_ERROR ) {
112		rc = LDAP_DECODING_ERROR;
113		goto free_and_return;
114	}
115
116	rc = ldap_pvt_get_controls( &be, serverctrls );
117
118free_and_return:
119
120	if( referralsp != NULL ) {
121		/* provide references regradless of return code */
122		*referralsp = refs;
123
124	} else {
125		LDAP_VFREE( refs );
126	}
127
128	if( freeit ) {
129		ldap_msgfree( ref );
130	}
131
132	if( rc != LDAP_SUCCESS ) {
133		ld->ld_errno = rc;
134
135		if( ld->ld_matched != NULL ) {
136			LDAP_FREE( ld->ld_matched );
137			ld->ld_matched = NULL;
138		}
139
140		if( ld->ld_error != NULL ) {
141			LDAP_FREE( ld->ld_error );
142			ld->ld_error = NULL;
143		}
144	}
145
146	return rc;
147}
148