1 /* $NetBSD: handler.c,v 1.1.1.2 2005/02/23 14:54:15 manu Exp $ */ 2 3 /* Id: handler.c,v 1.13 2004/11/21 19:36:26 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 #include "schedule.h" 54 #include "grabmyaddr.h" 55 #include "algorithm.h" 56 #include "crypto_openssl.h" 57 #include "policy.h" 58 #include "proposal.h" 59 #include "isakmp_var.h" 60 #include "evt.h" 61 #include "isakmp.h" 62 #ifdef ENABLE_HYBRID 63 #include "isakmp_xauth.h" 64 #include "isakmp_cfg.h" 65 #endif 66 #include "isakmp_inf.h" 67 #include "oakley.h" 68 #include "remoteconf.h" 69 #include "localconf.h" 70 #include "handler.h" 71 #include "gcmalloc.h" 72 #include "nattraversal.h" 73 74 #ifdef HAVE_GSSAPI 75 #include "gssapi.h" 76 #endif 77 78 static LIST_HEAD(_ph1tree_, ph1handle) ph1tree; 79 static LIST_HEAD(_ph2tree_, ph2handle) ph2tree; 80 static LIST_HEAD(_ctdtree_, contacted) ctdtree; 81 static LIST_HEAD(_rcptree_, recvdpkt) rcptree; 82 83 static void del_recvdpkt __P((struct recvdpkt *)); 84 static void rem_recvdpkt __P((struct recvdpkt *)); 85 static void sweep_recvdpkt __P((void *)); 86 87 /* 88 * functions about management of the isakmp status table 89 */ 90 /* %%% management phase 1 handler */ 91 /* 92 * search for isakmpsa handler with isakmp index. 93 */ 94 95 extern caddr_t val2str(const char *, size_t); 96 97 struct ph1handle * 98 getph1byindex(index) 99 isakmp_index *index; 100 { 101 struct ph1handle *p; 102 103 LIST_FOREACH(p, &ph1tree, chain) { 104 if (p->status == PHASE1ST_EXPIRED) 105 continue; 106 if (memcmp(&p->index, index, sizeof(*index)) == 0) 107 return p; 108 } 109 110 return NULL; 111 } 112 113 /* 114 * search for isakmp handler by i_ck in index. 115 */ 116 struct ph1handle * 117 getph1byindex0(index) 118 isakmp_index *index; 119 { 120 struct ph1handle *p; 121 122 LIST_FOREACH(p, &ph1tree, chain) { 123 if (p->status == PHASE1ST_EXPIRED) 124 continue; 125 if (memcmp(&p->index, index, sizeof(cookie_t)) == 0) 126 return p; 127 } 128 129 return NULL; 130 } 131 132 /* 133 * search for isakmpsa handler by source and remote address. 134 * don't use port number to search because this function search 135 * with phase 2's destinaion. 136 */ 137 struct ph1handle * 138 getph1byaddr(local, remote) 139 struct sockaddr *local, *remote; 140 { 141 struct ph1handle *p; 142 143 LIST_FOREACH(p, &ph1tree, chain) { 144 if (p->status == PHASE1ST_EXPIRED) 145 continue; 146 if (cmpsaddrwop(local, p->local) == 0 147 && cmpsaddrwop(remote, p->remote) == 0) 148 return p; 149 } 150 151 return NULL; 152 } 153 154 /* 155 * search for isakmpsa handler by remote address. 156 * don't use port number to search because this function search 157 * with phase 2's destinaion. 158 */ 159 struct ph1handle * 160 getph1bydstaddr(remote) 161 struct sockaddr *remote; 162 { 163 struct ph1handle *p; 164 165 LIST_FOREACH(p, &ph1tree, chain) { 166 if (p->status == PHASE1ST_EXPIRED) 167 continue; 168 if (cmpsaddrwop(remote, p->remote) == 0) 169 return p; 170 } 171 172 return NULL; 173 } 174 175 /* 176 * dump isakmp-sa 177 */ 178 vchar_t * 179 dumpph1() 180 { 181 struct ph1handle *iph1; 182 struct ph1dump *pd; 183 int cnt = 0; 184 vchar_t *buf; 185 186 /* get length of buffer */ 187 LIST_FOREACH(iph1, &ph1tree, chain) 188 cnt++; 189 190 buf = vmalloc(cnt * sizeof(struct ph1dump)); 191 if (buf == NULL) { 192 plog(LLV_ERROR, LOCATION, NULL, 193 "failed to get buffer\n"); 194 return NULL; 195 } 196 pd = (struct ph1dump *)buf->v; 197 198 LIST_FOREACH(iph1, &ph1tree, chain) { 199 memcpy(&pd->index, &iph1->index, sizeof(iph1->index)); 200 pd->status = iph1->status; 201 pd->side = iph1->side; 202 memcpy(&pd->remote, iph1->remote, sysdep_sa_len(iph1->remote)); 203 memcpy(&pd->local, iph1->local, sysdep_sa_len(iph1->local)); 204 pd->version = iph1->version; 205 pd->etype = iph1->etype; 206 pd->created = iph1->created; 207 pd->ph2cnt = iph1->ph2cnt; 208 pd++; 209 } 210 211 return buf; 212 } 213 214 /* 215 * create new isakmp Phase 1 status record to handle isakmp in Phase1 216 */ 217 struct ph1handle * 218 newph1() 219 { 220 struct ph1handle *iph1; 221 222 /* create new iph1 */ 223 iph1 = racoon_calloc(1, sizeof(*iph1)); 224 if (iph1 == NULL) 225 return NULL; 226 227 iph1->status = PHASE1ST_SPAWN; 228 229 #ifdef ENABLE_DPD 230 iph1->dpd_support = 0; 231 iph1->dpd_lastack = 0; 232 iph1->dpd_seq = 0; 233 iph1->dpd_fails = 0; 234 iph1->dpd_r_u = NULL; 235 #endif 236 237 return iph1; 238 } 239 240 /* 241 * delete new isakmp Phase 1 status record to handle isakmp in Phase1 242 */ 243 void 244 delph1(iph1) 245 struct ph1handle *iph1; 246 { 247 /* SA down shell script hook */ 248 if (iph1 != NULL) 249 script_hook(iph1, SCRIPT_PHASE1_DOWN); 250 251 EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL); 252 253 #ifdef ENABLE_NATT 254 if (iph1->natt_flags & NAT_KA_QUEUED) 255 natt_keepalive_remove (iph1->local, iph1->remote); 256 257 if (iph1->natt_options) { 258 racoon_free(iph1->natt_options); 259 iph1->natt_options = NULL; 260 } 261 #endif 262 263 if (iph1->remote) { 264 racoon_free(iph1->remote); 265 iph1->remote = NULL; 266 } 267 if (iph1->local) { 268 racoon_free(iph1->local); 269 iph1->local = NULL; 270 } 271 272 #ifdef ENABLE_HYBRID 273 if (iph1->mode_cfg) 274 isakmp_cfg_rmstate(iph1); 275 #endif 276 277 VPTRINIT(iph1->authstr); 278 279 sched_scrub_param(iph1); 280 iph1->sce = NULL; 281 iph1->scr = NULL; 282 283 VPTRINIT(iph1->sendbuf); 284 285 VPTRINIT(iph1->dhpriv); 286 VPTRINIT(iph1->dhpub); 287 VPTRINIT(iph1->dhpub_p); 288 VPTRINIT(iph1->dhgxy); 289 VPTRINIT(iph1->nonce); 290 VPTRINIT(iph1->nonce_p); 291 VPTRINIT(iph1->skeyid); 292 VPTRINIT(iph1->skeyid_d); 293 VPTRINIT(iph1->skeyid_a); 294 VPTRINIT(iph1->skeyid_e); 295 VPTRINIT(iph1->key); 296 VPTRINIT(iph1->hash); 297 VPTRINIT(iph1->sig); 298 VPTRINIT(iph1->sig_p); 299 oakley_delcert(iph1->cert); 300 iph1->cert = NULL; 301 oakley_delcert(iph1->cert_p); 302 iph1->cert_p = NULL; 303 oakley_delcert(iph1->crl_p); 304 iph1->crl_p = NULL; 305 oakley_delcert(iph1->cr_p); 306 iph1->cr_p = NULL; 307 VPTRINIT(iph1->id); 308 VPTRINIT(iph1->id_p); 309 310 if (iph1->ivm) { 311 oakley_delivm(iph1->ivm); 312 iph1->ivm = NULL; 313 } 314 315 VPTRINIT(iph1->sa); 316 VPTRINIT(iph1->sa_ret); 317 318 #ifdef HAVE_GSSAPI 319 VPTRINIT(iph1->gi_i); 320 VPTRINIT(iph1->gi_r); 321 322 gssapi_free_state(iph1); 323 #endif 324 325 racoon_free(iph1); 326 } 327 328 /* 329 * create new isakmp Phase 1 status record to handle isakmp in Phase1 330 */ 331 int 332 insph1(iph1) 333 struct ph1handle *iph1; 334 { 335 /* validity check */ 336 if (iph1->remote == NULL) { 337 plog(LLV_ERROR, LOCATION, NULL, 338 "invalid isakmp SA handler. no remote address.\n"); 339 return -1; 340 } 341 LIST_INSERT_HEAD(&ph1tree, iph1, chain); 342 343 return 0; 344 } 345 346 void 347 remph1(iph1) 348 struct ph1handle *iph1; 349 { 350 LIST_REMOVE(iph1, chain); 351 } 352 353 /* 354 * flush isakmp-sa 355 */ 356 void 357 flushph1() 358 { 359 struct ph1handle *p, *next; 360 361 for (p = LIST_FIRST(&ph1tree); p; p = next) { 362 next = LIST_NEXT(p, chain); 363 364 /* send delete information */ 365 if (p->status == PHASE1ST_ESTABLISHED) 366 isakmp_info_send_d1(p); 367 368 remph1(p); 369 delph1(p); 370 } 371 } 372 373 void 374 initph1tree() 375 { 376 LIST_INIT(&ph1tree); 377 } 378 379 /* %%% management phase 2 handler */ 380 /* 381 * search ph2handle with policy id. 382 */ 383 struct ph2handle * 384 getph2byspid(spid) 385 u_int32_t spid; 386 { 387 struct ph2handle *p; 388 389 LIST_FOREACH(p, &ph2tree, chain) { 390 /* 391 * there are ph2handle independent on policy 392 * such like informational exchange. 393 */ 394 if (p->spid == spid) 395 return p; 396 } 397 398 return NULL; 399 } 400 401 /* 402 * search ph2handle with sequence number. 403 */ 404 struct ph2handle * 405 getph2byseq(seq) 406 u_int32_t seq; 407 { 408 struct ph2handle *p; 409 410 LIST_FOREACH(p, &ph2tree, chain) { 411 if (p->seq == seq) 412 return p; 413 } 414 415 return NULL; 416 } 417 418 /* 419 * search ph2handle with message id. 420 */ 421 struct ph2handle * 422 getph2bymsgid(iph1, msgid) 423 struct ph1handle *iph1; 424 u_int32_t msgid; 425 { 426 struct ph2handle *p; 427 428 LIST_FOREACH(p, &ph2tree, chain) { 429 if (p->msgid == msgid) 430 return p; 431 } 432 433 return NULL; 434 } 435 436 /* 437 * call by pk_recvexpire(). 438 */ 439 struct ph2handle * 440 getph2bysaidx(src, dst, proto_id, spi) 441 struct sockaddr *src, *dst; 442 u_int proto_id; 443 u_int32_t spi; 444 { 445 struct ph2handle *iph2; 446 struct saproto *pr; 447 448 LIST_FOREACH(iph2, &ph2tree, chain) { 449 if (iph2->proposal == NULL && iph2->approval == NULL) 450 continue; 451 if (iph2->approval != NULL) { 452 for (pr = iph2->approval->head; pr != NULL; 453 pr = pr->next) { 454 if (proto_id != pr->proto_id) 455 break; 456 if (spi == pr->spi || spi == pr->spi_p) 457 return iph2; 458 } 459 } else if (iph2->proposal != NULL) { 460 for (pr = iph2->proposal->head; pr != NULL; 461 pr = pr->next) { 462 if (proto_id != pr->proto_id) 463 break; 464 if (spi == pr->spi) 465 return iph2; 466 } 467 } 468 } 469 470 return NULL; 471 } 472 473 /* 474 * create new isakmp Phase 2 status record to handle isakmp in Phase2 475 */ 476 struct ph2handle * 477 newph2() 478 { 479 struct ph2handle *iph2 = NULL; 480 481 /* create new iph2 */ 482 iph2 = racoon_calloc(1, sizeof(*iph2)); 483 if (iph2 == NULL) 484 return NULL; 485 486 iph2->status = PHASE1ST_SPAWN; 487 488 return iph2; 489 } 490 491 /* 492 * initialize ph2handle 493 * NOTE: don't initialize src/dst. 494 * SPI in the proposal is cleared. 495 */ 496 void 497 initph2(iph2) 498 struct ph2handle *iph2; 499 { 500 sched_scrub_param(iph2); 501 iph2->sce = NULL; 502 iph2->scr = NULL; 503 504 VPTRINIT(iph2->sendbuf); 505 VPTRINIT(iph2->msg1); 506 507 /* clear spi, keep variables in the proposal */ 508 if (iph2->proposal) { 509 struct saproto *pr; 510 for (pr = iph2->proposal->head; pr != NULL; pr = pr->next) 511 pr->spi = 0; 512 } 513 514 /* clear approval */ 515 if (iph2->approval) { 516 flushsaprop(iph2->approval); 517 iph2->approval = NULL; 518 } 519 520 /* clear the generated policy */ 521 if (iph2->spidx_gen) { 522 delsp_bothdir((struct policyindex *)iph2->spidx_gen); 523 racoon_free(iph2->spidx_gen); 524 iph2->spidx_gen = NULL; 525 } 526 527 if (iph2->pfsgrp) { 528 oakley_dhgrp_free(iph2->pfsgrp); 529 iph2->pfsgrp = NULL; 530 } 531 532 VPTRINIT(iph2->dhpriv); 533 VPTRINIT(iph2->dhpub); 534 VPTRINIT(iph2->dhpub_p); 535 VPTRINIT(iph2->dhgxy); 536 VPTRINIT(iph2->id); 537 VPTRINIT(iph2->id_p); 538 VPTRINIT(iph2->nonce); 539 VPTRINIT(iph2->nonce_p); 540 VPTRINIT(iph2->sa); 541 VPTRINIT(iph2->sa_ret); 542 543 if (iph2->ivm) { 544 oakley_delivm(iph2->ivm); 545 iph2->ivm = NULL; 546 } 547 } 548 549 /* 550 * delete new isakmp Phase 2 status record to handle isakmp in Phase2 551 */ 552 void 553 delph2(iph2) 554 struct ph2handle *iph2; 555 { 556 initph2(iph2); 557 558 if (iph2->src) { 559 racoon_free(iph2->src); 560 iph2->src = NULL; 561 } 562 if (iph2->dst) { 563 racoon_free(iph2->dst); 564 iph2->dst = NULL; 565 } 566 if (iph2->src_id) { 567 racoon_free(iph2->src_id); 568 iph2->src_id = NULL; 569 } 570 if (iph2->dst_id) { 571 racoon_free(iph2->dst_id); 572 iph2->dst_id = NULL; 573 } 574 575 if (iph2->proposal) { 576 flushsaprop(iph2->proposal); 577 iph2->proposal = NULL; 578 } 579 580 racoon_free(iph2); 581 } 582 583 /* 584 * create new isakmp Phase 2 status record to handle isakmp in Phase2 585 */ 586 int 587 insph2(iph2) 588 struct ph2handle *iph2; 589 { 590 LIST_INSERT_HEAD(&ph2tree, iph2, chain); 591 592 return 0; 593 } 594 595 void 596 remph2(iph2) 597 struct ph2handle *iph2; 598 { 599 LIST_REMOVE(iph2, chain); 600 } 601 602 void 603 initph2tree() 604 { 605 LIST_INIT(&ph2tree); 606 } 607 608 void 609 flushph2() 610 { 611 struct ph2handle *p, *next; 612 613 for (p = LIST_FIRST(&ph2tree); p; p = next) { 614 next = LIST_NEXT(p, chain); 615 616 /* send delete information */ 617 if (p->status == PHASE2ST_ESTABLISHED) 618 isakmp_info_send_d2(p); 619 620 unbindph12(p); 621 remph2(p); 622 delph2(p); 623 } 624 } 625 626 /* 627 * Delete all Phase 2 handlers for this src/dst/proto. This 628 * is used during INITIAL-CONTACT processing (so no need to 629 * send a message to the peer). 630 */ 631 void 632 deleteallph2(src, dst, proto_id) 633 struct sockaddr *src, *dst; 634 u_int proto_id; 635 { 636 struct ph2handle *iph2, *next; 637 struct saproto *pr; 638 639 for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) { 640 next = LIST_NEXT(iph2, chain); 641 if (iph2->proposal == NULL && iph2->approval == NULL) 642 continue; 643 if (iph2->approval != NULL) { 644 for (pr = iph2->approval->head; pr != NULL; 645 pr = pr->next) { 646 if (proto_id == pr->proto_id) 647 goto zap_it; 648 } 649 } else if (iph2->proposal != NULL) { 650 for (pr = iph2->proposal->head; pr != NULL; 651 pr = pr->next) { 652 if (proto_id == pr->proto_id) 653 goto zap_it; 654 } 655 } 656 continue; 657 zap_it: 658 unbindph12(iph2); 659 remph2(iph2); 660 delph2(iph2); 661 } 662 } 663 664 /* %%% */ 665 void 666 bindph12(iph1, iph2) 667 struct ph1handle *iph1; 668 struct ph2handle *iph2; 669 { 670 iph2->ph1 = iph1; 671 LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind); 672 } 673 674 void 675 unbindph12(iph2) 676 struct ph2handle *iph2; 677 { 678 if (iph2->ph1 != NULL) { 679 iph2->ph1 = NULL; 680 LIST_REMOVE(iph2, ph1bind); 681 } 682 } 683 684 /* %%% management contacted list */ 685 /* 686 * search contacted list. 687 */ 688 struct contacted * 689 getcontacted(remote) 690 struct sockaddr *remote; 691 { 692 struct contacted *p; 693 694 LIST_FOREACH(p, &ctdtree, chain) { 695 if (cmpsaddrstrict(remote, p->remote) == 0) 696 return p; 697 } 698 699 return NULL; 700 } 701 702 /* 703 * create new isakmp Phase 2 status record to handle isakmp in Phase2 704 */ 705 int 706 inscontacted(remote) 707 struct sockaddr *remote; 708 { 709 struct contacted *new; 710 711 /* create new iph2 */ 712 new = racoon_calloc(1, sizeof(*new)); 713 if (new == NULL) 714 return -1; 715 716 new->remote = dupsaddr(remote); 717 718 LIST_INSERT_HEAD(&ctdtree, new, chain); 719 720 return 0; 721 } 722 723 void 724 initctdtree() 725 { 726 LIST_INIT(&ctdtree); 727 } 728 729 /* 730 * check the response has been sent to the peer. when not, simply reply 731 * the buffered packet to the peer. 732 * OUT: 733 * 0: the packet is received at the first time. 734 * 1: the packet was processed before. 735 * 2: the packet was processed before, but the address mismatches. 736 * -1: error happened. 737 */ 738 int 739 check_recvdpkt(remote, local, rbuf) 740 struct sockaddr *remote, *local; 741 vchar_t *rbuf; 742 { 743 vchar_t *hash; 744 struct recvdpkt *r; 745 time_t t; 746 int len, s; 747 748 /* set current time */ 749 t = time(NULL); 750 751 hash = eay_md5_one(rbuf); 752 if (!hash) { 753 plog(LLV_ERROR, LOCATION, NULL, 754 "failed to allocate buffer.\n"); 755 return -1; 756 } 757 758 LIST_FOREACH(r, &rcptree, chain) { 759 if (memcmp(hash->v, r->hash->v, r->hash->l) == 0) 760 break; 761 } 762 vfree(hash); 763 764 /* this is the first time to receive the packet */ 765 if (r == NULL) 766 return 0; 767 768 /* 769 * the packet was processed before, but the remote address mismatches. 770 */ 771 if (cmpsaddrstrict(remote, r->remote) != 0) 772 return 2; 773 774 /* 775 * it should not check the local address because the packet 776 * may arrive at other interface. 777 */ 778 779 /* check the previous time to send */ 780 if (t - r->time_send < 1) { 781 plog(LLV_WARNING, LOCATION, NULL, 782 "the packet retransmitted in a short time from %s\n", 783 saddr2str(remote)); 784 /*XXX should it be error ? */ 785 } 786 787 /* select the socket to be sent */ 788 s = getsockmyaddr(r->local); 789 if (s == -1) 790 return -1; 791 792 /* resend the packet if needed */ 793 len = sendfromto(s, r->sendbuf->v, r->sendbuf->l, 794 r->local, r->remote, lcconf->count_persend); 795 if (len == -1) { 796 plog(LLV_ERROR, LOCATION, NULL, "sendfromto failed\n"); 797 return -1; 798 } 799 800 /* check the retry counter */ 801 r->retry_counter--; 802 if (r->retry_counter <= 0) { 803 rem_recvdpkt(r); 804 del_recvdpkt(r); 805 plog(LLV_DEBUG, LOCATION, NULL, 806 "deleted the retransmission packet to %s.\n", 807 saddr2str(remote)); 808 } else 809 r->time_send = t; 810 811 return 1; 812 } 813 814 /* 815 * adding a hash of received packet into the received list. 816 */ 817 int 818 add_recvdpkt(remote, local, sbuf, rbuf) 819 struct sockaddr *remote, *local; 820 vchar_t *sbuf, *rbuf; 821 { 822 struct recvdpkt *new = NULL; 823 824 if (lcconf->retry_counter == 0) { 825 /* no need to add it */ 826 return 0; 827 } 828 829 new = racoon_calloc(1, sizeof(*new)); 830 if (!new) { 831 plog(LLV_ERROR, LOCATION, NULL, 832 "failed to allocate buffer.\n"); 833 return -1; 834 } 835 836 new->hash = eay_md5_one(rbuf); 837 if (!new->hash) { 838 plog(LLV_ERROR, LOCATION, NULL, 839 "failed to allocate buffer.\n"); 840 del_recvdpkt(new); 841 return -1; 842 } 843 new->remote = dupsaddr(remote); 844 if (new->remote == NULL) { 845 plog(LLV_ERROR, LOCATION, NULL, 846 "failed to allocate buffer.\n"); 847 del_recvdpkt(new); 848 return -1; 849 } 850 new->local = dupsaddr(local); 851 if (new->local == NULL) { 852 plog(LLV_ERROR, LOCATION, NULL, 853 "failed to allocate buffer.\n"); 854 del_recvdpkt(new); 855 return -1; 856 } 857 new->sendbuf = vdup(sbuf); 858 if (new->sendbuf == NULL) { 859 plog(LLV_ERROR, LOCATION, NULL, 860 "failed to allocate buffer.\n"); 861 del_recvdpkt(new); 862 return -1; 863 } 864 865 new->retry_counter = lcconf->retry_counter; 866 new->time_send = 0; 867 new->created = time(NULL); 868 869 LIST_INSERT_HEAD(&rcptree, new, chain); 870 871 return 0; 872 } 873 874 void 875 del_recvdpkt(r) 876 struct recvdpkt *r; 877 { 878 if (r->remote) 879 racoon_free(r->remote); 880 if (r->local) 881 racoon_free(r->local); 882 if (r->hash) 883 vfree(r->hash); 884 if (r->sendbuf) 885 vfree(r->sendbuf); 886 racoon_free(r); 887 } 888 889 void 890 rem_recvdpkt(r) 891 struct recvdpkt *r; 892 { 893 LIST_REMOVE(r, chain); 894 } 895 896 void 897 sweep_recvdpkt(dummy) 898 void *dummy; 899 { 900 struct recvdpkt *r, *next; 901 time_t t, lt; 902 903 /* set current time */ 904 t = time(NULL); 905 906 /* set the lifetime of the retransmission */ 907 lt = lcconf->retry_counter * lcconf->retry_interval; 908 909 for (r = LIST_FIRST(&rcptree); r; r = next) { 910 next = LIST_NEXT(r, chain); 911 912 if (t - r->created > lt) { 913 rem_recvdpkt(r); 914 del_recvdpkt(r); 915 } 916 } 917 918 sched_new(lt, sweep_recvdpkt, NULL); 919 } 920 921 void 922 init_recvdpkt() 923 { 924 time_t lt = lcconf->retry_counter * lcconf->retry_interval; 925 926 LIST_INIT(&rcptree); 927 928 sched_new(lt, sweep_recvdpkt, NULL); 929 } 930 931 #ifdef ENABLE_HYBRID 932 /* 933 * Retruns 0 if the address was obtained by ISAKMP mode config, 1 otherwise 934 * This should be in isakmp_cfg.c but ph1tree being private, it must be there 935 */ 936 int 937 exclude_cfg_addr(addr) 938 const struct sockaddr *addr; 939 { 940 struct ph1handle *p; 941 struct sockaddr_in *sin; 942 943 LIST_FOREACH(p, &ph1tree, chain) { 944 if ((p->mode_cfg != NULL) && 945 (p->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) && 946 (addr->sa_family == AF_INET)) { 947 sin = (struct sockaddr_in *)addr; 948 if (sin->sin_addr.s_addr == p->mode_cfg->addr4.s_addr) 949 return 0; 950 } 951 } 952 953 return 1; 954 } 955 #endif 956