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