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