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