xref: /netbsd-src/crypto/dist/ipsec-tools/src/racoon/handler.c (revision aa73cae19608873cc4d1f712c4a0f8f8435f1ffa)
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