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