Changeset 4681
- Timestamp:
- 11/20/08 14:30:23 (2 months ago)
- Files:
-
- trunk/src/charon/sa/ike_sa_manager.c (modified) (49 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/charon/sa/ike_sa_manager.c
r4579 r4681 28 28 #include <crypto/hashers/hasher.h> 29 29 30 /* the default size of the hash table (MUST be a power of 2) */ 31 #define DEFAULT_HASHTABLE_SIZE 1 32 33 /* the maximum size of the hash table (MUST be a power of 2) */ 34 #define MAX_HASHTABLE_SIZE (1 << 30) 35 36 /* the default number of segments (MUST be a power of 2) */ 37 #define DEFAULT_SEGMENT_COUNT 1 38 30 39 typedef struct entry_t entry_t; 31 40 … … 61 70 62 71 /** 63 * Identifi action of an IKE_SA (SPIs).72 * Identification of an IKE_SA (SPIs). 64 73 */ 65 74 ike_sa_id_t *ike_sa_id; … … 142 151 } 143 152 153 /** 154 * Function that matches entry_t objects by initiator SPI and the hash of the 155 * IKE_SA_INIT message. 156 */ 157 static bool entry_match_by_hash(entry_t *entry, ike_sa_id_t *id, chunk_t *hash) 158 { 159 return id->get_responder_spi(id) == 0 && 160 id->is_initiator(id) == entry->ike_sa_id->is_initiator(entry->ike_sa_id) && 161 id->get_initiator_spi(id) == entry->ike_sa_id->get_initiator_spi(entry->ike_sa_id) && 162 chunk_equals(*hash, entry->init_hash); 163 } 164 165 /** 166 * Function that matches entry_t objects by ike_sa_id_t. 167 */ 168 static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id) 169 { 170 if (id->equals(id, entry->ike_sa_id)) 171 { 172 return TRUE; 173 } 174 if (entry->ike_sa_id->get_responder_spi(entry->ike_sa_id) == 0 && 175 id->is_initiator(id) == entry->ike_sa_id->is_initiator(entry->ike_sa_id) && 176 id->get_initiator_spi(id) == entry->ike_sa_id->get_initiator_spi(entry->ike_sa_id)) 177 { 178 /* this is TRUE for IKE_SAs that we initiated but have not yet received a response */ 179 return TRUE; 180 } 181 return FALSE; 182 } 183 184 /** 185 * Function that matches entry_t objects by ike_sa_t pointers. 186 */ 187 static bool entry_match_by_sa(entry_t *entry, ike_sa_t *ike_sa) 188 { 189 return entry->ike_sa == ike_sa; 190 } 191 192 /** 193 * Hash function for ike_sa_id_t objects. 194 */ 195 static u_int ike_sa_id_hash(ike_sa_id_t *ike_sa_id) 196 { 197 /* we always use initiator spi as key */ 198 return ike_sa_id->get_initiator_spi(ike_sa_id); 199 } 200 201 typedef struct segment_t segment_t; 202 203 /** 204 * Struct to manage segments of the hash table. 205 */ 206 struct segment_t { 207 /* mutex to access a segment exclusively */ 208 mutex_t *mutex; 209 210 /* the number of items in this segment */ 211 u_int count; 212 }; 144 213 145 214 typedef struct private_ike_sa_manager_t private_ike_sa_manager_t; … … 155 224 156 225 /** 157 * Lock for exclusivly accessing the manager.226 * Hash table with entries for the ike_sa_t objects. 158 227 */ 159 mutex_t *mutex;160 228 linked_list_t **ike_sa_table; 229 161 230 /** 162 * Linked list with entries for the ike_sa_t objects.231 * The size of the hash table. 163 232 */ 164 linked_list_t *ike_sa_list; 233 u_int table_size; 234 235 /** 236 * Mask to map the hashes to table rows. 237 */ 238 u_int table_mask; 239 240 /** 241 * Segments of the hash table. 242 */ 243 segment_t *segments; 244 245 /** 246 * The number of segments. 247 */ 248 u_int segment_count; 249 250 /** 251 * Mask to map a table row to a segment. 252 */ 253 u_int segment_mask; 165 254 166 255 /** … … 180 269 }; 181 270 182 /** 183 * Implementation of private_ike_sa_manager_t.get_entry_by_id. 271 272 /** 273 * Acquire a lock to access the segment of the table row with the given index. 274 * It also works with the segment index directly. 275 */ 276 static void lock_single_segment(private_ike_sa_manager_t *this, u_int index) 277 { 278 mutex_t *lock = this->segments[index & this->segment_mask].mutex; 279 lock->lock(lock); 280 } 281 282 /** 283 * Release the lock required to access the segment of the table row with the given index. 284 * It also works with the segment index directly. 285 */ 286 static void unlock_single_segment(private_ike_sa_manager_t *this, u_int index) 287 { 288 mutex_t *lock = this->segments[index & this->segment_mask].mutex; 289 lock->unlock(lock); 290 } 291 292 /** 293 * Lock all segments 294 */ 295 static void lock_all_segments(private_ike_sa_manager_t *this) 296 { 297 u_int i; 298 for (i = 0; i < this->segment_count; ++i) 299 { 300 this->segments[i].mutex->lock(this->segments[i].mutex); 301 } 302 } 303 304 /** 305 * Unlock all segments 306 */ 307 static void unlock_all_segments(private_ike_sa_manager_t *this) 308 { 309 u_int i; 310 for (i = 0; i < this->segment_count; ++i) 311 { 312 this->segments[i].mutex->unlock(this->segments[i].mutex); 313 } 314 } 315 316 typedef struct private_enumerator_t private_enumerator_t; 317 318 /** 319 * hash table enumerator implementation 320 */ 321 struct private_enumerator_t { 322 323 /** 324 * implements enumerator interface 325 */ 326 enumerator_t enumerator; 327 328 /** 329 * associated ike_sa_manager_t 330 */ 331 private_ike_sa_manager_t *manager; 332 333 /** 334 * current segment index 335 */ 336 u_int segment; 337 338 /** 339 * current table row index 340 */ 341 u_int row; 342 343 /** 344 * enumerator for the current table row 345 */ 346 enumerator_t *current; 347 }; 348 349 /** 350 * Implementation of private_enumerator_t.enumerator.enumerate. 351 */ 352 static bool enumerate(private_enumerator_t *this, entry_t **entry, u_int *segment) 353 { 354 while (this->segment < this->manager->segment_count) 355 { 356 while (this->row < this->manager->table_size) 357 { 358 if (this->current) 359 { 360 entry_t *item; 361 if (this->current->enumerate(this->current, (void**)&item)) 362 { 363 *entry = item; 364 *segment = this->segment; 365 return TRUE; 366 } 367 this->current->destroy(this->current); 368 this->current = NULL; 369 unlock_single_segment(this->manager, this->segment); 370 } 371 else 372 { 373 linked_list_t *list; 374 lock_single_segment(this->manager, this->segment); 375 if ((list = this->manager->ike_sa_table[this->row]) != NULL && 376 list->get_count(list)) 377 { 378 this->current = list->create_enumerator(list); 379 continue; 380 } 381 unlock_single_segment(this->manager, this->segment); 382 } 383 this->row += this->manager->segment_count; 384 } 385 this->segment++; 386 this->row = this->segment; 387 } 388 return FALSE; 389 } 390 391 /** 392 * Implementation of private_enumerator_t.enumerator.destroy. 393 */ 394 static void enumerator_destroy(private_enumerator_t *this) 395 { 396 if (this->current) 397 { 398 this->current->destroy(this->current); 399 unlock_single_segment(this->manager, this->segment); 400 } 401 free(this); 402 } 403 404 /** 405 * Creates an enumerator to enumerate the entries in the hash table. 406 */ 407 static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this) 408 { 409 private_enumerator_t *enumerator = malloc_thing(private_enumerator_t); 410 411 enumerator->enumerator.enumerate = (void*)enumerate; 412 enumerator->enumerator.destroy = (void*)enumerator_destroy; 413 enumerator->manager = this; 414 enumerator->segment = 0; 415 enumerator->row = 0; 416 enumerator->current = NULL; 417 418 return &enumerator->enumerator; 419 } 420 421 /** 422 * Put an entry into the hash table. 423 * Note: The caller has to unlock the returned segment. 424 */ 425 static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry) 426 { 427 linked_list_t *list; 428 u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask; 429 u_int segment = row & this->segment_mask; 430 431 lock_single_segment(this, segment); 432 if ((list = this->ike_sa_table[row]) == NULL) 433 { 434 list = this->ike_sa_table[row] = linked_list_create(); 435 } 436 list->insert_last(list, entry); 437 this->segments[segment].count++; 438 return segment; 439 } 440 441 /** 442 * Remove an entry from the hash table. 443 * Note: The caller MUST have a lock on the segment of this entry. 444 */ 445 static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry) 446 { 447 linked_list_t *list; 448 u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask; 449 u_int segment = row & this->segment_mask; 450 451 if ((list = this->ike_sa_table[row]) != NULL) 452 { 453 entry_t *current; 454 enumerator_t *enumerator = list->create_enumerator(list); 455 while (enumerator->enumerate(enumerator, ¤t)) 456 { 457 if (current == entry) 458 { 459 list->remove_at(list, enumerator); 460 this->segments[segment].count--; 461 break; 462 } 463 } 464 enumerator->destroy(enumerator); 465 } 466 } 467 468 /** 469 * Remove the entry at the current enumerator position. 470 */ 471 static void remove_entry_at(private_enumerator_t *this) 472 { 473 if (this->current) 474 { 475 linked_list_t *list = this->manager->ike_sa_table[this->row]; 476 list->remove_at(list, this->current); 477 this->manager->segments[this->segment].count--; 478 } 479 } 480 481 /** 482 * Find an entry using the provided match function to compare the entries for 483 * equality. 484 */ 485 static status_t get_entry_by_match_function(private_ike_sa_manager_t *this, 486 ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment, 487 linked_list_match_t match, void *p1, void *p2) 488 { 489 entry_t *current; 490 linked_list_t *list; 491 u_int row = ike_sa_id_hash(ike_sa_id) & this->table_mask; 492 u_int seg = row & this->segment_mask; 493 494 lock_single_segment(this, seg); 495 if ((list = this->ike_sa_table[row]) != NULL) 496 { 497 if (list->find_first(list, match, (void**)¤t, p1, p2) == SUCCESS) 498 { 499 *entry = current; 500 *segment = seg; 501 /* the locked segment has to be unlocked by the caller */ 502 return SUCCESS; 503 } 504 } 505 unlock_single_segment(this, seg); 506 return NOT_FOUND; 507 } 508 509 /** 510 * Find an entry by ike_sa_id_t. 511 * Note: On SUCCESS, the caller has to unlock the segment. 184 512 */ 185 513 static status_t get_entry_by_id(private_ike_sa_manager_t *this, 186 ike_sa_id_t *ike_sa_id, entry_t **entry) 187 { 188 enumerator_t *enumerator; 189 entry_t *current; 190 status_t status; 191 192 /* create enumerator over list of ike_sa's */ 193 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); 194 195 /* default status */ 196 status = NOT_FOUND; 197 198 while (enumerator->enumerate(enumerator, ¤t)) 199 { 200 if (current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id)) 201 { 202 DBG2(DBG_MGR, "found entry by both SPIs"); 203 *entry = current; 204 status = SUCCESS; 205 break; 206 } 207 if (ike_sa_id->get_responder_spi(ike_sa_id) == 0 || 208 current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0) 209 { 210 /* seems to be a half ready ike_sa */ 211 if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) == 212 ike_sa_id->get_initiator_spi(ike_sa_id)) && 213 (current->ike_sa_id->is_initiator(ike_sa_id) == 214 ike_sa_id->is_initiator(current->ike_sa_id))) 215 { 216 DBG2(DBG_MGR, "found entry by initiator SPI"); 217 *entry = current; 218 status = SUCCESS; 219 break; 220 } 221 } 222 } 223 224 enumerator->destroy(enumerator); 225 return status; 226 } 227 228 /** 229 * Implementation of private_ike_sa_manager_t.get_entry_by_sa. 514 ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment) 515 { 516 return get_entry_by_match_function(this, ike_sa_id, entry, segment, 517 (linked_list_match_t)entry_match_by_id, ike_sa_id, NULL); 518 } 519 520 /** 521 * Find an entry by initiator SPI and IKE_SA_INIT hash. 522 * Note: On SUCCESS, the caller has to unlock the segment. 523 */ 524 static status_t get_entry_by_hash(private_ike_sa_manager_t *this, 525 ike_sa_id_t *ike_sa_id, chunk_t hash, entry_t **entry, u_int *segment) 526 { 527 return get_entry_by_match_function(this, ike_sa_id, entry, segment, 528 (linked_list_match_t)entry_match_by_hash, ike_sa_id, &hash); 529 } 530 531 /** 532 * Find an entry by IKE_SA pointer. 533 * Note: On SUCCESS, the caller has to unlock the segment. 230 534 */ 231 535 static status_t get_entry_by_sa(private_ike_sa_manager_t *this, 232 ike_sa_t *ike_sa, entry_t **entry) 233 { 234 enumerator_t *enumerator; 235 entry_t *current; 236 status_t status; 237 238 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); 239 240 /* default status */ 241 status = NOT_FOUND; 242 243 while (enumerator->enumerate(enumerator, ¤t)) 244 { 245 /* only pointers are compared */ 246 if (current->ike_sa == ike_sa) 247 { 248 DBG2(DBG_MGR, "found entry by pointer"); 249 *entry = current; 250 status = SUCCESS; 251 break; 252 } 253 } 254 enumerator->destroy(enumerator); 255 256 return status; 257 } 258 259 /** 260 * Implementation of private_ike_sa_manager_s.delete_entry. 261 */ 262 static status_t delete_entry(private_ike_sa_manager_t *this, entry_t *entry) 263 { 264 enumerator_t *enumerator; 265 entry_t *current; 266 status_t status; 267 268 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); 269 270 status = NOT_FOUND; 271 272 while (enumerator->enumerate(enumerator, ¤t)) 273 { 274 if (current == entry) 275 { 276 /* mark it, so now new threads can get this entry */ 277 entry->driveout_new_threads = TRUE; 278 /* wait until all workers have done their work */ 279 while (entry->waiting_threads) 280 { 281 /* wake up all */ 282 entry->condvar->broadcast(entry->condvar); 283 /* they will wake us again when their work is done */ 284 entry->condvar->wait(entry->condvar, this->mutex); 285 } 286 287 DBG2(DBG_MGR, "found entry by pointer, deleting it"); 288 this->ike_sa_list->remove_at(this->ike_sa_list, enumerator); 289 entry_destroy(entry); 290 status = SUCCESS; 291 break; 292 } 293 } 294 enumerator->destroy(enumerator); 295 return status; 536 ike_sa_id_t *ike_sa_id, ike_sa_t *ike_sa, entry_t **entry, u_int *segment) 537 { 538 return get_entry_by_match_function(this, ike_sa_id, entry, segment, 539 (linked_list_match_t)entry_match_by_sa, ike_sa, NULL); 296 540 } 297 541 298 542 /** 299 543 * Wait until no other thread is using an IKE_SA, return FALSE if entry not 300 * acquireable 301 */ 302 static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry) 544 * acquirable. 545 */ 546 static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry, 547 u_int segment) 303 548 { 304 549 if (entry->driveout_new_threads) … … 312 557 * we register us as waiting. */ 313 558 entry->waiting_threads++; 314 entry->condvar->wait(entry->condvar, this-> mutex);559 entry->condvar->wait(entry->condvar, this->segments[segment].mutex); 315 560 entry->waiting_threads--; 316 561 } … … 343 588 ike_sa_t *ike_sa = NULL; 344 589 entry_t *entry; 345 346 DBG2(DBG_MGR, "checkout IKE_SA, %d IKE_SAs in manager", 347 this->ike_sa_list->get_count(this->ike_sa_list)); 348 349 this->mutex->lock(this->mutex); 350 if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS) 351 { 352 if (wait_for_entry(this, entry)) 590 u_int segment; 591 592 DBG2(DBG_MGR, "checkout IKE_SA"); 593 594 if (get_entry_by_id(this, ike_sa_id, &entry, &segment) == SUCCESS) 595 { 596 if (wait_for_entry(this, entry, segment)) 353 597 { 354 598 DBG2(DBG_MGR, "IKE_SA successfully checked out"); … … 356 600 ike_sa = entry->ike_sa; 357 601 } 358 }359 this->mutex->unlock(this->mutex);602 unlock_single_segment(this, segment); 603 } 360 604 charon->bus->set_sa(charon->bus, ike_sa); 361 605 return ike_sa; … … 369 613 entry_t *entry; 370 614 ike_sa_id_t *id; 615 u_int segment; 371 616 372 617 if (initiator) … … 380 625 entry = entry_create(id); 381 626 id->destroy(id); 382 this->mutex->lock(this->mutex);383 this->ike_sa_list->insert_last(this->ike_sa_list, entry);627 628 segment = put_entry(this, entry); 384 629 entry->checked_out = TRUE; 385 this->mutex->unlock(this->mutex);386 DBG2(DBG_MGR, "created IKE_SA, %d IKE_SAs in manager",387 this->ike_sa_list->get_count(this->ike_sa_list));630 unlock_single_segment(this, segment); 631 632 DBG2(DBG_MGR, "created IKE_SA"); 388 633 return entry->ike_sa; 389 634 } … … 395 640 message_t *message) 396 641 { 642 u_int segment; 397 643 entry_t *entry; 398 644 ike_sa_t *ike_sa = NULL; … … 401 647 id->switch_initiator(id); 402 648 403 DBG2(DBG_MGR, "checkout IKE_SA by message, %d IKE_SAs in manager", 404 this->ike_sa_list->get_count(this->ike_sa_list)); 649 DBG2(DBG_MGR, "checkout IKE_SA by message"); 405 650 406 651 if (message->get_request(message) && … … 408 653 { 409 654 /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */ 410 enumerator_t *enumerator;411 655 chunk_t data, hash; 412 656 413 657 data = message->get_packet_data(message); 414 658 this->hasher->allocate_hash(this->hasher, data, &hash); 415 659 chunk_free(&data); 416 660 417 this->mutex->lock(this->mutex); 418 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); 419 while (enumerator->enumerate(enumerator, &entry)) 420 { 421 if (chunk_equals(hash, entry->init_hash)) 422 { 423 if (entry->message_id == 0) 424 { 425 enumerator->destroy(enumerator); 426 this->mutex->unlock(this->mutex); 427 chunk_free(&hash); 428 id->destroy(id); 429 DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing"); 430 return NULL; 431 } 432 else if (wait_for_entry(this, entry)) 433 { 434 DBG2(DBG_MGR, "IKE_SA checked out by hash"); 435 entry->checked_out = TRUE; 436 entry->message_id = message->get_message_id(message); 437 ike_sa = entry->ike_sa; 438 } 439 break; 440 } 441 } 442 enumerator->destroy(enumerator); 443 this->mutex->unlock(this->mutex); 661 if (get_entry_by_hash(this, id, hash, &entry, &segment) == SUCCESS) 662 { 663 if (entry->message_id == 0) 664 { 665 unlock_single_segment(this, segment); 666 chunk_free(&hash); 667 id->destroy(id); 668 DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing"); 669 return NULL; 670 } 671 else if (wait_for_entry(this, entry, segment)) 672 { 673 DBG2(DBG_MGR, "IKE_SA checked out by hash"); 674 entry->checked_out = TRUE; 675 entry->message_id = message->get_message_id(message); 676 ike_sa = entry->ike_sa; 677 } 678 unlock_single_segment(this, segment); 679 } 444 680 445 681 if (ike_sa == NULL) … … 452 688 entry = entry_create(id); 453 689 454 this->mutex->lock(this->mutex); 455 this->ike_sa_list->insert_last(this->ike_sa_list, entry); 690 segment = put_entry(this, entry); 456 691 entry->checked_out = TRUE; 457 entry->message_id = message->get_message_id(message); 458 this->mutex->unlock(this->mutex); 692 unlock_single_segment(this, segment); 693 694 entry->message_id = message->get_message_id(message); 459 695 entry->init_hash = hash; 460 696 ike_sa = entry->ike_sa; 697 698 DBG2(DBG_MGR, "created IKE_SA"); 461 699 } 462 700 else … … 475 713 } 476 714 477 this->mutex->lock(this->mutex); 478 if (get_entry_by_id(this, id, &entry) == SUCCESS) 715 if (get_entry_by_id(this, id, &entry, &segment) == SUCCESS) 479 716 { 480 717 /* only check out if we are not processing this request */ … … 485 722 entry->message_id); 486 723 } 487 else if (wait_for_entry(this, entry ))724 else if (wait_for_entry(this, entry, segment)) 488 725 { 489 726 ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa); … … 497 734 ike_sa = entry->ike_sa; 498 735 } 499 }500 this->mutex->unlock(this->mutex);736 unlock_single_segment(this, segment); 737 } 501 738 id->destroy(id); 502 739 charon->bus->set_sa(charon->bus, ike_sa); … … 516 753 host_t *my_host, *other_host; 517 754 ike_cfg_t *ike_cfg; 755 u_int segment; 518 756 519 757 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg); … … 523 761 other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0); 524 762 525 this->mutex->lock(this->mutex);526 527 763 if (my_host && other_host && this->reuse_ikesa) 528 764 { 529 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);530 while (enumerator->enumerate(enumerator, &entry ))765 enumerator = create_table_enumerator(this); 766 while (enumerator->enumerate(enumerator, &entry, &segment)) 531 767 { 532 768 identification_t *found_my_id, *found_other_id; 533 769 host_t *found_my_host, *found_other_host; 534 770 535 if (!wait_for_entry(this, entry ))771 if (!wait_for_entry(this, entry, segment)) 536 772 { 537 773 continue; … … 540 776 if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING) 541 777 { 542 /* skip IKE_SA which are not useable */778 /* skip IKE_SAs which are not usable */ 543 779 continue; 544 780 } … … 586 822 if (!ike_sa) 587 823 { 588 u_int64_t initiator_spi;589 824 entry_t *new_entry; 590 825 ike_sa_id_t *new_ike_sa_id; 591 826 592 initiator_spi = get_next_spi(this); 593 new_ike_sa_id = ike_sa_id_create(0, 0, TRUE); 594 new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi); 827 new_ike_sa_id = ike_sa_id_create(get_next_spi(this), 0, TRUE); 595 828 596 829 /* create entry */ 597 830 new_entry = entry_create(new_ike_sa_id); 598 DBG2(DBG_MGR, "created IKE_SA");599 831 new_ike_sa_id->destroy(new_ike_sa_id); 600 832 601 this->ike_sa_list->insert_last(this->ike_sa_list, new_entry);833 segment = put_entry(this, new_entry); 602 834 603 835 /* check ike_sa out */ … … 605 837 new_entry->checked_out = TRUE; 606 838 ike_sa = new_entry->ike_sa; 607 }608 this->mutex->unlock(this->mutex);839 unlock_single_segment(this, segment); 840 } 609 841 charon->bus->set_sa(charon->bus, ike_sa); 610 842 return ike_sa; … … 622 854 ike_sa_t *ike_sa = NULL; 623 855 child_sa_t *child_sa; 624 625 this->mutex->lock(this->mutex); 626 627 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); 628 while (enumerator->enumerate(enumerator, &entry)) 629 { 630 if (wait_for_entry(this, entry)) 856 u_int segment; 857 858 enumerator = create_table_enumerator(this); 859 while (enumerator->enumerate(enumerator, &entry, &segment)) 860 { 861 if (wait_for_entry(this, entry, segment)) 631 862 { 632 863 /* look for a child with such a reqid ... */ … … 660 891 } 661 892 enumerator->destroy(enumerator); 662 this->mutex->unlock(this->mutex);663 893 664 894 charon->bus->set_sa(charon->bus, ike_sa); … … 677 907 ike_sa_t *ike_sa = NULL; 678 908 child_sa_t *child_sa; 679 680 this->mutex->lock(this->mutex); 681 682 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); 683 while (enumerator->enumerate(enumerator, &entry)) 684 { 685 if (wait_for_entry(this, entry)) 909 u_int segment; 910 911 enumerator = create_table_enumerator(this); 912 while (enumerator->enumerate(enumerator, &entry, &segment)) 913 { 914 if (wait_for_entry(this, entry, segment)) 686 915 { 687 916 /* look for a child with such a policy name ... */ … … 715 944 } 716 945 enumerator->destroy(enumerator); 717 this->mutex->unlock(this->mutex);718 946 719 947 charon->bus->set_sa(charon->bus, ike_sa); … … 731 959 ike_sa_t *duplicate = NULL; 732 960 identification_t *me, *other; 961 u_int segment; 733 962 734 963 me = ike_sa->get_my_id(ike_sa); 735 964 other = ike_sa->get_other_id(ike_sa); 736 965 737 this->mutex->lock(this->mutex); 738 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); 739 while (enumerator->enumerate(enumerator, &entry)) 966 enumerator = create_table_enumerator(this); 967 while (enumerator->enumerate(enumerator, &entry, &segment)) 740 968 { 741 969 if (entry->ike_sa == ike_sa) … … 749 977 * checkout_duplicate here, as the identities in entry would not 750 978 * have been set yet. Otherwise we would risk a deadlock. */ 751 if (wait_for_entry(this, entry ))979 if (wait_for_entry(this, entry, segment)) 752 980 { 753 981 duplicate = entry->ike_sa; … … 758 986 } 759 987 enumerator->destroy(enumerator); 760 this->mutex->unlock(this->mutex);761 988 return duplicate; 762 989 } 763 990 764 991 /** 765 * enumerator cleanup function766 */767 static void enumerator_unlock(private_ike_sa_manager_t *this)768 {769 this->mutex->unlock(this->mutex);770 }771 772 /**773 992 * enumerator filter function 774 993 */ 775 994 static bool enumerator_filter(private_ike_sa_manager_t *this, 776 entry_t **in, ike_sa_t **out )777 { 778 if (wait_for_entry(this, *in ))995 entry_t **in, ike_sa_t **out, u_int *segment) 996 { 997 if (wait_for_entry(this, *in, *segment)) 779 998 { 780 999 *out = (*in)->ike_sa; … … 785 1004 786 1005 /** 787 * Implementation of ike_sa_manager_t.create_ iterator.1006 * Implementation of ike_sa_manager_t.create_enumerator. 788 1007 */ 789 1008 static enumerator_t *create_enumerator(private_ike_sa_manager_t* this) 790 1009 { 791 this->mutex->lock(this->mutex);792 1010 return enumerator_create_filter( 793 this->ike_sa_list->create_enumerator(this->ike_sa_list),794 (void*)enumerator_filter, this, (void*)enumerator_unlock);1011 create_table_enumerator(this), 1012 (void*)enumerator_filter, this, NULL); 795 1013 } 796 1014 … … 802 1020 /* to check the SA back in, we look for the pointer of the ike_sa 803 1021 * in all entries. 804 * We can't search by SPI's since the MAY have changed (e.g. on reception 805 * of a IKE_SA_INIT response). Updating of the SPI MAY be necessary... 1022 * The lookup is done by initiator SPI, so even if the SPI has changed (e.g. 1023 * on reception of a IKE_SA_INIT response) the lookup will work but 1024 * updating of the SPI MAY be necessary... 806 1025 */ 807 1026 status_t retval; … … 810 1029 host_t *other; 811 1030 identification_t *my_id, *other_id; 1031 u_int segment; 812 1032 813 1033 ike_sa_id = ike_sa->get_id(ike_sa); … … 815 1035 DBG2(DBG_MGR, "checkin IKE_SA"); 816 1036 817 this->mutex->lock(this->mutex);818 819 1037 /* look for the entry */ 820 if (get_entry_by_sa(this, ike_sa , &entry) == SUCCESS)1038 if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS) 821 1039 { 822 1040 /* ike_sa_id must be updated */ … … 832 1050 entry->other = other->clone(other); 833 1051 } 834 /* apply identities for d iplicate test */1052 /* apply identities for duplicate test */ 835 1053 my_id = ike_sa->get_my_id(ike_sa); 836 1054 other_id = ike_sa->get_other_id(ike_sa); … … 850 1068 entry->condvar->signal(entry->condvar); 851 1069 retval = SUCCESS; 1070 unlock_single_segment(this, segment); 852 1071 } 853 1072 else … … 858 1077 } 859 1078 860 DBG2(DBG_MGR, "%d IKE_SAs in manager now",861 this->ike_sa_list->get_count(this->ike_sa_list));862 this->mutex->unlock(this->mutex);863 864 1079 charon->bus->set_sa(charon->bus, NULL); 865 1080 return retval; … … 872 1087 static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa) 873 1088 { 874 /* deletion is a bit complex, we must garantthat no thread is waiting for1089 /* deletion is a bit complex, we must ensure that no thread is waiting for 875 1090 * this SA. 876 * We take this SA from the list, and start signaling while threads1091 * We take this SA from the table, and start signaling while threads 877 1092 * are in the condvar. 878 1093 */ … … 880 1095 status_t retval; 881 1096 ike_sa_id_t *ike_sa_id; 1097 u_int segment; 882 1098 883 1099 ike_sa_id = ike_sa->get_id(ike_sa); 1100 884 1101 DBG2(DBG_MGR, "checkin and destroy IKE_SA"); 885 1102 886 this->mutex->lock(this->mutex); 887 888 if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS) 1103 if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS) 889 1104 { 890 1105 /* drive out waiting threads, as we are in hurry */ 891 1106 entry->driveout_waiting_threads = TRUE; 892 893 delete_entry(this, entry); 1107 /* mark it, so no new threads can get this entry */ 1108 entry->driveout_new_threads = TRUE; 1109 /* wait until all workers have done their work */ 1110 while (entry->waiting_threads) 1111 { 1112 /* wake up all */ 1113 entry->condvar->broadcast(entry->condvar); 1114 /* they will wake us again when their work is done */ 1115 entry->condvar->wait(entry->condvar, this->segments[segment].mutex); 1116 } 1117 1118 remove_entry(this, entry); 1119 entry_destroy(entry); 1120 unlock_single_segment(this, segment); 894 1121 895 1122 DBG2(DBG_MGR, "check-in and destroy of IKE_SA successful"); … … 902 1129 } 903 1130 charon->bus->set_sa(charon->bus, NULL); 904 905 this->mutex->unlock(this->mutex);906 1131 return retval; 907 1132 } … … 916 1141 int count = 0; 917 1142 918 this->mutex->lock(this->mutex); 919 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list); 1143 enumerator = create_table_enumerator(this); 920 1144 while (enumerator->enumerate(enumerator, &entry)) 921 1145 { … … 940 1164 enumerator->destroy(enumerator); 941 1165 942 this->mutex->unlock(this->mutex);943 1166 return count; 944 1167 } … … 952 1175 enumerator_t *enumerator; 953 1176 entry_t *entry; 954 955 this->mutex->lock(this->mutex); 1177 u_int segment; 1178 1179 lock_all_segments(this); 956 1180 DBG2(DBG_MGR, "going to destroy IKE_SA manager and all managed IKE_SA's"); 957 1181 /* Step 1: drive out all waiting threads */ 958 1182 DBG2(DBG_MGR, "set driveout flags for all stored IKE_SA's"); 959 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);960 while (enumerator->enumerate(enumerator, &entry ))1183 enumerator = create_table_enumerator(this); 1184 while (enumerator->enumerate(enumerator, &entry, &segment)) 961 1185 { 962 1186 /* do not accept new threads, drive out waiting threads */ … … 967 1191 DBG2(DBG_MGR, "wait for all threads to leave IKE_SA's"); 968 1192 /* Step 2: wait until all are gone */ 969 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);970 while (enumerator->enumerate(enumerator, &entry ))1193 enumerator = create_table_enumerator(this); 1194 while (enumerator->enumerate(enumerator, &entry, &segment)) 971 1195 { 972 1196 while (entry->waiting_threads) … … 975 1199 entry->condvar->broadcast(entry->condvar); 976 1200 /* go sleeping until they are gone */ 977 entry->condvar->wait(entry->condvar, this-> mutex);1201 entry->condvar->wait(entry->condvar, this->segments[segment].mutex); 978 1202 } 979 1203 } … … 981 1205 DBG2(DBG_MGR, "delete all IKE_SA's"); 982 1206 /* Step 3: initiate deletion of all IKE_SAs */ 983 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);984 while (enumerator->enumerate(enumerator, &entry ))1207 enumerator = create_table_enumerator(this); 1208 while (enumerator->enumerate(enumerator, &entry, &segment)) 985 1209 { 986 1210 charon->bus->set_sa(charon->bus, entry->ike_sa); … … 991 1215 DBG2(DBG_MGR, "destroy all entries"); 992 1216 /* Step 4: destroy all entries */ 993 while (this->ike_sa_list->remove_last(this->ike_sa_list,994 (void**)&entry) == SUCCESS)1217 enumerator = create_table_enumerator(this); 1218 while (enumerator->enumerate(enumerator, &entry, &segment)) 995 1219 { 996 1220 charon->bus->set_sa(charon->bus, entry->ike_sa); 1221 remove_entry_at((private_enumerator_t*)enumerator); 997 1222 entry_destroy(entry); 998 1223 } 1224 enumerator->destroy(enumerator); 999 1225 charon->bus->set_sa(charon->bus, NULL); 1000 this->mutex->unlock(this->mutex);1226 unlock_all_segments(this); 1001 1227 } 1002 1228 … … 1006 1232 static void destroy(private_ike_sa_manager_t *this) 1007 1233 { 1008 this->ike_sa_list->destroy(this->ike_sa_list); 1234 u_int i; 1235 for (i = 0; i < this->table_size; ++i) 1236 { 1237 linked_list_t *list; 1238 if ((list = this->ike_sa_table[i]) != NULL) 1239 { 1240 list->destroy(list); 1241 } 1242 } 1243 free(this->ike_sa_table); 1244 for (i = 0; i < this->segment_count; ++i) 1245 { 1
