xref: /openbsd/sbin/iked/policy.c (revision 03f38e3c)
1 /*	$OpenBSD: policy.c,v 1.50 2019/11/30 15:44:07 tobhe 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",
244 		    SPI_SA(sa, __func__), a, b);
245 		sa->sa_state = ostate;
246 	} else if (ostate != sa->sa_state) {
247 		switch (state) {
248 		case IKEV2_STATE_ESTABLISHED:
249 		case IKEV2_STATE_CLOSED:
250 			log_debug("%s: %s -> %s from %s to %s policy '%s'",
251 			    SPI_SA(sa, __func__), a, b,
252 			    print_host((struct sockaddr *)&sa->sa_peer.addr,
253 			    NULL, 0),
254 			    print_host((struct sockaddr *)&sa->sa_local.addr,
255 			    NULL, 0),
256 			    sa->sa_policy ? sa->sa_policy->pol_name :
257 			    "<unknown>");
258 			break;
259 		default:
260 			log_debug("%s: %s -> %s",
261 			    SPI_SA(sa, __func__), a, b);
262 			break;
263 		}
264 	}
265 
266 }
267 
268 void
269 sa_stateflags(struct iked_sa *sa, unsigned int flags)
270 {
271 	unsigned int	require;
272 
273 	if (sa->sa_state > IKEV2_STATE_SA_INIT)
274 		require = sa->sa_statevalid;
275 	else
276 		require = sa->sa_stateinit;
277 
278 	log_debug("%s: 0x%04x -> 0x%04x %s (required 0x%04x %s)", __func__,
279 	    sa->sa_stateflags, sa->sa_stateflags | flags,
280 	    print_bits(sa->sa_stateflags | flags, IKED_REQ_BITS), require,
281 	    print_bits(require, IKED_REQ_BITS));
282 
283 	sa->sa_stateflags |= flags;
284 }
285 
286 int
287 sa_stateok(struct iked_sa *sa, int state)
288 {
289 	unsigned int	 require;
290 
291 	if (sa->sa_state < state)
292 		return (0);
293 
294 	if (state == IKEV2_STATE_SA_INIT)
295 		require = sa->sa_stateinit;
296 	else
297 		require = sa->sa_statevalid;
298 
299 	if (state == IKEV2_STATE_SA_INIT ||
300 	    state == IKEV2_STATE_VALID ||
301 	    state == IKEV2_STATE_EAP_VALID) {
302 		log_debug("%s: %s flags 0x%04x, require 0x%04x %s", __func__,
303 		    print_map(state, ikev2_state_map),
304 		    (sa->sa_stateflags & require), require,
305 		    print_bits(require, IKED_REQ_BITS));
306 
307 		if ((sa->sa_stateflags & require) != require)
308 			return (0);	/* not ready, ignore */
309 	}
310 	return (1);
311 }
312 
313 struct iked_sa *
314 sa_new(struct iked *env, uint64_t ispi, uint64_t rspi,
315     unsigned int initiator, struct iked_policy *pol)
316 {
317 	struct iked_sa	*sa;
318 	struct iked_sa	*old;
319 	struct iked_id	*localid;
320 	unsigned int	 diff;
321 
322 	if ((ispi == 0 && rspi == 0) ||
323 	    (sa = sa_lookup(env, ispi, rspi, initiator)) == NULL) {
324 		/* Create new SA */
325 		if (!initiator && ispi == 0) {
326 			log_debug("%s: cannot create responder IKE SA w/o ispi",
327 			    __func__);
328 			return (NULL);
329 		}
330 		sa = config_new_sa(env, initiator);
331 		if (sa == NULL) {
332 			log_debug("%s: failed to allocate IKE SA", __func__);
333 			return (NULL);
334 		}
335 		if (!initiator)
336 			sa->sa_hdr.sh_ispi = ispi;
337 		old = RB_INSERT(iked_sas, &env->sc_sas, sa);
338 		if (old && old != sa) {
339 			log_warnx("%s: duplicate IKE SA", __func__);
340 			config_free_sa(env, sa);
341 			return (NULL);
342 		}
343 	}
344 	/* Update rspi in the initator case */
345 	if (initiator && sa->sa_hdr.sh_rspi == 0 && rspi)
346 		sa->sa_hdr.sh_rspi = rspi;
347 
348 	if (pol == NULL && sa->sa_policy == NULL)
349 		fatalx("%s: sa %p no policy", __func__, sa);
350 	else if (sa->sa_policy == NULL) {
351 		/* Increment refcount if the policy has refcounting enabled. */
352 		if (pol->pol_flags & IKED_POLICY_REFCNT) {
353 			log_info("%s: sa %p old pol %p pol_refcnt %d",
354 			    __func__, sa, pol, pol->pol_refcnt);
355 			policy_ref(env, pol);
356 		}
357 		sa->sa_policy = pol;
358 		TAILQ_INSERT_TAIL(&pol->pol_sapeers, sa, sa_peer_entry);
359 	} else
360 		pol = sa->sa_policy;
361 
362 	sa->sa_statevalid = IKED_REQ_AUTH|IKED_REQ_AUTHVALID|IKED_REQ_SA;
363 	if (pol != NULL && pol->pol_auth.auth_eap) {
364 		sa->sa_statevalid |= IKED_REQ_CERT|IKED_REQ_EAPVALID;
365 	} else if (pol != NULL && pol->pol_auth.auth_method !=
366 	    IKEV2_AUTH_SHARED_KEY_MIC) {
367 		sa->sa_statevalid |= IKED_REQ_CERTVALID|IKED_REQ_CERT;
368 	}
369 
370 	if (initiator) {
371 		localid = &sa->sa_iid;
372 		diff = IKED_REQ_CERTVALID|IKED_REQ_AUTHVALID|IKED_REQ_SA|
373 		    IKED_REQ_EAPVALID;
374 		sa->sa_stateinit = sa->sa_statevalid & ~diff;
375 		sa->sa_statevalid = sa->sa_statevalid & diff;
376 	} else
377 		localid = &sa->sa_rid;
378 
379 	if (!ibuf_length(localid->id_buf) && pol != NULL &&
380 	    ikev2_policy2id(&pol->pol_localid, localid, 1) != 0) {
381 		log_debug("%s: failed to get local id", __func__);
382 		ikev2_ike_sa_setreason(sa, "failed to get local id");
383 		sa_free(env, sa);
384 		return (NULL);
385 	}
386 
387 	return (sa);
388 }
389 
390 void
391 sa_free(struct iked *env, struct iked_sa *sa)
392 {
393 	if (sa->sa_reason)
394 		log_info("%s: %s", SPI_SA(sa, __func__), sa->sa_reason);
395 	else
396 		log_debug("%s: ispi %s rspi %s", SPI_SA(sa, __func__),
397 		    print_spi(sa->sa_hdr.sh_ispi, 8),
398 		    print_spi(sa->sa_hdr.sh_rspi, 8));
399 
400 	/* IKE rekeying running? */
401 	if (sa->sa_nexti) {
402 		RB_REMOVE(iked_sas, &env->sc_sas, sa->sa_nexti);
403 		config_free_sa(env, sa->sa_nexti);
404 	}
405 	if (sa->sa_nextr) {
406 		RB_REMOVE(iked_sas, &env->sc_sas, sa->sa_nextr);
407 		config_free_sa(env, sa->sa_nextr);
408 	}
409 	RB_REMOVE(iked_sas, &env->sc_sas, sa);
410 	config_free_sa(env, sa);
411 }
412 
413 /* oflow did replace active flow, so we need to re-activate a matching flow */
414 int
415 flow_replace(struct iked *env, struct iked_flow *oflow)
416 {
417 	struct iked_sa		*sa;
418 	struct iked_flow	*flow, *other;
419 
420 	if (!oflow->flow_loaded)
421 		return (-1);
422 	RB_FOREACH(sa, iked_sas, &env->sc_sas) {
423 		if (oflow->flow_ikesa == sa ||
424 		    sa->sa_state != IKEV2_STATE_ESTABLISHED)
425 			continue;
426 		TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry) {
427 			if (flow == oflow ||
428 			    flow->flow_loaded || !flow_equal(flow, oflow))
429 				continue;
430 			if ((other = RB_FIND(iked_flows, &env->sc_activeflows,
431 			    flow)) != NULL) {
432 				/* XXX should not happen */
433 				log_debug("%s: found flow %p for %p/%p",
434 				    __func__, other, flow, other);
435 				return (-1);
436 			}
437 			if (pfkey_flow_add(env->sc_pfkey, flow) != 0) {
438 				log_debug("%s: failed to load flow", __func__);
439 				return (-1);
440 			}
441 			RB_INSERT(iked_flows, &env->sc_activeflows, flow);
442 			log_debug("%s: loaded flow %p replaces %p", __func__,
443 			    flow, oflow);
444 			/* check for matching flow if we get deleted, too */
445 			flow->flow_replacing = 1;
446 			return (0);
447 		}
448 	}
449 	return (-1);
450 }
451 
452 void
453 sa_free_flows(struct iked *env, struct iked_saflows *head)
454 {
455 	struct iked_flow	*flow, *next;
456 
457 	for (flow = TAILQ_FIRST(head); flow != NULL; flow = next) {
458 		next = TAILQ_NEXT(flow, flow_entry);
459 
460 		log_debug("%s: free %p", __func__, flow);
461 
462 		if (flow->flow_loaded)
463 			RB_REMOVE(iked_flows, &env->sc_activeflows, flow);
464 		TAILQ_REMOVE(head, flow, flow_entry);
465 		if (!flow->flow_replacing ||
466 		    flow_replace(env, flow) != 0)
467 			(void)pfkey_flow_delete(env->sc_pfkey, flow);
468 		flow_free(flow);
469 	}
470 }
471 
472 
473 int
474 sa_address(struct iked_sa *sa, struct iked_addr *addr,
475     struct sockaddr_storage *peer)
476 {
477 	bzero(addr, sizeof(*addr));
478 	addr->addr_af = peer->ss_family;
479 	addr->addr_port = htons(socket_getport((struct sockaddr *)peer));
480 	memcpy(&addr->addr, peer, sizeof(*peer));
481 	if (socket_af((struct sockaddr *)&addr->addr, addr->addr_port) == -1) {
482 		log_debug("%s: invalid address", __func__);
483 		return (-1);
484 	}
485 	return (0);
486 }
487 
488 void
489 childsa_free(struct iked_childsa *csa)
490 {
491 	struct iked_childsa *csb;
492 
493 	if (csa->csa_children) {
494 		/* XXX should not happen */
495 		log_warnx("%s: trying to remove CSA %p children %u",
496 		    __func__, csa, csa->csa_children);
497 		return;
498 	}
499 	if (csa->csa_parent)
500 		csa->csa_parent->csa_children--;
501 	if ((csb = csa->csa_peersa) != NULL)
502 		csb->csa_peersa = NULL;
503 	ibuf_release(csa->csa_encrkey);
504 	ibuf_release(csa->csa_integrkey);
505 	free(csa);
506 }
507 
508 struct iked_childsa *
509 childsa_lookup(struct iked_sa *sa, uint64_t spi, uint8_t protoid)
510 {
511 	struct iked_childsa	*csa;
512 
513 	if (sa == NULL || spi == 0 || protoid == 0)
514 		return (NULL);
515 
516 	TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry) {
517 		if (csa->csa_spi.spi_protoid == protoid &&
518 		    (csa->csa_spi.spi == spi))
519 			break;
520 	}
521 	return (csa);
522 }
523 
524 void
525 flow_free(struct iked_flow *flow)
526 {
527 	free(flow);
528 }
529 
530 struct iked_sa *
531 sa_lookup(struct iked *env, uint64_t ispi, uint64_t rspi,
532     unsigned int initiator)
533 {
534 	struct iked_sa	*sa, key;
535 
536 	key.sa_hdr.sh_ispi = ispi;
537 	/* key.sa_hdr.sh_rspi = rspi; */
538 	key.sa_hdr.sh_initiator = initiator;
539 
540 	if ((sa = RB_FIND(iked_sas, &env->sc_sas, &key)) != NULL) {
541 		gettimeofday(&sa->sa_timeused, NULL);
542 
543 		/* Validate if SPIr matches */
544 		if ((sa->sa_hdr.sh_rspi != 0) &&
545 		    (rspi != 0) &&
546 		    (sa->sa_hdr.sh_rspi != rspi))
547 			return (NULL);
548 	}
549 
550 	return (sa);
551 }
552 
553 static __inline int
554 sa_cmp(struct iked_sa *a, struct iked_sa *b)
555 {
556 	if (a->sa_hdr.sh_initiator > b->sa_hdr.sh_initiator)
557 		return (-1);
558 	if (a->sa_hdr.sh_initiator < b->sa_hdr.sh_initiator)
559 		return (1);
560 
561 	if (a->sa_hdr.sh_ispi > b->sa_hdr.sh_ispi)
562 		return (-1);
563 	if (a->sa_hdr.sh_ispi < b->sa_hdr.sh_ispi)
564 		return (1);
565 
566 #if 0
567 	/* Responder SPI is not yet set in the local IKE SADB */
568 	if ((b->sa_type == IKED_SATYPE_LOCAL && b->sa_hdr.sh_rspi == 0) ||
569 	    (a->sa_type == IKED_SATYPE_LOCAL && a->sa_hdr.sh_rspi == 0))
570 		return (0);
571 
572 	if (a->sa_hdr.sh_rspi > b->sa_hdr.sh_rspi)
573 		return (-1);
574 	if (a->sa_hdr.sh_rspi < b->sa_hdr.sh_rspi)
575 		return (1);
576 #endif
577 
578 	return (0);
579 }
580 
581 static __inline int
582 sa_addrpool_cmp(struct iked_sa *a, struct iked_sa *b)
583 {
584 	return (sockaddr_cmp((struct sockaddr *)&a->sa_addrpool->addr,
585 	    (struct sockaddr *)&b->sa_addrpool->addr, -1));
586 }
587 
588 static __inline int
589 sa_addrpool6_cmp(struct iked_sa *a, struct iked_sa *b)
590 {
591 	return (sockaddr_cmp((struct sockaddr *)&a->sa_addrpool6->addr,
592 	    (struct sockaddr *)&b->sa_addrpool6->addr, -1));
593 }
594 
595 struct iked_user *
596 user_lookup(struct iked *env, const char *user)
597 {
598 	struct iked_user	 key;
599 
600 	if (strlcpy(key.usr_name, user,
601 	    sizeof(key.usr_name)) >= sizeof(key.usr_name))
602 		return (NULL);
603 
604 	return (RB_FIND(iked_users, &env->sc_users, &key));
605 }
606 
607 static __inline int
608 user_cmp(struct iked_user *a, struct iked_user *b)
609 {
610 	return (strcmp(a->usr_name, b->usr_name));
611 }
612 
613 static __inline int
614 childsa_cmp(struct iked_childsa *a, struct iked_childsa *b)
615 {
616 	if (a->csa_spi.spi > b->csa_spi.spi)
617 		return (1);
618 	if (a->csa_spi.spi < b->csa_spi.spi)
619 		return (-1);
620 	return (0);
621 }
622 
623 static __inline int
624 addr_cmp(struct iked_addr *a, struct iked_addr *b, int useports)
625 {
626 	int		diff = 0;
627 
628 	diff = sockaddr_cmp((struct sockaddr *)&a->addr,
629 	    (struct sockaddr *)&b->addr, 128);
630 	if (!diff)
631 		diff = (int)a->addr_mask - (int)b->addr_mask;
632 	if (!diff && useports)
633 		diff = a->addr_port - b->addr_port;
634 
635 	return (diff);
636 }
637 
638 static __inline int
639 flow_cmp(struct iked_flow *a, struct iked_flow *b)
640 {
641 	int		diff = 0;
642 
643 	if (!diff)
644 		diff = (int)a->flow_ipproto - (int)b->flow_ipproto;
645 	if (!diff)
646 		diff = (int)a->flow_saproto - (int)b->flow_saproto;
647 	if (!diff)
648 		diff = (int)a->flow_dir - (int)b->flow_dir;
649 	if (!diff)
650 		diff = addr_cmp(&a->flow_dst, &b->flow_dst, 1);
651 	if (!diff)
652 		diff = addr_cmp(&a->flow_src, &b->flow_src, 1);
653 
654 	return (diff);
655 }
656 
657 int
658 flow_equal(struct iked_flow *a, struct iked_flow *b)
659 {
660 	return (flow_cmp(a, b) == 0);
661 }
662 
663 RB_GENERATE(iked_sas, iked_sa, sa_entry, sa_cmp);
664 RB_GENERATE(iked_addrpool, iked_sa, sa_addrpool_entry, sa_addrpool_cmp);
665 RB_GENERATE(iked_addrpool6, iked_sa, sa_addrpool6_entry, sa_addrpool6_cmp);
666 RB_GENERATE(iked_users, iked_user, usr_entry, user_cmp);
667 RB_GENERATE(iked_activesas, iked_childsa, csa_node, childsa_cmp);
668 RB_GENERATE(iked_flows, iked_flow, flow_node, flow_cmp);
669