1 /* $NetBSD: dncache.c,v 1.3 2021/08/14 16:15:00 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2021 The OpenLDAP Foundation. 7 * Portions Copyright 2001-2003 Pierangelo Masarati. 8 * Portions Copyright 1999-2003 Howard Chu. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* ACKNOWLEDGEMENTS: 20 * This work was initially developed by the Howard Chu for inclusion 21 * in OpenLDAP Software and subsequently enhanced by Pierangelo 22 * Masarati. 23 */ 24 25 #include <sys/cdefs.h> 26 __RCSID("$NetBSD: dncache.c,v 1.3 2021/08/14 16:15:00 christos Exp $"); 27 28 #include "portable.h" 29 30 #include <stdio.h> 31 #include <ac/string.h> 32 33 #include "slap.h" 34 #include "../back-ldap/back-ldap.h" 35 #include "back-meta.h" 36 37 /* 38 * The dncache, at present, maps an entry to the target that holds it. 39 */ 40 41 typedef struct metadncacheentry_t { 42 struct berval dn; 43 int target; 44 45 time_t lastupdated; 46 } metadncacheentry_t; 47 48 /* 49 * meta_dncache_cmp 50 * 51 * compares two struct metadncacheentry; used by avl stuff 52 * FIXME: modify avl stuff to delete an entry based on cmp 53 * (e.g. when ttl expired?) 54 */ 55 int 56 meta_dncache_cmp( 57 const void *c1, 58 const void *c2 ) 59 { 60 metadncacheentry_t *cc1 = ( metadncacheentry_t * )c1; 61 metadncacheentry_t *cc2 = ( metadncacheentry_t * )c2; 62 63 /* 64 * case sensitive, because the dn MUST be normalized 65 */ 66 return ber_bvcmp( &cc1->dn, &cc2->dn); 67 } 68 69 /* 70 * meta_dncache_dup 71 * 72 * returns -1 in case a duplicate struct metadncacheentry has been inserted; 73 * used by avl stuff 74 */ 75 int 76 meta_dncache_dup( 77 void *c1, 78 void *c2 ) 79 { 80 metadncacheentry_t *cc1 = ( metadncacheentry_t * )c1; 81 metadncacheentry_t *cc2 = ( metadncacheentry_t * )c2; 82 83 /* 84 * case sensitive, because the dn MUST be normalized 85 */ 86 return ( ber_bvcmp( &cc1->dn, &cc2->dn ) == 0 ) ? -1 : 0; 87 } 88 89 /* 90 * meta_dncache_get_target 91 * 92 * returns the target a dn belongs to, or -1 in case the dn is not 93 * in the cache 94 */ 95 int 96 meta_dncache_get_target( 97 metadncache_t *cache, 98 struct berval *ndn ) 99 { 100 metadncacheentry_t tmp_entry, 101 *entry; 102 int target = META_TARGET_NONE; 103 104 assert( cache != NULL ); 105 assert( ndn != NULL ); 106 107 tmp_entry.dn = *ndn; 108 ldap_pvt_thread_mutex_lock( &cache->mutex ); 109 entry = ( metadncacheentry_t * )ldap_avl_find( cache->tree, 110 ( caddr_t )&tmp_entry, meta_dncache_cmp ); 111 112 if ( entry != NULL ) { 113 114 /* 115 * if cache->ttl < 0, cache never expires; 116 * if cache->ttl = 0 no cache is used; shouldn't get here 117 * else, cache is used with ttl 118 */ 119 if ( cache->ttl < 0 ) { 120 target = entry->target; 121 122 } else { 123 if ( entry->lastupdated+cache->ttl > slap_get_time() ) { 124 target = entry->target; 125 } 126 } 127 } 128 ldap_pvt_thread_mutex_unlock( &cache->mutex ); 129 130 return target; 131 } 132 133 /* 134 * meta_dncache_update_entry 135 * 136 * updates target and lastupdated of a struct metadncacheentry if exists, 137 * otherwise it gets created; returns -1 in case of error 138 */ 139 int 140 meta_dncache_update_entry( 141 metadncache_t *cache, 142 struct berval *ndn, 143 int target ) 144 { 145 metadncacheentry_t *entry, 146 tmp_entry; 147 time_t curr_time = 0L; 148 int err = 0; 149 150 assert( cache != NULL ); 151 assert( ndn != NULL ); 152 153 /* 154 * if cache->ttl < 0, cache never expires; 155 * if cache->ttl = 0 no cache is used; shouldn't get here 156 * else, cache is used with ttl 157 */ 158 if ( cache->ttl > 0 ) { 159 curr_time = slap_get_time(); 160 } 161 162 tmp_entry.dn = *ndn; 163 164 ldap_pvt_thread_mutex_lock( &cache->mutex ); 165 entry = ( metadncacheentry_t * )ldap_avl_find( cache->tree, 166 ( caddr_t )&tmp_entry, meta_dncache_cmp ); 167 168 if ( entry != NULL ) { 169 entry->target = target; 170 entry->lastupdated = curr_time; 171 172 } else { 173 entry = ch_malloc( sizeof( metadncacheentry_t ) + ndn->bv_len + 1 ); 174 if ( entry == NULL ) { 175 err = -1; 176 goto error_return; 177 } 178 179 entry->dn.bv_len = ndn->bv_len; 180 entry->dn.bv_val = (char *)&entry[ 1 ]; 181 AC_MEMCPY( entry->dn.bv_val, ndn->bv_val, ndn->bv_len ); 182 entry->dn.bv_val[ ndn->bv_len ] = '\0'; 183 184 entry->target = target; 185 entry->lastupdated = curr_time; 186 187 err = ldap_avl_insert( &cache->tree, ( caddr_t )entry, 188 meta_dncache_cmp, meta_dncache_dup ); 189 } 190 191 error_return:; 192 ldap_pvt_thread_mutex_unlock( &cache->mutex ); 193 194 return err; 195 } 196 197 /* 198 * meta_dncache_update_entry 199 * 200 * updates target and lastupdated of a struct metadncacheentry if exists, 201 * otherwise it gets created; returns -1 in case of error 202 */ 203 int 204 meta_dncache_delete_entry( 205 metadncache_t *cache, 206 struct berval *ndn ) 207 { 208 metadncacheentry_t *entry, 209 tmp_entry; 210 211 assert( cache != NULL ); 212 assert( ndn != NULL ); 213 214 tmp_entry.dn = *ndn; 215 216 ldap_pvt_thread_mutex_lock( &cache->mutex ); 217 entry = ldap_avl_delete( &cache->tree, ( caddr_t )&tmp_entry, 218 meta_dncache_cmp ); 219 ldap_pvt_thread_mutex_unlock( &cache->mutex ); 220 221 if ( entry != NULL ) { 222 meta_dncache_free( ( void * )entry ); 223 } 224 225 return 0; 226 } 227 228 /* 229 * meta_dncache_free 230 * 231 * frees an entry 232 * 233 */ 234 void 235 meta_dncache_free( 236 void *e ) 237 { 238 free( e ); 239 } 240 241