1/* $NetBSD: handler.c,v 1.42 2018/05/19 20:14:56 maxv Exp $ */ 2 3/* Id: handler.c,v 1.28 2006/05/26 12:17:29 manubsd Exp */ 4 5/* 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "config.h" 35 36#include <sys/types.h> 37#include <sys/param.h> 38#include <sys/socket.h> 39 40#include <stdlib.h> 41#include <stdio.h> 42#include <string.h> 43#include <time.h> 44#include <errno.h> 45 46#include "var.h" 47#include "misc.h" 48#include "vmbuf.h" 49#include "plog.h" 50#include "sockmisc.h" 51#include "debug.h" 52 53#ifdef ENABLE_HYBRID 54#include <resolv.h> 55#endif 56 57#include "schedule.h" 58#include "grabmyaddr.h" 59#include "algorithm.h" 60#include "crypto_openssl.h" 61#include "policy.h" 62#include "proposal.h" 63#include "isakmp_var.h" 64#include "evt.h" 65#include "isakmp.h" 66#ifdef ENABLE_HYBRID 67#include "isakmp_xauth.h" 68#include "isakmp_cfg.h" 69#endif 70#include "isakmp_inf.h" 71#include "oakley.h" 72#include "remoteconf.h" 73#include "localconf.h" 74#include "handler.h" 75#include "gcmalloc.h" 76#include "nattraversal.h" 77 78#include "sainfo.h" 79 80#ifdef HAVE_GSSAPI 81#include "gssapi.h" 82#endif 83 84static LIST_HEAD(_ph1tree_, ph1handle) ph1tree; 85static LIST_HEAD(_ph2tree_, ph2handle) ph2tree; 86static LIST_HEAD(_ctdtree_, contacted) ctdtree; 87static LIST_HEAD(_rcptree_, recvdpkt) rcptree; 88static struct sched sc_sweep = SCHED_INITIALIZER(); 89 90static void del_recvdpkt __P((struct recvdpkt *)); 91static void rem_recvdpkt __P((struct recvdpkt *)); 92 93/* 94 * functions about management of the isakmp status table 95 */ 96/* %%% management phase 1 handler */ 97/* 98 * search for isakmpsa handler with isakmp index. 99 */ 100 101extern caddr_t val2str(const char *, size_t); 102 103/* 104 * Enumerate the Phase 1 tree. 105 * If enum_func() internally return a non-zero value, this specific 106 * error value is returned. 0 is returned if everything went right. 107 * 108 * Note that it is ok for enum_func() to call insph1(). Those inserted 109 * Phase 1 will not interfere with current enumeration process. 110 */ 111int 112enumph1(sel, enum_func, enum_arg) 113 struct ph1selector *sel; 114 int (* enum_func)(struct ph1handle *iph1, void *arg); 115 void *enum_arg; 116{ 117 struct ph1handle *p; 118 int ret; 119 120 LIST_FOREACH(p, &ph1tree, chain) { 121 if (sel != NULL) { 122 if (sel->local != NULL && 123 cmpsaddr(sel->local, p->local) > CMPSADDR_WILDPORT_MATCH) 124 continue; 125 126 if (sel->remote != NULL && 127 cmpsaddr(sel->remote, p->remote) > CMPSADDR_WILDPORT_MATCH) 128 continue; 129 } 130 131 if ((ret = enum_func(p, enum_arg)) != 0) 132 return ret; 133 } 134 135 return 0; 136} 137 138struct ph1handle * 139getph1byindex(index) 140 isakmp_index *index; 141{ 142 struct ph1handle *p; 143 144 LIST_FOREACH(p, &ph1tree, chain) { 145 if (p->status >= PHASE1ST_EXPIRED) 146 continue; 147 if (memcmp(&p->index, index, sizeof(*index)) == 0) 148 return p; 149 } 150 151 return NULL; 152} 153 154 155/* 156 * search for isakmp handler by i_ck in index. 157 */ 158struct ph1handle * 159getph1byindex0(index) 160 isakmp_index *index; 161{ 162 struct ph1handle *p; 163 164 LIST_FOREACH(p, &ph1tree, chain) { 165 if (p->status >= PHASE1ST_EXPIRED) 166 continue; 167 if (memcmp(&p->index, index, sizeof(cookie_t)) == 0) 168 return p; 169 } 170 171 return NULL; 172} 173 174/* 175 * search for isakmpsa handler by source and remote address. 176 * don't use port number to search because this function search 177 * with phase 2's destinaion. 178 */ 179struct ph1handle * 180getph1(ph1hint, local, remote, flags) 181 struct ph1handle *ph1hint; 182 struct sockaddr *local, *remote; 183 int flags; 184{ 185 struct ph1handle *p; 186 187 plog(LLV_DEBUG2, LOCATION, NULL, "getph1: start\n"); 188 plog(LLV_DEBUG2, LOCATION, NULL, "local: %s\n", saddr2str(local)); 189 plog(LLV_DEBUG2, LOCATION, NULL, "remote: %s\n", saddr2str(remote)); 190 191 LIST_FOREACH(p, &ph1tree, chain) { 192 if (p->status >= PHASE1ST_DYING) 193 continue; 194 195 plog(LLV_DEBUG2, LOCATION, NULL, "p->local: %s\n", saddr2str(p->local)); 196 plog(LLV_DEBUG2, LOCATION, NULL, "p->remote: %s\n", saddr2str(p->remote)); 197 198 if ((flags & GETPH1_F_ESTABLISHED) && 199 (p->status != PHASE1ST_ESTABLISHED)) { 200 plog(LLV_DEBUG2, LOCATION, NULL, 201 "status %d, skipping\n", p->status); 202 continue; 203 } 204 205 if (local != NULL && cmpsaddr(local, p->local) == CMPSADDR_MISMATCH) 206 continue; 207 208 if (remote != NULL && cmpsaddr(remote, p->remote) == CMPSADDR_MISMATCH) 209 continue; 210 211 if (ph1hint != NULL) { 212 if (ph1hint->id && ph1hint->id->l && p->id && p->id->l && 213 (ph1hint->id->l != p->id->l || 214 memcmp(ph1hint->id->v, p->id->v, p->id->l) != 0)) { 215 plog(LLV_DEBUG2, LOCATION, NULL, 216 "local identity does not match hint\n"); 217 continue; 218 } 219 if (ph1hint->id_p && ph1hint->id_p->l && 220 p->id_p && p->id_p->l && 221 (ph1hint->id_p->l != p->id_p->l || 222 memcmp(ph1hint->id_p->v, p->id_p->v, p->id_p->l) != 0)) { 223 plog(LLV_DEBUG2, LOCATION, NULL, 224 "remote identity does not match hint\n"); 225 continue; 226 } 227 } 228 229 plog(LLV_DEBUG2, LOCATION, NULL, "matched\n"); 230 return p; 231 } 232 233 plog(LLV_DEBUG2, LOCATION, NULL, "no match\n"); 234 235 return NULL; 236} 237 238int 239resolveph1rmconf(iph1) 240 struct ph1handle *iph1; 241{ 242 struct remoteconf *rmconf; 243 244 /* INITIATOR is always expected to know the exact rmconf. */ 245 if (iph1->side == INITIATOR) 246 return 0; 247 248 rmconf = getrmconf_by_ph1(iph1); 249 if (rmconf == NULL) 250 return -1; 251 if (rmconf == RMCONF_ERR_MULTIPLE) 252 return 1; 253 254 if (iph1->rmconf != NULL) { 255 if (rmconf != iph1->rmconf) { 256 plog(LLV_ERROR, LOCATION, NULL, 257 "unexpected rmconf switch; killing ph1\n"); 258 return -1; 259 } 260 } else { 261 iph1->rmconf = rmconf; 262 } 263 264 return 0; 265} 266 267 268/* 269 * move phase2s from old_iph1 to new_iph1 270 */ 271void 272migrate_ph12(old_iph1, new_iph1) 273 struct ph1handle *old_iph1, *new_iph1; 274{ 275 struct ph2handle *p, *next; 276 277 /* Relocate phase2s to better phase1s or request a new phase1. */ 278 for (p = LIST_FIRST(&old_iph1->ph2tree); p; p = next) { 279 next = LIST_NEXT(p, ph1bind); 280 281 if (p->status != PHASE2ST_ESTABLISHED) 282 continue; 283 284 unbindph12(p); 285 bindph12(new_iph1, p); 286 } 287} 288 289/* 290 * the iph1 is new, migrate all phase2s that belong to a dying or dead ph1 291 */ 292void migrate_dying_ph12(iph1) 293 struct ph1handle *iph1; 294{ 295 struct ph1handle *p; 296 297 LIST_FOREACH(p, &ph1tree, chain) { 298 if (p == iph1) 299 continue; 300 if (p->status < PHASE1ST_DYING) 301 continue; 302 303 if (cmpsaddr(iph1->local, p->local) == CMPSADDR_MATCH 304 && cmpsaddr(iph1->remote, p->remote) == CMPSADDR_MATCH) 305 migrate_ph12(p, iph1); 306 } 307} 308 309 310/* 311 * dump isakmp-sa 312 */ 313vchar_t * 314dumpph1() 315{ 316 struct ph1handle *iph1; 317 struct ph1dump *pd; 318 int cnt = 0; 319 vchar_t *buf; 320 321 /* get length of buffer */ 322 LIST_FOREACH(iph1, &ph1tree, chain) 323 cnt++; 324 325 buf = vmalloc(cnt * sizeof(struct ph1dump)); 326 if (buf == NULL) { 327 plog(LLV_ERROR, LOCATION, NULL, 328 "failed to get buffer\n"); 329 return NULL; 330 } 331 pd = (struct ph1dump *)buf->v; 332 333 LIST_FOREACH(iph1, &ph1tree, chain) { 334 memcpy(&pd->index, &iph1->index, sizeof(iph1->index)); 335 pd->status = iph1->status; 336 pd->side = iph1->side; 337 memcpy(&pd->remote, iph1->remote, sysdep_sa_len(iph1->remote)); 338 memcpy(&pd->local, iph1->local, sysdep_sa_len(iph1->local)); 339 pd->version = iph1->version; 340 pd->etype = iph1->etype; 341 pd->created = iph1->created; 342 pd->ph2cnt = iph1->ph2cnt; 343 pd++; 344 } 345 346 return buf; 347} 348 349/* 350 * create new isakmp Phase 1 status record to handle isakmp in Phase1 351 */ 352struct ph1handle * 353newph1() 354{ 355 struct ph1handle *iph1; 356 357 /* create new iph1 */ 358 iph1 = racoon_calloc(1, sizeof(*iph1)); 359 if (iph1 == NULL) 360 return NULL; 361 362 iph1->status = PHASE1ST_SPAWN; 363 364#ifdef ENABLE_DPD 365 iph1->dpd_support = 0; 366 iph1->dpd_seq = 0; 367 iph1->dpd_fails = 0; 368#endif 369 evt_list_init(&iph1->evt_listeners); 370 371 return iph1; 372} 373 374/* 375 * delete new isakmp Phase 1 status record to handle isakmp in Phase1 376 */ 377void 378delph1(iph1) 379 struct ph1handle *iph1; 380{ 381 if (iph1 == NULL) 382 return; 383 384 /* SA down shell script hook */ 385 script_hook(iph1, SCRIPT_PHASE1_DOWN); 386 evt_list_cleanup(&iph1->evt_listeners); 387 388#ifdef ENABLE_NATT 389 if (iph1->natt_flags & NAT_KA_QUEUED) 390 natt_keepalive_remove (iph1->local, iph1->remote); 391 392 if (iph1->natt_options) { 393 racoon_free(iph1->natt_options); 394 iph1->natt_options = NULL; 395 } 396#endif 397 398#ifdef ENABLE_HYBRID 399 if (iph1->mode_cfg) 400 isakmp_cfg_rmstate(iph1); 401#endif 402 403#ifdef ENABLE_DPD 404 sched_cancel(&iph1->dpd_r_u); 405#endif 406 sched_cancel(&iph1->sce); 407 sched_cancel(&iph1->scr); 408 409 if (iph1->remote) { 410 racoon_free(iph1->remote); 411 iph1->remote = NULL; 412 } 413 if (iph1->local) { 414 racoon_free(iph1->local); 415 iph1->local = NULL; 416 } 417 if (iph1->approval) { 418 delisakmpsa(iph1->approval); 419 iph1->approval = NULL; 420 } 421 422 VPTRINIT(iph1->authstr); 423 VPTRINIT(iph1->sendbuf); 424 VPTRINIT(iph1->dhpriv); 425 VPTRINIT(iph1->dhpub); 426 VPTRINIT(iph1->dhpub_p); 427 VPTRINIT(iph1->dhgxy); 428 VPTRINIT(iph1->nonce); 429 VPTRINIT(iph1->nonce_p); 430 VPTRINIT(iph1->skeyid); 431 VPTRINIT(iph1->skeyid_d); 432 VPTRINIT(iph1->skeyid_a); 433 VPTRINIT(iph1->skeyid_e); 434 VPTRINIT(iph1->key); 435 VPTRINIT(iph1->hash); 436 VPTRINIT(iph1->sig); 437 VPTRINIT(iph1->sig_p); 438 VPTRINIT(iph1->cert); 439 VPTRINIT(iph1->cert_p); 440 VPTRINIT(iph1->crl_p); 441 VPTRINIT(iph1->cr_p); 442 VPTRINIT(iph1->id); 443 VPTRINIT(iph1->id_p); 444 445 if(iph1->approval != NULL) 446 delisakmpsa(iph1->approval); 447 448 if (iph1->ivm) { 449 oakley_delivm(iph1->ivm); 450 iph1->ivm = NULL; 451 } 452 453 VPTRINIT(iph1->sa); 454 VPTRINIT(iph1->sa_ret); 455 456#ifdef HAVE_GSSAPI 457 VPTRINIT(iph1->gi_i); 458 VPTRINIT(iph1->gi_r); 459 460 gssapi_free_state(iph1); 461#endif 462 463 racoon_free(iph1); 464} 465 466/* 467 * create new isakmp Phase 1 status record to handle isakmp in Phase1 468 */ 469int 470insph1(iph1) 471 struct ph1handle *iph1; 472{ 473 /* validity check */ 474 if (iph1->remote == NULL) { 475 plog(LLV_ERROR, LOCATION, NULL, 476 "invalid isakmp SA handler. no remote address.\n"); 477 return -1; 478 } 479 LIST_INSERT_HEAD(&ph1tree, iph1, chain); 480 481 return 0; 482} 483 484void 485remph1(iph1) 486 struct ph1handle *iph1; 487{ 488 LIST_REMOVE(iph1, chain); 489} 490 491/* 492 * flush isakmp-sa 493 */ 494void 495flushph1() 496{ 497 struct ph1handle *p, *next; 498 499 for (p = LIST_FIRST(&ph1tree); p; p = next) { 500 next = LIST_NEXT(p, chain); 501 502 /* send delete information */ 503 if (p->status >= PHASE1ST_ESTABLISHED) 504 isakmp_info_send_d1(p); 505 506 remph1(p); 507 delph1(p); 508 } 509} 510 511void 512initph1tree() 513{ 514 LIST_INIT(&ph1tree); 515} 516 517int 518ph1_rekey_enabled(iph1) 519 struct ph1handle *iph1; 520{ 521 if (iph1->rmconf == NULL) 522 return 0; 523 if (iph1->rmconf->rekey == REKEY_FORCE) 524 return 1; 525#ifdef ENABLE_DPD 526 if (iph1->rmconf->rekey == REKEY_ON && iph1->dpd_support && 527 iph1->rmconf->dpd_interval) 528 return 1; 529#endif 530 return 0; 531} 532 533/* %%% management phase 2 handler */ 534 535int 536enumph2(sel, enum_func, enum_arg) 537 struct ph2selector *sel; 538 int (*enum_func)(struct ph2handle *ph2, void *arg); 539 void *enum_arg; 540{ 541 struct ph2handle *p; 542 int ret; 543 544 LIST_FOREACH(p, &ph2tree, chain) { 545 if (sel != NULL) { 546 if (sel->spid != 0 && sel->spid != p->spid) 547 continue; 548 549 if (sel->src != NULL && 550 cmpsaddr(sel->src, p->src) != CMPSADDR_MATCH) 551 continue; 552 553 if (sel->dst != NULL && 554 cmpsaddr(sel->dst, p->dst) != CMPSADDR_MATCH) 555 continue; 556 } 557 558 if ((ret = enum_func(p, enum_arg)) != 0) 559 return ret; 560 } 561 562 return 0; 563} 564 565/* 566 * search ph2handle with sequence number. 567 */ 568struct ph2handle * 569getph2byseq(seq) 570 u_int32_t seq; 571{ 572 struct ph2handle *p; 573 574 LIST_FOREACH(p, &ph2tree, chain) { 575 if (p->seq == seq) 576 return p; 577 } 578 579 return NULL; 580} 581 582/* 583 * search ph2handle with message id. 584 */ 585struct ph2handle * 586getph2bymsgid(iph1, msgid) 587 struct ph1handle *iph1; 588 u_int32_t msgid; 589{ 590 struct ph2handle *p; 591 592 LIST_FOREACH(p, &iph1->ph2tree, ph1bind) { 593 if (p->msgid == msgid && p->ph1 == iph1) 594 return p; 595 } 596 597 return NULL; 598} 599 600/* Note that src and dst are not the selectors of the SP 601 * but the source and destination addresses used for 602 * for SA negotiation (best example is tunnel mode SA 603 * where src and dst are the endpoints). There is at most 604 * a unique match because racoon does not support bundles 605 * which makes that there is at most a single established 606 * SA for a given spid. One could say that src and dst 607 * are in fact useless ... 608 */ 609struct ph2handle * 610getph2byid(src, dst, spid) 611 struct sockaddr *src, *dst; 612 u_int32_t spid; 613{ 614 struct ph2handle *p, *next; 615 616 for (p = LIST_FIRST(&ph2tree); p; p = next) { 617 next = LIST_NEXT(p, chain); 618 619 if (spid == p->spid && 620 cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH && 621 cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH){ 622 /* Sanity check to detect zombie handlers 623 * XXX Sould be done "somewhere" more interesting, 624 * because we have lots of getph2byxxxx(), but this one 625 * is called by pk_recvacquire(), so is the most important. 626 */ 627 if(p->status < PHASE2ST_ESTABLISHED && 628 p->retry_counter == 0 629 && p->sce.func == NULL && p->scr.func == NULL) { 630 plog(LLV_DEBUG, LOCATION, NULL, 631 "Zombie ph2 found, expiring it\n"); 632 isakmp_ph2expire(p); 633 }else 634 return p; 635 } 636 } 637 638 return NULL; 639} 640 641struct ph2handle * 642getph2bysaddr(src, dst) 643 struct sockaddr *src, *dst; 644{ 645 struct ph2handle *p; 646 647 LIST_FOREACH(p, &ph2tree, chain) { 648 if (cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH && 649 cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH) 650 return p; 651 } 652 653 return NULL; 654} 655 656/* 657 * call by pk_recvexpire(). 658 */ 659struct ph2handle * 660getph2bysaidx(src, dst, proto_id, spi) 661 struct sockaddr *src, *dst; 662 u_int proto_id; 663 u_int32_t spi; 664{ 665 struct ph2handle *iph2; 666 struct saproto *pr; 667 668 LIST_FOREACH(iph2, &ph2tree, chain) { 669 if (iph2->proposal == NULL && iph2->approval == NULL) 670 continue; 671 if (iph2->approval != NULL) { 672 for (pr = iph2->approval->head; pr != NULL; 673 pr = pr->next) { 674 if (proto_id != pr->proto_id) 675 break; 676 if (spi == pr->spi || spi == pr->spi_p) 677 return iph2; 678 } 679 } else if (iph2->proposal != NULL) { 680 for (pr = iph2->proposal->head; pr != NULL; 681 pr = pr->next) { 682 if (proto_id != pr->proto_id) 683 break; 684 if (spi == pr->spi) 685 return iph2; 686 } 687 } 688 } 689 690 return NULL; 691} 692 693/* 694 * create new isakmp Phase 2 status record to handle isakmp in Phase2 695 */ 696struct ph2handle * 697newph2() 698{ 699 struct ph2handle *iph2 = NULL; 700 701 /* create new iph2 */ 702 iph2 = racoon_calloc(1, sizeof(*iph2)); 703 if (iph2 == NULL) 704 return NULL; 705 706 iph2->status = PHASE1ST_SPAWN; 707 evt_list_init(&iph2->evt_listeners); 708 709 return iph2; 710} 711 712/* 713 * initialize ph2handle 714 * NOTE: don't initialize src/dst. 715 * SPI in the proposal is cleared. 716 */ 717void 718initph2(iph2) 719 struct ph2handle *iph2; 720{ 721 evt_list_cleanup(&iph2->evt_listeners); 722 unbindph12(iph2); 723 724 sched_cancel(&iph2->sce); 725 sched_cancel(&iph2->scr); 726 727 VPTRINIT(iph2->sendbuf); 728 VPTRINIT(iph2->msg1); 729 730 /* clear spi, keep variables in the proposal */ 731 if (iph2->proposal) { 732 struct saproto *pr; 733 for (pr = iph2->proposal->head; pr != NULL; pr = pr->next) 734 pr->spi = 0; 735 } 736 737 /* clear approval */ 738 if (iph2->approval) { 739 flushsaprop(iph2->approval); 740 iph2->approval = NULL; 741 } 742 743 /* clear the generated policy */ 744 if (iph2->spidx_gen) { 745 delsp_bothdir((struct policyindex *)iph2->spidx_gen); 746 racoon_free(iph2->spidx_gen); 747 iph2->spidx_gen = NULL; 748 } 749 750 if (iph2->pfsgrp) { 751 oakley_dhgrp_free(iph2->pfsgrp); 752 iph2->pfsgrp = NULL; 753 } 754 755 VPTRINIT(iph2->dhpriv); 756 VPTRINIT(iph2->dhpub); 757 VPTRINIT(iph2->dhpub_p); 758 VPTRINIT(iph2->dhgxy); 759 VPTRINIT(iph2->id); 760 VPTRINIT(iph2->id_p); 761 VPTRINIT(iph2->nonce); 762 VPTRINIT(iph2->nonce_p); 763 VPTRINIT(iph2->sa); 764 VPTRINIT(iph2->sa_ret); 765 766 if (iph2->ivm) { 767 oakley_delivm(iph2->ivm); 768 iph2->ivm = NULL; 769 } 770 771#ifdef ENABLE_NATT 772 if (iph2->natoa_src) { 773 racoon_free(iph2->natoa_src); 774 iph2->natoa_src = NULL; 775 } 776 if (iph2->natoa_dst) { 777 racoon_free(iph2->natoa_dst); 778 iph2->natoa_dst = NULL; 779 } 780#endif 781} 782 783/* 784 * delete new isakmp Phase 2 status record to handle isakmp in Phase2 785 */ 786void 787delph2(iph2) 788 struct ph2handle *iph2; 789{ 790 initph2(iph2); 791 792 if (iph2->src) { 793 racoon_free(iph2->src); 794 iph2->src = NULL; 795 } 796 if (iph2->dst) { 797 racoon_free(iph2->dst); 798 iph2->dst = NULL; 799 } 800 if (iph2->sa_src) { 801 racoon_free(iph2->sa_src); 802 iph2->sa_src = NULL; 803 } 804 if (iph2->sa_dst) { 805 racoon_free(iph2->sa_dst); 806 iph2->sa_dst = NULL; 807 } 808#ifdef ENABLE_NATT 809 if (iph2->natoa_src) { 810 racoon_free(iph2->natoa_src); 811 iph2->natoa_src = NULL; 812 } 813 if (iph2->natoa_dst) { 814 racoon_free(iph2->natoa_dst); 815 iph2->natoa_dst = NULL; 816 } 817#endif 818 819 if (iph2->proposal) { 820 flushsaprop(iph2->proposal); 821 iph2->proposal = NULL; 822 } 823 824 racoon_free(iph2); 825} 826 827/* 828 * create new isakmp Phase 2 status record to handle isakmp in Phase2 829 */ 830int 831insph2(iph2) 832 struct ph2handle *iph2; 833{ 834 LIST_INSERT_HEAD(&ph2tree, iph2, chain); 835 836 return 0; 837} 838 839void 840remph2(iph2) 841 struct ph2handle *iph2; 842{ 843 unbindph12(iph2); 844 LIST_REMOVE(iph2, chain); 845} 846 847void 848initph2tree() 849{ 850 LIST_INIT(&ph2tree); 851} 852 853void 854flushph2() 855{ 856 struct ph2handle *p, *next; 857 858 plog(LLV_DEBUG2, LOCATION, NULL, 859 "flushing all ph2 handlers...\n"); 860 861 for (p = LIST_FIRST(&ph2tree); p; p = next) { 862 next = LIST_NEXT(p, chain); 863 864 /* send delete information */ 865 if (p->status == PHASE2ST_ESTABLISHED){ 866 plog(LLV_DEBUG2, LOCATION, NULL, 867 "got a ph2 handler to flush...\n"); 868 isakmp_info_send_d2(p); 869 }else{ 870 plog(LLV_DEBUG2, LOCATION, NULL, 871 "skipping ph2 handler (state %d)\n", p->status); 872 } 873 874 delete_spd(p, 0); 875 remph2(p); 876 delph2(p); 877 } 878} 879 880/* 881 * Delete all Phase 2 handlers for this src/dst/proto. This 882 * is used during INITIAL-CONTACT processing (so no need to 883 * send a message to the peer). 884 */ 885void 886deleteallph2(src, dst, proto_id) 887 struct sockaddr *src, *dst; 888 u_int proto_id; 889{ 890 struct ph2handle *iph2, *next; 891 struct saproto *pr; 892 893 for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) { 894 next = LIST_NEXT(iph2, chain); 895 if (iph2->proposal == NULL && iph2->approval == NULL) 896 continue; 897 if (iph2->approval != NULL) { 898 for (pr = iph2->approval->head; pr != NULL; 899 pr = pr->next) { 900 if (proto_id == pr->proto_id) 901 goto zap_it; 902 } 903 } else if (iph2->proposal != NULL) { 904 for (pr = iph2->proposal->head; pr != NULL; 905 pr = pr->next) { 906 if (proto_id == pr->proto_id) 907 goto zap_it; 908 } 909 } 910 continue; 911 zap_it: 912 remph2(iph2); 913 delph2(iph2); 914 } 915} 916 917/* %%% */ 918void 919bindph12(iph1, iph2) 920 struct ph1handle *iph1; 921 struct ph2handle *iph2; 922{ 923 unbindph12(iph2); 924 925 iph2->ph1 = iph1; 926 iph1->ph2cnt++; 927 LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind); 928} 929 930void 931unbindph12(iph2) 932 struct ph2handle *iph2; 933{ 934 if (iph2->ph1 != NULL) { 935 LIST_REMOVE(iph2, ph1bind); 936 iph2->ph1->ph2cnt--; 937 iph2->ph1 = NULL; 938 } 939} 940 941/* %%% management contacted list */ 942/* 943 * search contacted list. 944 */ 945struct contacted * 946getcontacted(remote) 947 struct sockaddr *remote; 948{ 949 struct contacted *p; 950 951 LIST_FOREACH(p, &ctdtree, chain) { 952 if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH) 953 return p; 954 } 955 956 return NULL; 957} 958 959/* 960 * create new isakmp Phase 2 status record to handle isakmp in Phase2 961 */ 962int 963inscontacted(remote) 964 struct sockaddr *remote; 965{ 966 struct contacted *new; 967 968 /* create new iph2 */ 969 new = racoon_calloc(1, sizeof(*new)); 970 if (new == NULL) 971 return -1; 972 973 new->remote = dupsaddr(remote); 974 if (new->remote == NULL) { 975 plog(LLV_ERROR, LOCATION, NULL, 976 "failed to allocate buffer.\n"); 977 racoon_free(new); 978 return -1; 979 } 980 981 LIST_INSERT_HEAD(&ctdtree, new, chain); 982 983 return 0; 984} 985 986void 987remcontacted(remote) 988 struct sockaddr *remote; 989{ 990 struct contacted *p, *next; 991 992 for (p = LIST_FIRST(&ctdtree); p; p = next) { 993 next = LIST_NEXT(p, chain); 994 995 if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH) { 996 LIST_REMOVE(p, chain); 997 racoon_free(p->remote); 998 racoon_free(p); 999 break; 1000 } 1001 } 1002} 1003 1004void 1005initctdtree() 1006{ 1007 LIST_INIT(&ctdtree); 1008} 1009 1010/* 1011 * check the response has been sent to the peer. when not, simply reply 1012 * the buffered packet to the peer. 1013 * OUT: 1014 * 0: the packet is received at the first time. 1015 * 1: the packet was processed before. 1016 * 2: the packet was processed before, but the address mismatches. 1017 * -1: error happened. 1018 */ 1019int 1020check_recvdpkt(remote, local, rbuf) 1021 struct sockaddr *remote, *local; 1022 vchar_t *rbuf; 1023{ 1024 vchar_t *hash; 1025 struct recvdpkt *r; 1026 struct timeval now, diff; 1027 int len, s; 1028 1029 hash = eay_md5_one(rbuf); 1030 if (!hash) { 1031 plog(LLV_ERROR, LOCATION, NULL, 1032 "failed to allocate buffer.\n"); 1033 return -1; 1034 } 1035 1036 LIST_FOREACH(r, &rcptree, chain) { 1037 if (memcmp(hash->v, r->hash->v, r->hash->l) == 0) 1038 break; 1039 } 1040 vfree(hash); 1041 1042 /* this is the first time to receive the packet */ 1043 if (r == NULL) 1044 return 0; 1045 1046 /* 1047 * the packet was processed before, but the remote address mismatches. 1048 */ 1049 if (cmpsaddr(remote, r->remote) != CMPSADDR_MATCH) 1050 return 2; 1051 1052 /* 1053 * it should not check the local address because the packet 1054 * may arrive at other interface. 1055 */ 1056 1057 /* check the previous time to send */ 1058 sched_get_monotonic_time(&now); 1059 timersub(&now, &r->time_send, &diff); 1060 if (diff.tv_sec == 0) { 1061 plog(LLV_WARNING, LOCATION, NULL, 1062 "the packet retransmitted in a short time from %s\n", 1063 saddr2str(remote)); 1064 /*XXX should it be error ? */ 1065 } 1066 1067 /* select the socket to be sent */ 1068 s = myaddr_getfd(r->local); 1069 if (s == -1) 1070 return -1; 1071 1072 /* resend the packet if needed */ 1073 len = sendfromto(s, r->sendbuf->v, r->sendbuf->l, 1074 r->local, r->remote, lcconf->count_persend); 1075 if (len == -1) { 1076 plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n"); 1077 return -1; 1078 } 1079 1080 /* check the retry counter */ 1081 r->retry_counter--; 1082 if (r->retry_counter <= 0) { 1083 rem_recvdpkt(r); 1084 del_recvdpkt(r); 1085 plog(LLV_DEBUG, LOCATION, NULL, 1086 "deleted the retransmission packet to %s.\n", 1087 saddr2str(remote)); 1088 } else 1089 r->time_send = now; 1090 1091 return 1; 1092} 1093 1094/* 1095 * adding a hash of received packet into the received list. 1096 */ 1097int 1098add_recvdpkt(remote, local, sbuf, rbuf) 1099 struct sockaddr *remote, *local; 1100 vchar_t *sbuf, *rbuf; 1101{ 1102 struct recvdpkt *new = NULL; 1103 1104 if (lcconf->retry_counter == 0) { 1105 /* no need to add it */ 1106 return 0; 1107 } 1108 1109 new = racoon_calloc(1, sizeof(*new)); 1110 if (!new) { 1111 plog(LLV_ERROR, LOCATION, NULL, 1112 "failed to allocate buffer.\n"); 1113 return -1; 1114 } 1115 1116 new->hash = eay_md5_one(rbuf); 1117 if (!new->hash) { 1118 plog(LLV_ERROR, LOCATION, NULL, 1119 "failed to allocate buffer.\n"); 1120 del_recvdpkt(new); 1121 return -1; 1122 } 1123 new->remote = dupsaddr(remote); 1124 if (new->remote == NULL) { 1125 plog(LLV_ERROR, LOCATION, NULL, 1126 "failed to allocate buffer.\n"); 1127 del_recvdpkt(new); 1128 return -1; 1129 } 1130 new->local = dupsaddr(local); 1131 if (new->local == NULL) { 1132 plog(LLV_ERROR, LOCATION, NULL, 1133 "failed to allocate buffer.\n"); 1134 del_recvdpkt(new); 1135 return -1; 1136 } 1137 new->sendbuf = vdup(sbuf); 1138 if (new->sendbuf == NULL) { 1139 plog(LLV_ERROR, LOCATION, NULL, 1140 "failed to allocate buffer.\n"); 1141 del_recvdpkt(new); 1142 return -1; 1143 } 1144 1145 new->retry_counter = lcconf->retry_counter; 1146 sched_get_monotonic_time(&new->time_send); 1147 1148 LIST_INSERT_HEAD(&rcptree, new, chain); 1149 1150 return 0; 1151} 1152 1153void 1154del_recvdpkt(r) 1155 struct recvdpkt *r; 1156{ 1157 if (r->remote) 1158 racoon_free(r->remote); 1159 if (r->local) 1160 racoon_free(r->local); 1161 if (r->hash) 1162 vfree(r->hash); 1163 if (r->sendbuf) 1164 vfree(r->sendbuf); 1165 racoon_free(r); 1166} 1167 1168void 1169rem_recvdpkt(r) 1170 struct recvdpkt *r; 1171{ 1172 LIST_REMOVE(r, chain); 1173} 1174 1175static void 1176sweep_recvdpkt(struct sched *dummy) 1177{ 1178 struct recvdpkt *r, *next; 1179 struct timeval now, diff, sweep; 1180 1181 sched_get_monotonic_time(&now); 1182 1183 /* calculate sweep time; delete entries older than this */ 1184 diff.tv_sec = lcconf->retry_counter * lcconf->retry_interval; 1185 diff.tv_usec = 0; 1186 timersub(&now, &diff, &sweep); 1187 1188 for (r = LIST_FIRST(&rcptree); r; r = next) { 1189 next = LIST_NEXT(r, chain); 1190 1191 if (timercmp(&r->time_send, &sweep, <)) { 1192 rem_recvdpkt(r); 1193 del_recvdpkt(r); 1194 } 1195 } 1196 1197 sched_schedule(&sc_sweep, diff.tv_sec, sweep_recvdpkt); 1198} 1199 1200void 1201init_recvdpkt() 1202{ 1203 time_t lt = lcconf->retry_counter * lcconf->retry_interval; 1204 1205 LIST_INIT(&rcptree); 1206 1207 sched_schedule(&sc_sweep, lt, sweep_recvdpkt); 1208} 1209 1210#ifdef ENABLE_HYBRID 1211/* 1212 * Retruns 0 if the address was obtained by ISAKMP mode config, 1 otherwise 1213 * This should be in isakmp_cfg.c but ph1tree being private, it must be there 1214 */ 1215int 1216exclude_cfg_addr(addr) 1217 const struct sockaddr *addr; 1218{ 1219 struct ph1handle *p; 1220 struct sockaddr_in *sin; 1221 1222 LIST_FOREACH(p, &ph1tree, chain) { 1223 if ((p->mode_cfg != NULL) && 1224 (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) && 1225 (addr->sa_family == AF_INET)) { 1226 sin = (struct sockaddr_in *)addr; 1227 if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr) 1228 return 0; 1229 } 1230 } 1231 1232 return 1; 1233} 1234#endif 1235 1236 1237 1238/* 1239 * Reload conf code 1240 */ 1241static int revalidate_ph2(struct ph2handle *iph2){ 1242 struct sainfoalg *alg; 1243 int found, check_level; 1244 struct sainfo *sainfo; 1245 struct saprop *approval; 1246 struct ph1handle *iph1; 1247 1248 /* 1249 * Get the new sainfo using values of the old one 1250 */ 1251 if (iph2->sainfo != NULL) { 1252 iph2->sainfo = getsainfo(iph2->sainfo->idsrc, 1253 iph2->sainfo->iddst, iph2->sainfo->id_i, 1254 NULL, iph2->sainfo->remoteid); 1255 } 1256 approval = iph2->approval; 1257 sainfo = iph2->sainfo; 1258 1259 if (sainfo == NULL) { 1260 /* 1261 * Sainfo has been removed 1262 */ 1263 plog(LLV_DEBUG, LOCATION, NULL, 1264 "Reload: No sainfo for ph2\n"); 1265 return 0; 1266 } 1267 1268 if (approval == NULL) { 1269 /* 1270 * XXX why do we have a NULL approval sometimes ??? 1271 */ 1272 plog(LLV_DEBUG, LOCATION, NULL, 1273 "No approval found !\n"); 1274 return 0; 1275 } 1276 1277 /* 1278 * Don't care about proposals, should we do something ? 1279 * We have to keep iph2->proposal valid at least for initiator, 1280 * for pk_sendgetspi() 1281 */ 1282 1283 plog(LLV_DEBUG, LOCATION, NULL, "active single bundle:\n"); 1284 printsaprop0(LLV_DEBUG, approval); 1285 1286 /* 1287 * Validate approval against sainfo 1288 * Note: we must have an updated ph1->rmconf before doing that, 1289 * we'll set check_level to EXACT if we don't have a ph1 1290 * XXX try tu find the new remote section to get the new check level ? 1291 * XXX lifebyte 1292 */ 1293 if (iph2->ph1 != NULL) 1294 iph1=iph2->ph1; 1295 else 1296 iph1=getph1byaddr(iph2->src, iph2->dst, 0); 1297 1298 if(iph1 != NULL && iph1->rmconf != NULL) { 1299 check_level = iph1->rmconf->pcheck_level; 1300 } else { 1301 if(iph1 != NULL) 1302 plog(LLV_DEBUG, LOCATION, NULL, "No phase1 rmconf found !\n"); 1303 else 1304 plog(LLV_DEBUG, LOCATION, NULL, "No phase1 found !\n"); 1305 check_level = PROP_CHECK_EXACT; 1306 } 1307 1308 switch (check_level) { 1309 case PROP_CHECK_OBEY: 1310 plog(LLV_DEBUG, LOCATION, NULL, 1311 "Reload: OBEY for ph2, ok\n"); 1312 return 1; 1313 break; 1314 1315 case PROP_CHECK_STRICT: 1316 /* FALLTHROUGH */ 1317 case PROP_CHECK_CLAIM: 1318 if (sainfo->lifetime < approval->lifetime) { 1319 plog(LLV_DEBUG, LOCATION, NULL, 1320 "Reload: lifetime mismatch\n"); 1321 return 0; 1322 } 1323 1324#if 0 1325 /* Lifebyte is deprecated, just ignore it 1326 */ 1327 if (sainfo->lifebyte < approval->lifebyte) { 1328 plog(LLV_DEBUG, LOCATION, NULL, 1329 "Reload: lifebyte mismatch\n"); 1330 return 0; 1331 } 1332#endif 1333 1334 if (sainfo->pfs_group && 1335 sainfo->pfs_group != approval->pfs_group) { 1336 plog(LLV_DEBUG, LOCATION, NULL, 1337 "Reload: PFS group mismatch\n"); 1338 return 0; 1339 } 1340 break; 1341 1342 case PROP_CHECK_EXACT: 1343 if (sainfo->lifetime != approval->lifetime || 1344#if 0 1345 /* Lifebyte is deprecated, just ignore it 1346 */ 1347 sainfo->lifebyte != approval->lifebyte || 1348#endif 1349 sainfo->pfs_group != iph2->approval->pfs_group) { 1350 plog(LLV_DEBUG, LOCATION, NULL, 1351 "Reload: lifetime | pfs mismatch\n"); 1352 return 0; 1353 } 1354 break; 1355 1356 default: 1357 plog(LLV_DEBUG, LOCATION, NULL, 1358 "Reload: Shouldn't be here !\n"); 1359 return 0; 1360 break; 1361 } 1362 1363 for (alg = sainfo->algs[algclass_ipsec_auth]; alg; alg = alg->next) { 1364 if (alg->alg == approval->head->head->authtype) 1365 break; 1366 } 1367 if (alg == NULL) { 1368 plog(LLV_DEBUG, LOCATION, NULL, 1369 "Reload: alg == NULL (auth)\n"); 1370 return 0; 1371 } 1372 1373 found = 0; 1374 for (alg = sainfo->algs[algclass_ipsec_enc]; 1375 (found == 0 && alg != NULL); alg = alg->next) { 1376 plog(LLV_DEBUG, LOCATION, NULL, 1377 "Reload: next ph2 enc alg...\n"); 1378 1379 if (alg->alg != approval->head->head->trns_id){ 1380 plog(LLV_DEBUG, LOCATION, NULL, 1381 "Reload: encmode mismatch (%d / %d)\n", 1382 alg->alg, approval->head->head->trns_id); 1383 continue; 1384 } 1385 1386 switch (check_level){ 1387 /* PROP_CHECK_STRICT cannot happen here */ 1388 case PROP_CHECK_EXACT: 1389 if (alg->encklen != approval->head->head->encklen) { 1390 plog(LLV_DEBUG, LOCATION, NULL, 1391 "Reload: enclen mismatch\n"); 1392 continue; 1393 } 1394 break; 1395 1396 case PROP_CHECK_CLAIM: 1397 /* FALLTHROUGH */ 1398 case PROP_CHECK_STRICT: 1399 if (alg->encklen > approval->head->head->encklen) { 1400 plog(LLV_DEBUG, LOCATION, NULL, 1401 "Reload: enclen mismatch\n"); 1402 continue; 1403 } 1404 break; 1405 1406 default: 1407 plog(LLV_ERROR, LOCATION, NULL, 1408 "unexpected check_level\n"); 1409 continue; 1410 break; 1411 } 1412 found = 1; 1413 } 1414 1415 if (!found){ 1416 plog(LLV_DEBUG, LOCATION, NULL, 1417 "Reload: No valid enc\n"); 1418 return 0; 1419 } 1420 1421 /* 1422 * XXX comp 1423 */ 1424 plog(LLV_DEBUG, LOCATION, NULL, 1425 "Reload: ph2 check ok\n"); 1426 1427 return 1; 1428} 1429 1430 1431static void 1432remove_ph2(struct ph2handle *iph2) 1433{ 1434 u_int32_t spis[2]; 1435 1436 if(iph2 == NULL) 1437 return; 1438 1439 plog(LLV_DEBUG, LOCATION, NULL, 1440 "Deleting a Ph2...\n"); 1441 1442 if (iph2->status == PHASE2ST_ESTABLISHED) 1443 isakmp_info_send_d2(iph2); 1444 1445 if(iph2->approval != NULL && iph2->approval->head != NULL){ 1446 spis[0]=iph2->approval->head->spi; 1447 spis[1]=iph2->approval->head->spi_p; 1448 1449 /* purge_ipsec_spi() will do all the work: 1450 * - delete SPIs in kernel 1451 * - delete generated SPD 1452 * - unbind / rem / del ph2 1453 */ 1454 purge_ipsec_spi(iph2->dst, iph2->approval->head->proto_id, 1455 spis, 2); 1456 }else{ 1457 remph2(iph2); 1458 delph2(iph2); 1459 } 1460} 1461 1462static void remove_ph1(struct ph1handle *iph1){ 1463 struct ph2handle *iph2, *iph2_next; 1464 1465 if(iph1 == NULL) 1466 return; 1467 1468 plog(LLV_DEBUG, LOCATION, NULL, 1469 "Removing PH1...\n"); 1470 1471 if (iph1->status == PHASE1ST_ESTABLISHED || 1472 iph1->status == PHASE1ST_DYING) { 1473 for (iph2 = LIST_FIRST(&iph1->ph2tree); iph2; iph2 = iph2_next) { 1474 iph2_next = LIST_NEXT(iph2, ph1bind); 1475 remove_ph2(iph2); 1476 } 1477 isakmp_info_send_d1(iph1); 1478 } 1479 iph1->status = PHASE1ST_EXPIRED; 1480 /* directly call isakmp_ph1delete to avoid as possible a race 1481 * condition where we'll try to access iph1->rmconf after it has 1482 * freed 1483 */ 1484 isakmp_ph1delete(iph1); 1485} 1486 1487 1488static int revalidate_ph1tree_rmconf(void) 1489{ 1490 struct ph1handle *p, *next; 1491 struct remoteconf *rmconf; 1492 1493 for (p = LIST_FIRST(&ph1tree); p; p = next) { 1494 next = LIST_NEXT(p, chain); 1495 1496 if (p->status >= PHASE1ST_EXPIRED) 1497 continue; 1498 if (p->rmconf == NULL) 1499 continue; 1500 1501 rmconf = getrmconf_by_ph1(p); 1502 if (rmconf == NULL || rmconf == RMCONF_ERR_MULTIPLE) 1503 remove_ph1(p); 1504 else 1505 p->rmconf = rmconf; 1506 } 1507 1508 return 1; 1509} 1510 1511static int revalidate_ph2tree(void){ 1512 struct ph2handle *p, *next; 1513 1514 for (p = LIST_FIRST(&ph2tree); p; p = next) { 1515 next = LIST_NEXT(p, chain); 1516 1517 if (p->status == PHASE2ST_EXPIRED) 1518 continue; 1519 1520 if(!revalidate_ph2(p)){ 1521 plog(LLV_DEBUG, LOCATION, NULL, 1522 "PH2 not validated, removing it\n"); 1523 remove_ph2(p); 1524 } 1525 } 1526 1527 return 1; 1528} 1529 1530int 1531revalidate_ph12(void) 1532{ 1533 1534 revalidate_ph1tree_rmconf(); 1535 revalidate_ph2tree(); 1536 1537 return 1; 1538} 1539 1540#ifdef ENABLE_HYBRID 1541struct ph1handle * 1542getph1bylogin(login) 1543 char *login; 1544{ 1545 struct ph1handle *p; 1546 1547 LIST_FOREACH(p, &ph1tree, chain) { 1548 if (p->mode_cfg == NULL) 1549 continue; 1550 if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0) 1551 return p; 1552 } 1553 1554 return NULL; 1555} 1556 1557int 1558purgeph1bylogin(login) 1559 char *login; 1560{ 1561 struct ph1handle *p, *next; 1562 int found = 0; 1563 1564 for (p = LIST_FIRST(&ph1tree); p; p = next) { 1565 next = LIST_NEXT(p, chain); 1566 1567 if (p->mode_cfg == NULL) 1568 continue; 1569 if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0) { 1570 if (p->status >= PHASE1ST_EXPIRED) 1571 continue; 1572 1573 if (p->status >= PHASE1ST_ESTABLISHED) 1574 isakmp_info_send_d1(p); 1575 purge_remote(p); 1576 found++; 1577 } 1578 } 1579 1580 return found; 1581} 1582#endif 1583