GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/iked/policy.c Lines: 0 280 0.0 %
Date: 2017-11-07 Branches: 0 1301 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: policy.c,v 1.46 2017/03/13 18:48:16 mikeb Exp $	*/
2
3
/*
4
 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
5
 * Copyright (c) 2001 Daniel Hartmeier
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/queue.h>
21
#include <sys/socket.h>
22
#include <sys/uio.h>
23
#include <sys/tree.h>
24
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <unistd.h>
28
#include <string.h>
29
#include <errno.h>
30
#include <fcntl.h>
31
#include <event.h>
32
33
#include "iked.h"
34
#include "ikev2.h"
35
36
static __inline int
37
	 sa_cmp(struct iked_sa *, struct iked_sa *);
38
static __inline int
39
	 user_cmp(struct iked_user *, struct iked_user *);
40
static __inline int
41
	 childsa_cmp(struct iked_childsa *, struct iked_childsa *);
42
static __inline int
43
	 flow_cmp(struct iked_flow *, struct iked_flow *);
44
45
46
void
47
policy_init(struct iked *env)
48
{
49
	TAILQ_INIT(&env->sc_policies);
50
	TAILQ_INIT(&env->sc_ocsp);
51
	RB_INIT(&env->sc_users);
52
	RB_INIT(&env->sc_sas);
53
	RB_INIT(&env->sc_activesas);
54
	RB_INIT(&env->sc_activeflows);
55
}
56
57
int
58
policy_lookup(struct iked *env, struct iked_message *msg)
59
{
60
	struct iked_policy	 pol;
61
	char			*s, idstr[IKED_ID_SIZE];
62
63
64
	if (msg->msg_sa != NULL && msg->msg_sa->sa_policy != NULL) {
65
		/* Existing SA with policy */
66
		msg->msg_policy = msg->msg_sa->sa_policy;
67
		goto found;
68
	}
69
70
	bzero(&pol, sizeof(pol));
71
	pol.pol_af = msg->msg_peer.ss_family;
72
	memcpy(&pol.pol_peer.addr, &msg->msg_peer, sizeof(msg->msg_peer));
73
	memcpy(&pol.pol_local.addr, &msg->msg_local, sizeof(msg->msg_local));
74
	if (msg->msg_id.id_type &&
75
	    ikev2_print_id(&msg->msg_id, idstr, IKED_ID_SIZE) == 0 &&
76
	    (s = strchr(idstr, '/')) != NULL) {
77
		pol.pol_peerid.id_type = msg->msg_id.id_type;
78
		pol.pol_peerid.id_length = strlen(s+1);
79
		strlcpy(pol.pol_peerid.id_data, s+1,
80
		    sizeof(pol.pol_peerid.id_data));
81
		log_debug("%s: peerid '%s'", __func__, s+1);
82
	}
83
84
	/* Try to find a matching policy for this message */
85
	if ((msg->msg_policy = policy_test(env, &pol)) != NULL)
86
		goto found;
87
88
	/* No matching policy found, try the default */
89
	if ((msg->msg_policy = env->sc_defaultcon) != NULL)
90
		goto found;
91
92
	/* No policy found */
93
	return (-1);
94
95
 found:
96
	return (0);
97
}
98
99
struct iked_policy *
100
policy_test(struct iked *env, struct iked_policy *key)
101
{
102
	struct iked_policy	*p = NULL, *pol = NULL;
103
	struct iked_flow	*flow = NULL, *flowkey;
104
	unsigned int		 cnt = 0;
105
106
	p = TAILQ_FIRST(&env->sc_policies);
107
	while (p != NULL) {
108
		cnt++;
109
		if (p->pol_flags & IKED_POLICY_SKIP)
110
			p = p->pol_skip[IKED_SKIP_FLAGS];
111
		else if (key->pol_af && p->pol_af &&
112
		    key->pol_af != p->pol_af)
113
			p = p->pol_skip[IKED_SKIP_AF];
114
		else if (key->pol_ipproto && p->pol_ipproto &&
115
		    key->pol_ipproto != p->pol_ipproto)
116
			p = p->pol_skip[IKED_SKIP_PROTO];
117
		else if (sockaddr_cmp((struct sockaddr *)&key->pol_peer.addr,
118
		    (struct sockaddr *)&p->pol_peer.addr,
119
		    p->pol_peer.addr_mask) != 0)
120
			p = p->pol_skip[IKED_SKIP_DST_ADDR];
121
		else if (sockaddr_cmp((struct sockaddr *)&key->pol_local.addr,
122
		    (struct sockaddr *)&p->pol_local.addr,
123
		    p->pol_local.addr_mask) != 0)
124
			p = p->pol_skip[IKED_SKIP_SRC_ADDR];
125
		else {
126
			/*
127
			 * Check if a specific flow is requested
128
			 * (eg. for acquire messages from the kernel)
129
			 * and find a matching flow.
130
			 */
131
			if (key->pol_nflows &&
132
			    (flowkey = RB_MIN(iked_flows,
133
			    &key->pol_flows)) != NULL &&
134
			    (flow = RB_FIND(iked_flows, &p->pol_flows,
135
			    flowkey)) == NULL) {
136
				p = TAILQ_NEXT(p, pol_entry);
137
				continue;
138
			}
139
			/* make sure the peer ID matches */
140
			if (key->pol_peerid.id_type &&
141
			    (key->pol_peerid.id_type != p->pol_peerid.id_type ||
142
			    memcmp(key->pol_peerid.id_data,
143
			    p->pol_peerid.id_data,
144
			    sizeof(key->pol_peerid.id_data)) != 0)) {
145
				p = TAILQ_NEXT(p, pol_entry);
146
				continue;
147
			}
148
149
			/* Policy matched */
150
			pol = p;
151
152
			if (pol->pol_flags & IKED_POLICY_QUICK)
153
				break;
154
155
			/* Continue to find last matching policy */
156
			p = TAILQ_NEXT(p, pol_entry);
157
		}
158
	}
159
160
	return (pol);
161
}
162
163
#define	IKED_SET_SKIP_STEPS(i)						\
164
	do {								\
165
		while (head[i] != cur) {				\
166
			head[i]->pol_skip[i] = cur;			\
167
			head[i] = TAILQ_NEXT(head[i], pol_entry);	\
168
		}							\
169
	} while (0)
170
171
/* This code is derived from pf_calc_skip_steps() from pf.c */
172
void
173
policy_calc_skip_steps(struct iked_policies *policies)
174
{
175
	struct iked_policy	*head[IKED_SKIP_COUNT], *cur, *prev;
176
	int			 i;
177
178
	cur = TAILQ_FIRST(policies);
179
	prev = cur;
180
	for (i = 0; i < IKED_SKIP_COUNT; ++i)
181
		head[i] = cur;
182
	while (cur != NULL) {
183
		if (cur->pol_flags & IKED_POLICY_SKIP)
184
			IKED_SET_SKIP_STEPS(IKED_SKIP_FLAGS);
185
		else if (cur->pol_af != AF_UNSPEC &&
186
		    prev->pol_af != AF_UNSPEC &&
187
		    cur->pol_af != prev->pol_af)
188
			IKED_SET_SKIP_STEPS(IKED_SKIP_AF);
189
		else if (cur->pol_ipproto && prev->pol_ipproto &&
190
		    cur->pol_ipproto != prev->pol_ipproto)
191
			IKED_SET_SKIP_STEPS(IKED_SKIP_PROTO);
192
		else if (IKED_ADDR_NEQ(&cur->pol_peer, &prev->pol_peer))
193
			IKED_SET_SKIP_STEPS(IKED_SKIP_DST_ADDR);
194
		else if (IKED_ADDR_NEQ(&cur->pol_local, &prev->pol_local))
195
			IKED_SET_SKIP_STEPS(IKED_SKIP_SRC_ADDR);
196
197
		prev = cur;
198
		cur = TAILQ_NEXT(cur, pol_entry);
199
	}
200
	for (i = 0; i < IKED_SKIP_COUNT; ++i)
201
		IKED_SET_SKIP_STEPS(i);
202
}
203
204
void
205
policy_ref(struct iked *env, struct iked_policy *pol)
206
{
207
	pol->pol_refcnt++;
208
	pol->pol_flags |= IKED_POLICY_REFCNT;
209
}
210
211
void
212
policy_unref(struct iked *env, struct iked_policy *pol)
213
{
214
	if (pol == NULL || (pol->pol_flags & IKED_POLICY_REFCNT) == 0)
215
		return;
216
	if (--(pol->pol_refcnt) <= 0)
217
		config_free_policy(env, pol);
218
	else {
219
		struct iked_sa		*tmp;
220
		int			 count = 0;
221
222
		TAILQ_FOREACH(tmp, &pol->pol_sapeers, sa_peer_entry)
223
			count++;
224
		if (count != pol->pol_refcnt)
225
			log_warnx("%s: ERROR pol %p pol_refcnt %d != count %d",
226
			    __func__, pol, pol->pol_refcnt, count);
227
	}
228
}
229
230
void
231
sa_state(struct iked *env, struct iked_sa *sa, int state)
232
{
233
	const char		*a;
234
	const char		*b;
235
	int			 ostate = sa->sa_state;
236
237
	a = print_map(ostate, ikev2_state_map);
238
	b = print_map(state, ikev2_state_map);
239
240
	sa->sa_state = state;
241
	if (ostate != IKEV2_STATE_INIT &&
242
	    !sa_stateok(sa, state)) {
243
		log_debug("%s: cannot switch: %s -> %s", __func__, a, b);
244
		sa->sa_state = ostate;
245
	} else if (ostate != sa->sa_state) {
246
		switch (state) {
247
		case IKEV2_STATE_ESTABLISHED:
248
		case IKEV2_STATE_CLOSED:
249
			log_info("%s: %s -> %s from %s to %s policy '%s'",
250
			    __func__, a, b,
251
			    print_host((struct sockaddr *)&sa->sa_peer.addr,
252
			    NULL, 0),
253
			    print_host((struct sockaddr *)&sa->sa_local.addr,
254
			    NULL, 0),
255
			    sa->sa_policy ? sa->sa_policy->pol_name :
256
			    "<unknown>");
257
			break;
258
		default:
259
			log_debug("%s: %s -> %s", __func__, a, b);
260
			break;
261
		}
262
	}
263
264
}
265
266
void
267
sa_stateflags(struct iked_sa *sa, unsigned int flags)
268
{
269
	unsigned int	require;
270
271
	if (sa->sa_state > IKEV2_STATE_SA_INIT)
272
		require = sa->sa_statevalid;
273
	else
274
		require = sa->sa_stateinit;
275
276
	log_debug("%s: 0x%04x -> 0x%04x %s (required 0x%04x %s)", __func__,
277
	    sa->sa_stateflags, sa->sa_stateflags | flags,
278
	    print_bits(sa->sa_stateflags | flags, IKED_REQ_BITS), require,
279
	    print_bits(require, IKED_REQ_BITS));
280
281
	sa->sa_stateflags |= flags;
282
}
283
284
int
285
sa_stateok(struct iked_sa *sa, int state)
286
{
287
	unsigned int	 require;
288
289
	if (sa->sa_state < state)
290
		return (0);
291
292
	if (state == IKEV2_STATE_SA_INIT)
293
		require = sa->sa_stateinit;
294
	else
295
		require = sa->sa_statevalid;
296
297
	if (state == IKEV2_STATE_SA_INIT ||
298
	    state == IKEV2_STATE_VALID ||
299
	    state == IKEV2_STATE_EAP_VALID) {
300
		log_debug("%s: %s flags 0x%04x, require 0x%04x %s", __func__,
301
		    print_map(state, ikev2_state_map),
302
		    (sa->sa_stateflags & require), require,
303
		    print_bits(require, IKED_REQ_BITS));
304
305
		if ((sa->sa_stateflags & require) != require)
306
			return (0);	/* not ready, ignore */
307
	}
308
	return (1);
309
}
310
311
struct iked_sa *
312
sa_new(struct iked *env, uint64_t ispi, uint64_t rspi,
313
    unsigned int initiator, struct iked_policy *pol)
314
{
315
	struct iked_sa	*sa;
316
	struct iked_sa	*old;
317
	struct iked_id	*localid;
318
	unsigned int	 diff;
319
320
	if ((ispi == 0 && rspi == 0) ||
321
	    (sa = sa_lookup(env, ispi, rspi, initiator)) == NULL) {
322
		/* Create new SA */
323
		if (!initiator && ispi == 0) {
324
			log_debug("%s: cannot create responder IKE SA w/o ispi",
325
			    __func__);
326
			return (NULL);
327
		}
328
		sa = config_new_sa(env, initiator);
329
		if (sa == NULL) {
330
			log_debug("%s: failed to allocate IKE SA", __func__);
331
			return (NULL);
332
		}
333
		if (!initiator)
334
			sa->sa_hdr.sh_ispi = ispi;
335
		old = RB_INSERT(iked_sas, &env->sc_sas, sa);
336
		if (old && old != sa) {
337
			log_warnx("%s: duplicate IKE SA", __func__);
338
			config_free_sa(env, sa);
339
			return (NULL);
340
		}
341
	}
342
	/* Update rspi in the initator case */
343
	if (initiator && sa->sa_hdr.sh_rspi == 0 && rspi)
344
		sa->sa_hdr.sh_rspi = rspi;
345
346
	if (pol == NULL && sa->sa_policy == NULL)
347
		fatalx("%s: sa %p no policy", __func__, sa);
348
	else if (sa->sa_policy == NULL) {
349
		/* Increment refcount if the policy has refcounting enabled. */
350
		if (pol->pol_flags & IKED_POLICY_REFCNT) {
351
			log_info("%s: sa %p old pol %p pol_refcnt %d",
352
			    __func__, sa, pol, pol->pol_refcnt);
353
			policy_ref(env, pol);
354
		}
355
		sa->sa_policy = pol;
356
		TAILQ_INSERT_TAIL(&pol->pol_sapeers, sa, sa_peer_entry);
357
	} else
358
		pol = sa->sa_policy;
359
360
	sa->sa_statevalid = IKED_REQ_AUTH|IKED_REQ_AUTHVALID|IKED_REQ_SA;
361
	if (pol != NULL && pol->pol_auth.auth_eap) {
362
		sa->sa_statevalid |= IKED_REQ_CERT|IKED_REQ_EAPVALID;
363
	} else if (pol != NULL && pol->pol_auth.auth_method !=
364
	    IKEV2_AUTH_SHARED_KEY_MIC) {
365
		sa->sa_statevalid |= IKED_REQ_CERTVALID|IKED_REQ_CERT;
366
	}
367
368
	if (initiator) {
369
		localid = &sa->sa_iid;
370
		diff = IKED_REQ_CERTVALID|IKED_REQ_AUTHVALID|IKED_REQ_SA|
371
		    IKED_REQ_EAPVALID;
372
		sa->sa_stateinit = sa->sa_statevalid & ~diff;
373
		sa->sa_statevalid = sa->sa_statevalid & diff;
374
	} else
375
		localid = &sa->sa_rid;
376
377
	if (!ibuf_length(localid->id_buf) && pol != NULL &&
378
	    ikev2_policy2id(&pol->pol_localid, localid, 1) != 0) {
379
		log_debug("%s: failed to get local id", __func__);
380
		sa_free(env, sa);
381
		return (NULL);
382
	}
383
384
	return (sa);
385
}
386
387
void
388
sa_free(struct iked *env, struct iked_sa *sa)
389
{
390
	log_debug("%s: ispi %s rspi %s", __func__,
391
	    print_spi(sa->sa_hdr.sh_ispi, 8),
392
	    print_spi(sa->sa_hdr.sh_rspi, 8));
393
394
	/* IKE rekeying running? */
395
	if (sa->sa_nexti) {
396
		RB_REMOVE(iked_sas, &env->sc_sas, sa->sa_nexti);
397
		config_free_sa(env, sa->sa_nexti);
398
	}
399
	if (sa->sa_nextr) {
400
		RB_REMOVE(iked_sas, &env->sc_sas, sa->sa_nextr);
401
		config_free_sa(env, sa->sa_nextr);
402
	}
403
	RB_REMOVE(iked_sas, &env->sc_sas, sa);
404
	config_free_sa(env, sa);
405
}
406
407
void
408
sa_free_flows(struct iked *env, struct iked_saflows *head)
409
{
410
	struct iked_flow	*flow, *next;
411
412
	for (flow = TAILQ_FIRST(head); flow != NULL; flow = next) {
413
		next = TAILQ_NEXT(flow, flow_entry);
414
415
		log_debug("%s: free %p", __func__, flow);
416
417
		if (flow->flow_loaded)
418
			RB_REMOVE(iked_flows, &env->sc_activeflows, flow);
419
		TAILQ_REMOVE(head, flow, flow_entry);
420
		(void)pfkey_flow_delete(env->sc_pfkey, flow);
421
		flow_free(flow);
422
	}
423
}
424
425
426
int
427
sa_address(struct iked_sa *sa, struct iked_addr *addr,
428
    struct sockaddr_storage *peer)
429
{
430
	bzero(addr, sizeof(*addr));
431
	addr->addr_af = peer->ss_family;
432
	addr->addr_port = htons(socket_getport((struct sockaddr *)peer));
433
	memcpy(&addr->addr, peer, sizeof(*peer));
434
	if (socket_af((struct sockaddr *)&addr->addr, addr->addr_port) == -1) {
435
		log_debug("%s: invalid address", __func__);
436
		return (-1);
437
	}
438
	return (0);
439
}
440
441
void
442
childsa_free(struct iked_childsa *csa)
443
{
444
	struct iked_childsa *csb;
445
446
	if (csa->csa_children) {
447
		/* XXX should not happen */
448
		log_warnx("%s: trying to remove CSA %p children %u",
449
		    __func__, csa, csa->csa_children);
450
		return;
451
	}
452
	if (csa->csa_parent)
453
		csa->csa_parent->csa_children--;
454
	if ((csb = csa->csa_peersa) != NULL)
455
		csb->csa_peersa = NULL;
456
	ibuf_release(csa->csa_encrkey);
457
	ibuf_release(csa->csa_integrkey);
458
	free(csa);
459
}
460
461
struct iked_childsa *
462
childsa_lookup(struct iked_sa *sa, uint64_t spi, uint8_t protoid)
463
{
464
	struct iked_childsa	*csa;
465
466
	if (sa == NULL || spi == 0 || protoid == 0)
467
		return (NULL);
468
469
	TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry) {
470
		if (csa->csa_spi.spi_protoid == protoid &&
471
		    (csa->csa_spi.spi == spi))
472
			break;
473
	}
474
	return (csa);
475
}
476
477
void
478
flow_free(struct iked_flow *flow)
479
{
480
	free(flow);
481
}
482
483
struct iked_sa *
484
sa_lookup(struct iked *env, uint64_t ispi, uint64_t rspi,
485
    unsigned int initiator)
486
{
487
	struct iked_sa	*sa, key;
488
489
	key.sa_hdr.sh_ispi = ispi;
490
	/* key.sa_hdr.sh_rspi = rspi; */
491
	key.sa_hdr.sh_initiator = initiator;
492
493
	if ((sa = RB_FIND(iked_sas, &env->sc_sas, &key)) != NULL) {
494
		gettimeofday(&sa->sa_timeused, NULL);
495
496
		/* Validate if SPIr matches */
497
		if ((sa->sa_hdr.sh_rspi != 0) &&
498
		    (rspi != 0) &&
499
		    (sa->sa_hdr.sh_rspi != rspi))
500
			return (NULL);
501
	}
502
503
	return (sa);
504
}
505
506
static __inline int
507
sa_cmp(struct iked_sa *a, struct iked_sa *b)
508
{
509
	if (a->sa_hdr.sh_initiator > b->sa_hdr.sh_initiator)
510
		return (-1);
511
	if (a->sa_hdr.sh_initiator < b->sa_hdr.sh_initiator)
512
		return (1);
513
514
	if (a->sa_hdr.sh_ispi > b->sa_hdr.sh_ispi)
515
		return (-1);
516
	if (a->sa_hdr.sh_ispi < b->sa_hdr.sh_ispi)
517
		return (1);
518
519
#if 0
520
	/* Responder SPI is not yet set in the local IKE SADB */
521
	if ((b->sa_type == IKED_SATYPE_LOCAL && b->sa_hdr.sh_rspi == 0) ||
522
	    (a->sa_type == IKED_SATYPE_LOCAL && a->sa_hdr.sh_rspi == 0))
523
		return (0);
524
525
	if (a->sa_hdr.sh_rspi > b->sa_hdr.sh_rspi)
526
		return (-1);
527
	if (a->sa_hdr.sh_rspi < b->sa_hdr.sh_rspi)
528
		return (1);
529
#endif
530
531
	return (0);
532
}
533
534
static __inline int
535
sa_addrpool_cmp(struct iked_sa *a, struct iked_sa *b)
536
{
537
	return (sockaddr_cmp((struct sockaddr *)&a->sa_addrpool->addr,
538
	    (struct sockaddr *)&b->sa_addrpool->addr, -1));
539
}
540
541
static __inline int
542
sa_addrpool6_cmp(struct iked_sa *a, struct iked_sa *b)
543
{
544
	return (sockaddr_cmp((struct sockaddr *)&a->sa_addrpool6->addr,
545
	    (struct sockaddr *)&b->sa_addrpool6->addr, -1));
546
}
547
548
struct iked_user *
549
user_lookup(struct iked *env, const char *user)
550
{
551
	struct iked_user	 key;
552
553
	if (strlcpy(key.usr_name, user,
554
	    sizeof(key.usr_name)) >= sizeof(key.usr_name))
555
		return (NULL);
556
557
	return (RB_FIND(iked_users, &env->sc_users, &key));
558
}
559
560
static __inline int
561
user_cmp(struct iked_user *a, struct iked_user *b)
562
{
563
	return (strcmp(a->usr_name, b->usr_name));
564
}
565
566
static __inline int
567
childsa_cmp(struct iked_childsa *a, struct iked_childsa *b)
568
{
569
	if (a->csa_spi.spi > b->csa_spi.spi)
570
		return (1);
571
	if (a->csa_spi.spi < b->csa_spi.spi)
572
		return (-1);
573
	return (0);
574
}
575
576
static __inline int
577
addr_cmp(struct iked_addr *a, struct iked_addr *b, int useports)
578
{
579
	int		diff = 0;
580
581
	diff = sockaddr_cmp((struct sockaddr *)&a->addr,
582
	    (struct sockaddr *)&b->addr, 128);
583
	if (!diff)
584
		diff = (int)a->addr_mask - (int)b->addr_mask;
585
	if (!diff && useports)
586
		diff = a->addr_port - b->addr_port;
587
588
	return (diff);
589
}
590
591
static __inline int
592
flow_cmp(struct iked_flow *a, struct iked_flow *b)
593
{
594
	int		diff = 0;
595
596
	if (!diff)
597
		diff = (int)a->flow_ipproto - (int)b->flow_ipproto;
598
	if (!diff)
599
		diff = (int)a->flow_saproto - (int)b->flow_saproto;
600
	if (!diff)
601
		diff = (int)a->flow_dir - (int)b->flow_dir;
602
	if (!diff)
603
		diff = addr_cmp(&a->flow_dst, &b->flow_dst, 1);
604
	if (!diff)
605
		diff = addr_cmp(&a->flow_src, &b->flow_src, 1);
606
607
	return (diff);
608
}
609
610
int
611
flow_equal(struct iked_flow *a, struct iked_flow *b)
612
{
613
	return (flow_cmp(a, b) == 0);
614
}
615
616
RB_GENERATE(iked_sas, iked_sa, sa_entry, sa_cmp);
617
RB_GENERATE(iked_addrpool, iked_sa, sa_addrpool_entry, sa_addrpool_cmp);
618
RB_GENERATE(iked_addrpool6, iked_sa, sa_addrpool6_entry, sa_addrpool6_cmp);
619
RB_GENERATE(iked_users, iked_user, usr_entry, user_cmp);
620
RB_GENERATE(iked_activesas, iked_childsa, csa_node, childsa_cmp);
621
RB_GENERATE(iked_flows, iked_flow, flow_node, flow_cmp);