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