1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/kmem.h> 28 #include <sys/ksynch.h> 29 #include <sys/systm.h> 30 #include <sys/socket.h> 31 #include <sys/disp.h> 32 #include <sys/taskq.h> 33 #include <sys/cmn_err.h> 34 #include <sys/strsun.h> 35 #include <sys/sdt.h> 36 #include <sys/atomic.h> 37 #include <netinet/in.h> 38 #include <inet/ip.h> 39 #include <inet/ip6.h> 40 #include <inet/tcp.h> 41 #include <inet/udp_impl.h> 42 #include <inet/kstatcom.h> 43 44 #include <inet/ilb_ip.h> 45 #include "ilb_alg.h" 46 #include "ilb_nat.h" 47 #include "ilb_conn.h" 48 49 /* ILB kmem cache flag */ 50 int ilb_kmem_flags = 0; 51 52 /* 53 * The default size for the different hash tables. Global for all stacks. 54 * But each stack has its own table, just that their sizes are the same. 55 */ 56 static size_t ilb_rule_hash_size = 2048; 57 58 static size_t ilb_conn_hash_size = 262144; 59 60 static size_t ilb_sticky_hash_size = 262144; 61 62 /* This should be a prime number. */ 63 static size_t ilb_nat_src_hash_size = 97; 64 65 /* Default NAT cache entry expiry time. */ 66 static uint32_t ilb_conn_tcp_expiry = 120; 67 static uint32_t ilb_conn_udp_expiry = 60; 68 69 /* Default sticky entry expiry time. */ 70 static uint32_t ilb_sticky_expiry = 60; 71 72 /* addr is assumed to be a uint8_t * to an ipaddr_t. */ 73 #define ILB_RULE_HASH(addr, hash_size) \ 74 ((*((addr) + 3) * 29791 + *((addr) + 2) * 961 + *((addr) + 1) * 31 + \ 75 *(addr)) & ((hash_size) - 1)) 76 77 /* 78 * Note on ILB delayed processing 79 * 80 * To avoid in line removal on some of the data structures, such as rules, 81 * servers and ilb_conn_hash entries, ILB delays such processing to a taskq. 82 * There are three types of ILB taskq: 83 * 84 * 1. rule handling: created at stack initialialization time, ilb_stack_init() 85 * 2. conn hash handling: created at conn hash initialization time, 86 * ilb_conn_hash_init() 87 * 3. sticky hash handling: created at sticky hash initialization time, 88 * ilb_sticky_hash_init() 89 * 90 * The rule taskq is for processing rule and server removal. When a user 91 * land rule/server removal request comes in, a taskq is dispatched after 92 * removing the rule/server from all related hashes. This taskq will wait 93 * until all references to the rule/server are gone before removing it. 94 * So the user land thread requesting the removal does not need to wait 95 * for the removal completion. 96 * 97 * The conn hash/sticky hash taskq is for processing ilb_conn_hash and 98 * ilb_sticky_hash table entry removal. There are ilb_conn_timer_size timers 99 * and ilb_sticky_timer_size timers running for ilb_conn_hash and 100 * ilb_sticky_hash cleanup respectively. Each timer is responsible for one 101 * portion (same size) of the hash table. When a timer fires, it dispatches 102 * a conn hash taskq to clean up its portion of the table. This avoids in 103 * line processing of the removal. 104 * 105 * There is another delayed processing, the clean up of NAT source address 106 * table. We just use the timer to directly handle it instead of using 107 * a taskq. The reason is that the table is small so it is OK to use the 108 * timer. 109 */ 110 111 /* ILB rule taskq constants. */ 112 #define ILB_RULE_TASKQ_NUM_THR 20 113 114 /* Argument passed to ILB rule taskq routines. */ 115 typedef struct { 116 ilb_stack_t *ilbs; 117 ilb_rule_t *rule; 118 } ilb_rule_tq_t; 119 120 /* kstat handling routines. */ 121 static kstat_t *ilb_kstat_g_init(netstackid_t, ilb_stack_t *); 122 static void ilb_kstat_g_fini(netstackid_t, ilb_stack_t *); 123 static kstat_t *ilb_rule_kstat_init(netstackid_t, ilb_rule_t *); 124 static kstat_t *ilb_server_kstat_init(netstackid_t, ilb_rule_t *, 125 ilb_server_t *); 126 127 /* Rule hash handling routines. */ 128 static void ilb_rule_hash_init(ilb_stack_t *); 129 static void ilb_rule_hash_fini(ilb_stack_t *); 130 static void ilb_rule_hash_add(ilb_stack_t *, ilb_rule_t *, const in6_addr_t *); 131 static void ilb_rule_hash_del(ilb_rule_t *); 132 static ilb_rule_t *ilb_rule_hash(ilb_stack_t *, int, int, in6_addr_t *, 133 in_port_t, zoneid_t, uint32_t, boolean_t *); 134 135 static void ilb_rule_g_add(ilb_stack_t *, ilb_rule_t *); 136 static void ilb_rule_g_del(ilb_stack_t *, ilb_rule_t *); 137 static void ilb_del_rule_common(ilb_stack_t *, ilb_rule_t *); 138 static ilb_rule_t *ilb_find_rule_locked(ilb_stack_t *, zoneid_t, const char *, 139 int *); 140 static boolean_t ilb_match_rule(ilb_stack_t *, zoneid_t, const char *, int, 141 int, in_port_t, in_port_t, const in6_addr_t *); 142 143 /* Back end server handling routines. */ 144 static void ilb_server_free(ilb_server_t *); 145 146 /* Network stack handling routines. */ 147 static void *ilb_stack_init(netstackid_t, netstack_t *); 148 static void ilb_stack_shutdown(netstackid_t, void *); 149 static void ilb_stack_fini(netstackid_t, void *); 150 151 /* Sticky connection handling routines. */ 152 static void ilb_rule_sticky_init(ilb_rule_t *); 153 static void ilb_rule_sticky_fini(ilb_rule_t *); 154 155 /* Handy macro to check for unspecified address. */ 156 #define IS_ADDR_UNSPEC(addr) \ 157 (IN6_IS_ADDR_V4MAPPED(addr) ? IN6_IS_ADDR_V4MAPPED_ANY(addr) : \ 158 IN6_IS_ADDR_UNSPECIFIED(addr)) 159 160 /* 161 * Global kstat instance counter. When a rule is created, its kstat instance 162 * number is assigned by ilb_kstat_instance and ilb_kstat_instance is 163 * incremented. 164 */ 165 static uint_t ilb_kstat_instance = 0; 166 167 /* 168 * The ILB global kstat has name ILB_G_KS_NAME and class name ILB_G_KS_CNAME. 169 * A rule's kstat has ILB_RULE_KS_CNAME class name. 170 */ 171 #define ILB_G_KS_NAME "global" 172 #define ILB_G_KS_CNAME "kstat" 173 #define ILB_RULE_KS_CNAME "rulestat" 174 175 static kstat_t * 176 ilb_kstat_g_init(netstackid_t stackid, ilb_stack_t *ilbs) 177 { 178 kstat_t *ksp; 179 ilb_g_kstat_t template = { 180 { "num_rules", KSTAT_DATA_UINT64, 0 }, 181 { "ip_frag_in", KSTAT_DATA_UINT64, 0 }, 182 { "ip_frag_dropped", KSTAT_DATA_UINT64, 0 } 183 }; 184 185 ksp = kstat_create_netstack(ILB_KSTAT_MOD_NAME, 0, ILB_G_KS_NAME, 186 ILB_G_KS_CNAME, KSTAT_TYPE_NAMED, NUM_OF_FIELDS(ilb_g_kstat_t), 187 KSTAT_FLAG_VIRTUAL, stackid); 188 if (ksp == NULL) 189 return (NULL); 190 bcopy(&template, ilbs->ilbs_kstat, sizeof (template)); 191 ksp->ks_data = ilbs->ilbs_kstat; 192 ksp->ks_private = (void *)(uintptr_t)stackid; 193 194 kstat_install(ksp); 195 return (ksp); 196 } 197 198 static void 199 ilb_kstat_g_fini(netstackid_t stackid, ilb_stack_t *ilbs) 200 { 201 if (ilbs->ilbs_ksp != NULL) { 202 ASSERT(stackid == (netstackid_t)(uintptr_t) 203 ilbs->ilbs_ksp->ks_private); 204 kstat_delete_netstack(ilbs->ilbs_ksp, stackid); 205 ilbs->ilbs_ksp = NULL; 206 } 207 } 208 209 static kstat_t * 210 ilb_rule_kstat_init(netstackid_t stackid, ilb_rule_t *rule) 211 { 212 kstat_t *ksp; 213 ilb_rule_kstat_t template = { 214 { "num_servers", KSTAT_DATA_UINT64, 0 }, 215 { "bytes_not_processed", KSTAT_DATA_UINT64, 0 }, 216 { "pkt_not_processed", KSTAT_DATA_UINT64, 0 }, 217 { "bytes_dropped", KSTAT_DATA_UINT64, 0 }, 218 { "pkt_dropped", KSTAT_DATA_UINT64, 0 }, 219 { "nomem_bytes_dropped", KSTAT_DATA_UINT64, 0 }, 220 { "nomem_pkt_dropped", KSTAT_DATA_UINT64, 0 }, 221 { "noport_bytes_dropped", KSTAT_DATA_UINT64, 0 }, 222 { "noport_pkt_dropped", KSTAT_DATA_UINT64, 0 }, 223 { "icmp_echo_processed", KSTAT_DATA_UINT64, 0 }, 224 { "icmp_dropped", KSTAT_DATA_UINT64, 0 }, 225 { "icmp_too_big_processed", KSTAT_DATA_UINT64, 0 }, 226 { "icmp_too_big_dropped", KSTAT_DATA_UINT64, 0 } 227 }; 228 229 ksp = kstat_create_netstack(ILB_KSTAT_MOD_NAME, rule->ir_ks_instance, 230 rule->ir_name, ILB_RULE_KS_CNAME, KSTAT_TYPE_NAMED, 231 NUM_OF_FIELDS(ilb_rule_kstat_t), KSTAT_FLAG_VIRTUAL, stackid); 232 if (ksp == NULL) 233 return (NULL); 234 235 bcopy(&template, &rule->ir_kstat, sizeof (template)); 236 ksp->ks_data = &rule->ir_kstat; 237 ksp->ks_private = (void *)(uintptr_t)stackid; 238 239 kstat_install(ksp); 240 return (ksp); 241 } 242 243 static kstat_t * 244 ilb_server_kstat_init(netstackid_t stackid, ilb_rule_t *rule, 245 ilb_server_t *server) 246 { 247 kstat_t *ksp; 248 ilb_server_kstat_t template = { 249 { "bytes_processed", KSTAT_DATA_UINT64, 0 }, 250 { "pkt_processed", KSTAT_DATA_UINT64, 0 }, 251 { "ip_address", KSTAT_DATA_STRING, 0 } 252 }; 253 char cname_buf[KSTAT_STRLEN]; 254 255 /* 7 is "-sstat" */ 256 ASSERT(strlen(rule->ir_name) + 7 < KSTAT_STRLEN); 257 (void) sprintf(cname_buf, "%s-sstat", rule->ir_name); 258 ksp = kstat_create_netstack(ILB_KSTAT_MOD_NAME, rule->ir_ks_instance, 259 server->iser_name, cname_buf, KSTAT_TYPE_NAMED, 260 NUM_OF_FIELDS(ilb_server_kstat_t), KSTAT_FLAG_VIRTUAL, stackid); 261 if (ksp == NULL) 262 return (NULL); 263 264 bcopy(&template, &server->iser_kstat, sizeof (template)); 265 ksp->ks_data = &server->iser_kstat; 266 ksp->ks_private = (void *)(uintptr_t)stackid; 267 268 kstat_named_setstr(&server->iser_kstat.ip_address, 269 server->iser_ip_addr); 270 /* We never change the IP address */ 271 ksp->ks_data_size += strlen(server->iser_ip_addr) + 1; 272 273 kstat_install(ksp); 274 return (ksp); 275 } 276 277 /* Initialize the rule hash table. */ 278 static void 279 ilb_rule_hash_init(ilb_stack_t *ilbs) 280 { 281 int i; 282 283 /* 284 * If ilbs->ilbs_rule_hash_size is not a power of 2, bump it up to 285 * the next power of 2. 286 */ 287 if (ilbs->ilbs_rule_hash_size & (ilbs->ilbs_rule_hash_size - 1)) { 288 for (i = 0; i < 31; i++) { 289 if (ilbs->ilbs_rule_hash_size < (1 << i)) 290 break; 291 } 292 ilbs->ilbs_rule_hash_size = 1 << i; 293 } 294 ilbs->ilbs_g_hash = kmem_zalloc(sizeof (ilb_hash_t) * 295 ilbs->ilbs_rule_hash_size, KM_SLEEP); 296 for (i = 0; i < ilbs->ilbs_rule_hash_size; i++) { 297 mutex_init(&ilbs->ilbs_g_hash[i].ilb_hash_lock, NULL, 298 MUTEX_DEFAULT, NULL); 299 } 300 } 301 302 /* Clean up the rule hash table. */ 303 static void 304 ilb_rule_hash_fini(ilb_stack_t *ilbs) 305 { 306 if (ilbs->ilbs_g_hash == NULL) 307 return; 308 kmem_free(ilbs->ilbs_g_hash, sizeof (ilb_hash_t) * 309 ilbs->ilbs_rule_hash_size); 310 } 311 312 /* Add a rule to the rule hash table. */ 313 static void 314 ilb_rule_hash_add(ilb_stack_t *ilbs, ilb_rule_t *rule, const in6_addr_t *addr) 315 { 316 int i; 317 318 i = ILB_RULE_HASH((uint8_t *)&addr->s6_addr32[3], 319 ilbs->ilbs_rule_hash_size); 320 DTRACE_PROBE2(ilb__rule__hash__add, ilb_rule_t *, rule, int, i); 321 mutex_enter(&ilbs->ilbs_g_hash[i].ilb_hash_lock); 322 rule->ir_hash_next = ilbs->ilbs_g_hash[i].ilb_hash_rule; 323 if (ilbs->ilbs_g_hash[i].ilb_hash_rule != NULL) 324 ilbs->ilbs_g_hash[i].ilb_hash_rule->ir_hash_prev = rule; 325 rule->ir_hash_prev = NULL; 326 ilbs->ilbs_g_hash[i].ilb_hash_rule = rule; 327 328 rule->ir_hash = &ilbs->ilbs_g_hash[i]; 329 mutex_exit(&ilbs->ilbs_g_hash[i].ilb_hash_lock); 330 } 331 332 /* 333 * Remove a rule from the rule hash table. Note that the rule is not freed 334 * in this routine. 335 */ 336 static void 337 ilb_rule_hash_del(ilb_rule_t *rule) 338 { 339 mutex_enter(&rule->ir_hash->ilb_hash_lock); 340 if (rule->ir_hash->ilb_hash_rule == rule) { 341 rule->ir_hash->ilb_hash_rule = rule->ir_hash_next; 342 if (rule->ir_hash_next != NULL) 343 rule->ir_hash_next->ir_hash_prev = NULL; 344 } else { 345 if (rule->ir_hash_prev != NULL) 346 rule->ir_hash_prev->ir_hash_next = 347 rule->ir_hash_next; 348 if (rule->ir_hash_next != NULL) { 349 rule->ir_hash_next->ir_hash_prev = 350 rule->ir_hash_prev; 351 } 352 } 353 mutex_exit(&rule->ir_hash->ilb_hash_lock); 354 355 rule->ir_hash_next = NULL; 356 rule->ir_hash_prev = NULL; 357 rule->ir_hash = NULL; 358 } 359 360 /* 361 * Given the info of a packet, look for a match in the rule hash table. 362 */ 363 static ilb_rule_t * 364 ilb_rule_hash(ilb_stack_t *ilbs, int l3, int l4, in6_addr_t *addr, 365 in_port_t port, zoneid_t zoneid, uint32_t len, boolean_t *busy) 366 { 367 int i; 368 ilb_rule_t *rule; 369 ipaddr_t v4_addr; 370 371 *busy = B_FALSE; 372 IN6_V4MAPPED_TO_IPADDR(addr, v4_addr); 373 i = ILB_RULE_HASH((uint8_t *)&v4_addr, ilbs->ilbs_rule_hash_size); 374 port = ntohs(port); 375 376 mutex_enter(&ilbs->ilbs_g_hash[i].ilb_hash_lock); 377 for (rule = ilbs->ilbs_g_hash[i].ilb_hash_rule; rule != NULL; 378 rule = rule->ir_hash_next) { 379 if (!rule->ir_port_range) { 380 if (rule->ir_min_port != port) 381 continue; 382 } else { 383 if (port < rule->ir_min_port || 384 port > rule->ir_max_port) { 385 continue; 386 } 387 } 388 if (rule->ir_ipver != l3 || rule->ir_proto != l4 || 389 rule->ir_zoneid != zoneid) { 390 continue; 391 } 392 393 if (l3 == IPPROTO_IP) { 394 if (rule->ir_target_v4 != INADDR_ANY && 395 rule->ir_target_v4 != v4_addr) { 396 continue; 397 } 398 } else { 399 if (!IN6_IS_ADDR_UNSPECIFIED(&rule->ir_target_v6) && 400 !IN6_ARE_ADDR_EQUAL(addr, &rule->ir_target_v6)) { 401 continue; 402 } 403 } 404 405 /* 406 * Just update the stats if the rule is disabled. 407 */ 408 mutex_enter(&rule->ir_lock); 409 if (!(rule->ir_flags & ILB_RULE_ENABLED)) { 410 ILB_R_KSTAT(rule, pkt_not_processed); 411 ILB_R_KSTAT_UPDATE(rule, bytes_not_processed, len); 412 mutex_exit(&rule->ir_lock); 413 rule = NULL; 414 break; 415 } else if (rule->ir_flags & ILB_RULE_BUSY) { 416 /* 417 * If we are busy... 418 * 419 * XXX we should have a queue to postpone the 420 * packet processing. But this requires a 421 * mechanism in IP to re-start the packet 422 * processing. So for now, just drop the packet. 423 */ 424 ILB_R_KSTAT(rule, pkt_dropped); 425 ILB_R_KSTAT_UPDATE(rule, bytes_dropped, len); 426 mutex_exit(&rule->ir_lock); 427 *busy = B_TRUE; 428 rule = NULL; 429 break; 430 } else { 431 rule->ir_refcnt++; 432 ASSERT(rule->ir_refcnt != 1); 433 mutex_exit(&rule->ir_lock); 434 break; 435 } 436 } 437 mutex_exit(&ilbs->ilbs_g_hash[i].ilb_hash_lock); 438 return (rule); 439 } 440 441 /* 442 * Add a rule to the global rule list. This list is for finding all rules 443 * in an IP stack. The caller is assumed to hold the ilbs_g_lock. 444 */ 445 static void 446 ilb_rule_g_add(ilb_stack_t *ilbs, ilb_rule_t *rule) 447 { 448 ASSERT(mutex_owned(&ilbs->ilbs_g_lock)); 449 rule->ir_next = ilbs->ilbs_rule_head; 450 ilbs->ilbs_rule_head = rule; 451 ILB_KSTAT_UPDATE(ilbs, num_rules, 1); 452 } 453 454 /* The call is assumed to hold the ilbs_g_lock. */ 455 static void 456 ilb_rule_g_del(ilb_stack_t *ilbs, ilb_rule_t *rule) 457 { 458 ilb_rule_t *tmp_rule; 459 ilb_rule_t *prev_rule; 460 461 ASSERT(mutex_owned(&ilbs->ilbs_g_lock)); 462 prev_rule = NULL; 463 for (tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL; 464 prev_rule = tmp_rule, tmp_rule = tmp_rule->ir_next) { 465 if (tmp_rule == rule) 466 break; 467 } 468 if (tmp_rule == NULL) { 469 mutex_exit(&ilbs->ilbs_g_lock); 470 return; 471 } 472 if (prev_rule == NULL) 473 ilbs->ilbs_rule_head = tmp_rule->ir_next; 474 else 475 prev_rule->ir_next = tmp_rule->ir_next; 476 ILB_KSTAT_UPDATE(ilbs, num_rules, -1); 477 } 478 479 /* 480 * Helper routine to calculate how many source addresses are in a given 481 * range. 482 */ 483 static int64_t 484 num_nat_src_v6(const in6_addr_t *a1, const in6_addr_t *a2) 485 { 486 int64_t ret; 487 uint32_t addr1, addr2; 488 489 /* 490 * Here we assume that the max number of NAT source cannot be 491 * large such that the most significant 2 s6_addr32 must be 492 * equal. 493 */ 494 addr1 = ntohl(a1->s6_addr32[3]); 495 addr2 = ntohl(a2->s6_addr32[3]); 496 if (a1->s6_addr32[0] != a2->s6_addr32[0] || 497 a1->s6_addr32[1] != a2->s6_addr32[1] || 498 a1->s6_addr32[2] > a2->s6_addr32[2] || 499 (a1->s6_addr32[2] == a2->s6_addr32[2] && addr1 > addr2)) { 500 return (-1); 501 } 502 if (a1->s6_addr32[2] == a2->s6_addr32[2]) { 503 return (addr2 - addr1 + 1); 504 } else { 505 ret = (ntohl(a2->s6_addr32[2]) - ntohl(a1->s6_addr32[2])); 506 ret <<= 32; 507 ret = ret + addr1 - addr2; 508 return (ret + 1); 509 } 510 } 511 512 /* 513 * Add an ILB rule. 514 */ 515 int 516 ilb_rule_add(ilb_stack_t *ilbs, zoneid_t zoneid, const ilb_rule_cmd_t *cmd) 517 { 518 ilb_rule_t *rule; 519 netstackid_t stackid; 520 int ret; 521 in_port_t min_port, max_port; 522 int64_t num_src; 523 524 /* Sanity checks. */ 525 if (cmd->ip_ver != IPPROTO_IP && cmd->ip_ver != IPPROTO_IPV6) 526 return (EINVAL); 527 528 /* Need to support SCTP... */ 529 if (cmd->proto != IPPROTO_TCP && cmd->proto != IPPROTO_UDP) 530 return (EINVAL); 531 532 /* For full NAT, the NAT source must be supplied. */ 533 if (cmd->topo == ILB_TOPO_IMPL_NAT) { 534 if (IS_ADDR_UNSPEC(&cmd->nat_src_start) || 535 IS_ADDR_UNSPEC(&cmd->nat_src_end)) { 536 return (EINVAL); 537 } 538 } 539 540 /* Check invalid mask */ 541 if ((cmd->flags & ILB_RULE_STICKY) && 542 IS_ADDR_UNSPEC(&cmd->sticky_mask)) { 543 return (EINVAL); 544 } 545 546 /* Port is passed in network byte order. */ 547 min_port = ntohs(cmd->min_port); 548 max_port = ntohs(cmd->max_port); 549 if (min_port > max_port) 550 return (EINVAL); 551 552 /* min_port == 0 means "all ports". Make it so */ 553 if (min_port == 0) { 554 min_port = 1; 555 max_port = 65535; 556 } 557 558 /* Funny address checking. */ 559 if (cmd->ip_ver == IPPROTO_IP) { 560 in_addr_t v4_addr1, v4_addr2; 561 562 v4_addr1 = cmd->vip.s6_addr32[3]; 563 if ((*(uchar_t *)&v4_addr1) == IN_LOOPBACKNET || 564 CLASSD(v4_addr1) || v4_addr1 == INADDR_BROADCAST || 565 v4_addr1 == INADDR_ANY || 566 !IN6_IS_ADDR_V4MAPPED(&cmd->vip)) { 567 return (EINVAL); 568 } 569 570 if (cmd->topo == ILB_TOPO_IMPL_NAT) { 571 v4_addr1 = ntohl(cmd->nat_src_start.s6_addr32[3]); 572 v4_addr2 = ntohl(cmd->nat_src_end.s6_addr32[3]); 573 if ((*(uchar_t *)&v4_addr1) == IN_LOOPBACKNET || 574 (*(uchar_t *)&v4_addr2) == IN_LOOPBACKNET || 575 v4_addr1 == INADDR_BROADCAST || 576 v4_addr2 == INADDR_BROADCAST || 577 v4_addr1 == INADDR_ANY || v4_addr2 == INADDR_ANY || 578 CLASSD(v4_addr1) || CLASSD(v4_addr2) || 579 !IN6_IS_ADDR_V4MAPPED(&cmd->nat_src_start) || 580 !IN6_IS_ADDR_V4MAPPED(&cmd->nat_src_end)) { 581 return (EINVAL); 582 } 583 584 num_src = v4_addr2 - v4_addr1 + 1; 585 if (v4_addr1 > v4_addr2 || num_src > ILB_MAX_NAT_SRC) 586 return (EINVAL); 587 } 588 } else { 589 if (IN6_IS_ADDR_LOOPBACK(&cmd->vip) || 590 IN6_IS_ADDR_MULTICAST(&cmd->vip) || 591 IN6_IS_ADDR_UNSPECIFIED(&cmd->vip) || 592 IN6_IS_ADDR_V4MAPPED(&cmd->vip)) { 593 return (EINVAL); 594 } 595 596 if (cmd->topo == ILB_TOPO_IMPL_NAT) { 597 if (IN6_IS_ADDR_LOOPBACK(&cmd->nat_src_start) || 598 IN6_IS_ADDR_LOOPBACK(&cmd->nat_src_end) || 599 IN6_IS_ADDR_MULTICAST(&cmd->nat_src_start) || 600 IN6_IS_ADDR_MULTICAST(&cmd->nat_src_end) || 601 IN6_IS_ADDR_UNSPECIFIED(&cmd->nat_src_start) || 602 IN6_IS_ADDR_UNSPECIFIED(&cmd->nat_src_end) || 603 IN6_IS_ADDR_V4MAPPED(&cmd->nat_src_start) || 604 IN6_IS_ADDR_V4MAPPED(&cmd->nat_src_end)) { 605 return (EINVAL); 606 } 607 608 if ((num_src = num_nat_src_v6(&cmd->nat_src_start, 609 &cmd->nat_src_end)) < 0 || 610 num_src > ILB_MAX_NAT_SRC) { 611 return (EINVAL); 612 } 613 } 614 } 615 616 mutex_enter(&ilbs->ilbs_g_lock); 617 if (ilbs->ilbs_g_hash == NULL) 618 ilb_rule_hash_init(ilbs); 619 if (ilbs->ilbs_c2s_conn_hash == NULL) { 620 ASSERT(ilbs->ilbs_s2c_conn_hash == NULL); 621 ilb_conn_hash_init(ilbs); 622 ilb_nat_src_init(ilbs); 623 } 624 625 /* Make sure that the new rule does not duplicate an existing one. */ 626 if (ilb_match_rule(ilbs, zoneid, cmd->name, cmd->ip_ver, cmd->proto, 627 min_port, max_port, &cmd->vip)) { 628 mutex_exit(&ilbs->ilbs_g_lock); 629 return (EEXIST); 630 } 631 632 rule = kmem_zalloc(sizeof (ilb_rule_t), KM_NOSLEEP); 633 if (rule == NULL) { 634 mutex_exit(&ilbs->ilbs_g_lock); 635 return (ENOMEM); 636 } 637 638 /* ir_name is all 0 to begin with */ 639 (void) memcpy(rule->ir_name, cmd->name, ILB_RULE_NAMESZ - 1); 640 641 rule->ir_ks_instance = atomic_add_int_nv(&ilb_kstat_instance, 1); 642 stackid = (netstackid_t)(uintptr_t)ilbs->ilbs_ksp->ks_private; 643 if ((rule->ir_ksp = ilb_rule_kstat_init(stackid, rule)) == NULL) { 644 ret = ENOMEM; 645 goto error; 646 } 647 648 if (cmd->topo == ILB_TOPO_IMPL_NAT) { 649 rule->ir_nat_src_start = cmd->nat_src_start; 650 rule->ir_nat_src_end = cmd->nat_src_end; 651 } 652 653 rule->ir_ipver = cmd->ip_ver; 654 rule->ir_proto = cmd->proto; 655 rule->ir_topo = cmd->topo; 656 657 rule->ir_min_port = min_port; 658 rule->ir_max_port = max_port; 659 if (rule->ir_min_port != rule->ir_max_port) 660 rule->ir_port_range = B_TRUE; 661 else 662 rule->ir_port_range = B_FALSE; 663 664 rule->ir_zoneid = zoneid; 665 666 rule->ir_target_v6 = cmd->vip; 667 rule->ir_servers = NULL; 668 669 /* 670 * The default connection drain timeout is indefinite (value 0), 671 * meaning we will wait for all connections to finish. So we 672 * can assign cmd->conn_drain_timeout to it directly. 673 */ 674 rule->ir_conn_drain_timeout = cmd->conn_drain_timeout; 675 if (cmd->nat_expiry != 0) { 676 rule->ir_nat_expiry = cmd->nat_expiry; 677 } else { 678 switch (rule->ir_proto) { 679 case IPPROTO_TCP: 680 rule->ir_nat_expiry = ilb_conn_tcp_expiry; 681 break; 682 case IPPROTO_UDP: 683 rule->ir_nat_expiry = ilb_conn_udp_expiry; 684 break; 685 default: 686 cmn_err(CE_PANIC, "data corruption: wrong ir_proto: %p", 687 (void *)rule); 688 break; 689 } 690 } 691 if (cmd->sticky_expiry != 0) 692 rule->ir_sticky_expiry = cmd->sticky_expiry; 693 else 694 rule->ir_sticky_expiry = ilb_sticky_expiry; 695 696 if (cmd->flags & ILB_RULE_STICKY) { 697 rule->ir_flags |= ILB_RULE_STICKY; 698 rule->ir_sticky_mask = cmd->sticky_mask; 699 if (ilbs->ilbs_sticky_hash == NULL) 700 ilb_sticky_hash_init(ilbs); 701 } 702 if (cmd->flags & ILB_RULE_ENABLED) 703 rule->ir_flags |= ILB_RULE_ENABLED; 704 705 mutex_init(&rule->ir_lock, NULL, MUTEX_DEFAULT, NULL); 706 cv_init(&rule->ir_cv, NULL, CV_DEFAULT, NULL); 707 708 rule->ir_refcnt = 1; 709 710 switch (cmd->algo) { 711 case ILB_ALG_IMPL_ROUNDROBIN: 712 if ((rule->ir_alg = ilb_alg_rr_init(rule, NULL)) == NULL) { 713 ret = ENOMEM; 714 goto error; 715 } 716 rule->ir_alg_type = ILB_ALG_IMPL_ROUNDROBIN; 717 break; 718 case ILB_ALG_IMPL_HASH_IP: 719 case ILB_ALG_IMPL_HASH_IP_SPORT: 720 case ILB_ALG_IMPL_HASH_IP_VIP: 721 if ((rule->ir_alg = ilb_alg_hash_init(rule, 722 &cmd->algo)) == NULL) { 723 ret = ENOMEM; 724 goto error; 725 } 726 rule->ir_alg_type = cmd->algo; 727 break; 728 default: 729 ret = EINVAL; 730 goto error; 731 } 732 733 /* Add it to the global list and hash array at the end. */ 734 ilb_rule_g_add(ilbs, rule); 735 ilb_rule_hash_add(ilbs, rule, &cmd->vip); 736 737 mutex_exit(&ilbs->ilbs_g_lock); 738 739 return (0); 740 741 error: 742 mutex_exit(&ilbs->ilbs_g_lock); 743 if (rule->ir_ksp != NULL) { 744 /* stackid must be initialized if ir_ksp != NULL */ 745 kstat_delete_netstack(rule->ir_ksp, stackid); 746 } 747 kmem_free(rule, sizeof (ilb_rule_t)); 748 return (ret); 749 } 750 751 /* 752 * The final part in deleting a rule. Either called directly or by the 753 * taskq dispatched. 754 */ 755 static void 756 ilb_rule_del_common(ilb_stack_t *ilbs, ilb_rule_t *tmp_rule) 757 { 758 netstackid_t stackid; 759 ilb_server_t *server; 760 761 stackid = (netstackid_t)(uintptr_t)ilbs->ilbs_ksp->ks_private; 762 763 /* 764 * Let the algorithm know that the rule is going away. The 765 * algorithm fini routine will free all its resources with this 766 * rule. 767 */ 768 tmp_rule->ir_alg->ilb_alg_fini(&tmp_rule->ir_alg); 769 770 while ((server = tmp_rule->ir_servers) != NULL) { 771 mutex_enter(&server->iser_lock); 772 ilb_destroy_nat_src(&server->iser_nat_src); 773 if (tmp_rule->ir_conn_drain_timeout != 0) { 774 /* 775 * The garbage collection thread checks this value 776 * without grabing a lock. So we need to use 777 * atomic_swap_64() to make sure that the value seen 778 * by gc thread is intact. 779 */ 780 (void) atomic_swap_64( 781 (uint64_t *)&server->iser_die_time, 782 ddi_get_lbolt64() + 783 SEC_TO_TICK(tmp_rule->ir_conn_drain_timeout)); 784 } 785 while (server->iser_refcnt > 1) 786 cv_wait(&server->iser_cv, &server->iser_lock); 787 tmp_rule->ir_servers = server->iser_next; 788 kstat_delete_netstack(server->iser_ksp, stackid); 789 kmem_free(server, sizeof (ilb_server_t)); 790 } 791 792 ASSERT(tmp_rule->ir_ksp != NULL); 793 kstat_delete_netstack(tmp_rule->ir_ksp, stackid); 794 795 kmem_free(tmp_rule, sizeof (ilb_rule_t)); 796 } 797 798 /* The routine executed by the delayed rule taskq. */ 799 static void 800 ilb_rule_del_tq(void *arg) 801 { 802 ilb_stack_t *ilbs = ((ilb_rule_tq_t *)arg)->ilbs; 803 ilb_rule_t *rule = ((ilb_rule_tq_t *)arg)->rule; 804 805 mutex_enter(&rule->ir_lock); 806 while (rule->ir_refcnt > 1) 807 cv_wait(&rule->ir_cv, &rule->ir_lock); 808 ilb_rule_del_common(ilbs, rule); 809 kmem_free(arg, sizeof (ilb_rule_tq_t)); 810 } 811 812 /* Routine to delete a rule. */ 813 int 814 ilb_rule_del(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name) 815 { 816 ilb_rule_t *tmp_rule; 817 ilb_rule_tq_t *arg; 818 int err; 819 820 mutex_enter(&ilbs->ilbs_g_lock); 821 if ((tmp_rule = ilb_find_rule_locked(ilbs, zoneid, name, 822 &err)) == NULL) { 823 mutex_exit(&ilbs->ilbs_g_lock); 824 return (err); 825 } 826 827 /* 828 * First remove the rule from the hash array and the global list so 829 * that no one can find this rule any more. 830 */ 831 ilb_rule_hash_del(tmp_rule); 832 ilb_rule_g_del(ilbs, tmp_rule); 833 mutex_exit(&ilbs->ilbs_g_lock); 834 ILB_RULE_REFRELE(tmp_rule); 835 836 /* 837 * Now no one can find this rule, we can remove it once all 838 * references to it are dropped and all references to the list 839 * of servers are dropped. So dispatch a task to finish the deletion. 840 * We do this instead of letting the last one referencing the 841 * rule do it. The reason is that the last one may be the 842 * interrupt thread. We want to minimize the work it needs to 843 * do. Rule deletion is not a critical task so it can be delayed. 844 */ 845 arg = kmem_alloc(sizeof (ilb_rule_tq_t), KM_SLEEP); 846 arg->ilbs = ilbs; 847 arg->rule = tmp_rule; 848 (void) taskq_dispatch(ilbs->ilbs_rule_taskq, ilb_rule_del_tq, arg, 849 TQ_SLEEP); 850 851 return (0); 852 } 853 854 /* 855 * Given an IP address, check to see if there is a rule using this 856 * as the VIP. It can be used to check if we need to drop a fragment. 857 */ 858 boolean_t 859 ilb_rule_match_vip_v6(ilb_stack_t *ilbs, in6_addr_t *vip, ilb_rule_t **ret_rule) 860 { 861 int i; 862 ilb_rule_t *rule; 863 boolean_t ret = B_FALSE; 864 865 i = ILB_RULE_HASH((uint8_t *)&vip->s6_addr32[3], 866 ilbs->ilbs_rule_hash_size); 867 mutex_enter(&ilbs->ilbs_g_hash[i].ilb_hash_lock); 868 for (rule = ilbs->ilbs_g_hash[i].ilb_hash_rule; rule != NULL; 869 rule = rule->ir_hash_next) { 870 if (IN6_ARE_ADDR_EQUAL(vip, &rule->ir_target_v6)) { 871 mutex_enter(&rule->ir_lock); 872 if (rule->ir_flags & ILB_RULE_BUSY) { 873 mutex_exit(&rule->ir_lock); 874 break; 875 } 876 if (ret_rule != NULL) { 877 rule->ir_refcnt++; 878 mutex_exit(&rule->ir_lock); 879 *ret_rule = rule; 880 } else { 881 mutex_exit(&rule->ir_lock); 882 } 883 ret = B_TRUE; 884 break; 885 } 886 } 887 mutex_exit(&ilbs->ilbs_g_hash[i].ilb_hash_lock); 888 return (ret); 889 } 890 891 boolean_t 892 ilb_rule_match_vip_v4(ilb_stack_t *ilbs, ipaddr_t addr, ilb_rule_t **ret_rule) 893 { 894 int i; 895 ilb_rule_t *rule; 896 boolean_t ret = B_FALSE; 897 898 i = ILB_RULE_HASH((uint8_t *)&addr, ilbs->ilbs_rule_hash_size); 899 mutex_enter(&ilbs->ilbs_g_hash[i].ilb_hash_lock); 900 for (rule = ilbs->ilbs_g_hash[i].ilb_hash_rule; rule != NULL; 901 rule = rule->ir_hash_next) { 902 if (rule->ir_target_v6.s6_addr32[3] == addr) { 903 mutex_enter(&rule->ir_lock); 904 if (rule->ir_flags & ILB_RULE_BUSY) { 905 mutex_exit(&rule->ir_lock); 906 break; 907 } 908 if (ret_rule != NULL) { 909 rule->ir_refcnt++; 910 mutex_exit(&rule->ir_lock); 911 *ret_rule = rule; 912 } else { 913 mutex_exit(&rule->ir_lock); 914 } 915 ret = B_TRUE; 916 break; 917 } 918 } 919 mutex_exit(&ilbs->ilbs_g_hash[i].ilb_hash_lock); 920 return (ret); 921 } 922 923 static ilb_rule_t * 924 ilb_find_rule_locked(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name, 925 int *err) 926 { 927 ilb_rule_t *tmp_rule; 928 929 ASSERT(mutex_owned(&ilbs->ilbs_g_lock)); 930 931 for (tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL; 932 tmp_rule = tmp_rule->ir_next) { 933 if (tmp_rule->ir_zoneid != zoneid) 934 continue; 935 if (strcasecmp(tmp_rule->ir_name, name) == 0) { 936 mutex_enter(&tmp_rule->ir_lock); 937 if (tmp_rule->ir_flags & ILB_RULE_BUSY) { 938 mutex_exit(&tmp_rule->ir_lock); 939 *err = EINPROGRESS; 940 return (NULL); 941 } 942 tmp_rule->ir_refcnt++; 943 mutex_exit(&tmp_rule->ir_lock); 944 *err = 0; 945 return (tmp_rule); 946 } 947 } 948 *err = ENOENT; 949 return (NULL); 950 } 951 952 /* To find a rule with a given name and zone in the global rule list. */ 953 ilb_rule_t * 954 ilb_find_rule(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name, 955 int *err) 956 { 957 ilb_rule_t *tmp_rule; 958 959 mutex_enter(&ilbs->ilbs_g_lock); 960 tmp_rule = ilb_find_rule_locked(ilbs, zoneid, name, err); 961 mutex_exit(&ilbs->ilbs_g_lock); 962 return (tmp_rule); 963 } 964 965 /* Try to match the given packet info and zone ID with a rule. */ 966 static boolean_t 967 ilb_match_rule(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name, int l3, 968 int l4, in_port_t min_port, in_port_t max_port, const in6_addr_t *addr) 969 { 970 ilb_rule_t *tmp_rule; 971 972 ASSERT(mutex_owned(&ilbs->ilbs_g_lock)); 973 974 for (tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL; 975 tmp_rule = tmp_rule->ir_next) { 976 if (tmp_rule->ir_zoneid != zoneid) 977 continue; 978 979 /* 980 * We don't allow the same name in different rules even if all 981 * the other rule components are different. 982 */ 983 if (strcasecmp(tmp_rule->ir_name, name) == 0) 984 return (B_TRUE); 985 986 if (tmp_rule->ir_ipver != l3 || tmp_rule->ir_proto != l4) 987 continue; 988 989 /* 990 * ir_min_port and ir_max_port are the same if ir_port_range 991 * is false. In this case, if the ir_min|max_port (same) is 992 * outside of the given port range, it is OK. In other cases, 993 * check if min and max port are outside a rule's range. 994 */ 995 if (tmp_rule->ir_max_port < min_port || 996 tmp_rule->ir_min_port > max_port) { 997 continue; 998 } 999 1000 /* 1001 * If l3 is IPv4, the addr passed in is assumed to be 1002 * mapped address. 1003 */ 1004 if (V6_OR_V4_INADDR_ANY(*addr) || 1005 V6_OR_V4_INADDR_ANY(tmp_rule->ir_target_v6) || 1006 IN6_ARE_ADDR_EQUAL(addr, &tmp_rule->ir_target_v6)) { 1007 return (B_TRUE); 1008 } 1009 } 1010 return (B_FALSE); 1011 } 1012 1013 int 1014 ilb_rule_enable(ilb_stack_t *ilbs, zoneid_t zoneid, 1015 const char *rule_name, ilb_rule_t *in_rule) 1016 { 1017 ilb_rule_t *rule; 1018 int err; 1019 1020 ASSERT((in_rule == NULL && rule_name != NULL) || 1021 (in_rule != NULL && rule_name == NULL)); 1022 if ((rule = in_rule) == NULL) { 1023 if ((rule = ilb_find_rule(ilbs, zoneid, rule_name, 1024 &err)) == NULL) { 1025 return (err); 1026 } 1027 } 1028 mutex_enter(&rule->ir_lock); 1029 rule->ir_flags |= ILB_RULE_ENABLED; 1030 mutex_exit(&rule->ir_lock); 1031 1032 /* Only refrele if the rule is passed in. */ 1033 if (in_rule == NULL) 1034 ILB_RULE_REFRELE(rule); 1035 return (0); 1036 } 1037 1038 int 1039 ilb_rule_disable(ilb_stack_t *ilbs, zoneid_t zoneid, 1040 const char *rule_name, ilb_rule_t *in_rule) 1041 { 1042 ilb_rule_t *rule; 1043 int err; 1044 1045 ASSERT((in_rule == NULL && rule_name != NULL) || 1046 (in_rule != NULL && rule_name == NULL)); 1047 if ((rule = in_rule) == NULL) { 1048 if ((rule = ilb_find_rule(ilbs, zoneid, rule_name, 1049 &err)) == NULL) { 1050 return (err); 1051 } 1052 } 1053 mutex_enter(&rule->ir_lock); 1054 rule->ir_flags &= ~ILB_RULE_ENABLED; 1055 mutex_exit(&rule->ir_lock); 1056 1057 /* Only refrele if the rule is passed in. */ 1058 if (in_rule == NULL) 1059 ILB_RULE_REFRELE(rule); 1060 return (0); 1061 } 1062 1063 /* 1064 * XXX We should probably have a walker function to walk all rules. For 1065 * now, just add a simple loop for enable/disable/del. 1066 */ 1067 void 1068 ilb_rule_enable_all(ilb_stack_t *ilbs, zoneid_t zoneid) 1069 { 1070 ilb_rule_t *rule; 1071 1072 mutex_enter(&ilbs->ilbs_g_lock); 1073 for (rule = ilbs->ilbs_rule_head; rule != NULL; rule = rule->ir_next) { 1074 if (rule->ir_zoneid != zoneid) 1075 continue; 1076 /* 1077 * No need to hold the rule as we are holding the global 1078 * lock so it won't go away. Ignore the return value here 1079 * as the rule is provided so the call cannot fail. 1080 */ 1081 (void) ilb_rule_enable(ilbs, zoneid, NULL, rule); 1082 } 1083 mutex_exit(&ilbs->ilbs_g_lock); 1084 } 1085 1086 void 1087 ilb_rule_disable_all(ilb_stack_t *ilbs, zoneid_t zoneid) 1088 { 1089 ilb_rule_t *rule; 1090 1091 mutex_enter(&ilbs->ilbs_g_lock); 1092 for (rule = ilbs->ilbs_rule_head; rule != NULL; 1093 rule = rule->ir_next) { 1094 if (rule->ir_zoneid != zoneid) 1095 continue; 1096 (void) ilb_rule_disable(ilbs, zoneid, NULL, rule); 1097 } 1098 mutex_exit(&ilbs->ilbs_g_lock); 1099 } 1100 1101 void 1102 ilb_rule_del_all(ilb_stack_t *ilbs, zoneid_t zoneid) 1103 { 1104 ilb_rule_t *rule; 1105 ilb_rule_tq_t *arg; 1106 1107 mutex_enter(&ilbs->ilbs_g_lock); 1108 while ((rule = ilbs->ilbs_rule_head) != NULL) { 1109 if (rule->ir_zoneid != zoneid) 1110 continue; 1111 ilb_rule_hash_del(rule); 1112 ilb_rule_g_del(ilbs, rule); 1113 mutex_exit(&ilbs->ilbs_g_lock); 1114 1115 arg = kmem_alloc(sizeof (ilb_rule_tq_t), KM_SLEEP); 1116 arg->ilbs = ilbs; 1117 arg->rule = rule; 1118 (void) taskq_dispatch(ilbs->ilbs_rule_taskq, ilb_rule_del_tq, 1119 arg, TQ_SLEEP); 1120 1121 mutex_enter(&ilbs->ilbs_g_lock); 1122 } 1123 mutex_exit(&ilbs->ilbs_g_lock); 1124 } 1125 1126 /* 1127 * This is just an optimization, so don't grab the global lock. The 1128 * worst case is that we missed a couple packets. 1129 */ 1130 boolean_t 1131 ilb_has_rules(ilb_stack_t *ilbs) 1132 { 1133 return (ilbs->ilbs_rule_head != NULL); 1134 } 1135 1136 1137 static int 1138 ilb_server_toggle(ilb_stack_t *ilbs, zoneid_t zoneid, const char *rule_name, 1139 ilb_rule_t *rule, in6_addr_t *addr, boolean_t enable) 1140 { 1141 ilb_server_t *tmp_server; 1142 int ret; 1143 1144 ASSERT((rule == NULL && rule_name != NULL) || 1145 (rule != NULL && rule_name == NULL)); 1146 1147 if (rule == NULL) { 1148 if ((rule = ilb_find_rule(ilbs, zoneid, rule_name, 1149 &ret)) == NULL) { 1150 return (ret); 1151 } 1152 } 1153 1154 /* Once we get a hold on the rule, no server can be added/deleted. */ 1155 for (tmp_server = rule->ir_servers; tmp_server != NULL; 1156 tmp_server = tmp_server->iser_next) { 1157 if (IN6_ARE_ADDR_EQUAL(&tmp_server->iser_addr_v6, addr)) 1158 break; 1159 } 1160 if (tmp_server == NULL) { 1161 ret = ENOENT; 1162 goto done; 1163 } 1164 1165 if (enable) { 1166 ret = rule->ir_alg->ilb_alg_server_enable(tmp_server, 1167 rule->ir_alg->ilb_alg_data); 1168 if (ret == 0) { 1169 tmp_server->iser_enabled = B_TRUE; 1170 tmp_server->iser_die_time = 0; 1171 } 1172 } else { 1173 ret = rule->ir_alg->ilb_alg_server_disable(tmp_server, 1174 rule->ir_alg->ilb_alg_data); 1175 if (ret == 0) { 1176 tmp_server->iser_enabled = B_FALSE; 1177 if (rule->ir_conn_drain_timeout != 0) { 1178 (void) atomic_swap_64( 1179 (uint64_t *)&tmp_server->iser_die_time, 1180 ddi_get_lbolt64() + SEC_TO_TICK( 1181 rule->ir_conn_drain_timeout)); 1182 } 1183 } 1184 } 1185 1186 done: 1187 if (rule_name != NULL) 1188 ILB_RULE_REFRELE(rule); 1189 return (ret); 1190 } 1191 int 1192 ilb_server_enable(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name, 1193 ilb_rule_t *rule, in6_addr_t *addr) 1194 { 1195 return (ilb_server_toggle(ilbs, zoneid, name, rule, addr, B_TRUE)); 1196 } 1197 1198 int 1199 ilb_server_disable(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name, 1200 ilb_rule_t *rule, in6_addr_t *addr) 1201 { 1202 return (ilb_server_toggle(ilbs, zoneid, name, rule, addr, B_FALSE)); 1203 } 1204 1205 /* 1206 * Add a back end server to a rule. If the address is IPv4, it is assumed 1207 * to be passed in as a mapped address. 1208 */ 1209 int 1210 ilb_server_add(ilb_stack_t *ilbs, ilb_rule_t *rule, ilb_server_info_t *info) 1211 { 1212 ilb_server_t *server; 1213 netstackid_t stackid; 1214 int ret = 0; 1215 in_port_t min_port, max_port; 1216 in_port_t range; 1217 1218 /* Port is passed in network byte order. */ 1219 min_port = ntohs(info->min_port); 1220 max_port = ntohs(info->max_port); 1221 if (min_port > max_port) 1222 return (EINVAL); 1223 1224 /* min_port == 0 means "all ports". Make it so */ 1225 if (min_port == 0) { 1226 min_port = 1; 1227 max_port = 65535; 1228 } 1229 range = max_port - min_port; 1230 1231 mutex_enter(&rule->ir_lock); 1232 /* If someone is already doing server add/del, sleeps and wait. */ 1233 while (rule->ir_flags & ILB_RULE_BUSY) { 1234 if (cv_wait_sig(&rule->ir_cv, &rule->ir_lock) == 0) { 1235 mutex_exit(&rule->ir_lock); 1236 return (EINTR); 1237 } 1238 } 1239 1240 /* 1241 * Set the rule to be busy to make sure that no new packet can 1242 * use this rule. 1243 */ 1244 rule->ir_flags |= ILB_RULE_BUSY; 1245 1246 /* Now wait for all other guys to finish their work. */ 1247 while (rule->ir_refcnt > 2) { 1248 if (cv_wait_sig(&rule->ir_cv, &rule->ir_lock) == 0) { 1249 mutex_exit(&rule->ir_lock); 1250 ret = EINTR; 1251 goto end; 1252 } 1253 } 1254 mutex_exit(&rule->ir_lock); 1255 1256 /* Sanity checks... */ 1257 if ((IN6_IS_ADDR_V4MAPPED(&info->addr) && 1258 rule->ir_ipver != IPPROTO_IP) || 1259 (!IN6_IS_ADDR_V4MAPPED(&info->addr) && 1260 rule->ir_ipver != IPPROTO_IPV6)) { 1261 ret = EINVAL; 1262 goto end; 1263 } 1264 1265 /* 1266 * Check for valid port range. 1267 * 1268 * For DSR, there can be no port shifting. Hence the server 1269 * specification must be the same as the rule's. 1270 * 1271 * For half-NAT/NAT, the range must either be 0 (port collapsing) or 1272 * it must be equal to the same value as the rule port range. 1273 * 1274 */ 1275 if (rule->ir_topo == ILB_TOPO_IMPL_DSR) { 1276 if (rule->ir_max_port != max_port || 1277 rule->ir_min_port != min_port) { 1278 ret = EINVAL; 1279 goto end; 1280 } 1281 } else { 1282 if ((range != rule->ir_max_port - rule->ir_min_port) && 1283 range != 0) { 1284 ret = EINVAL; 1285 goto end; 1286 } 1287 } 1288 1289 /* Check for duplicate. */ 1290 for (server = rule->ir_servers; server != NULL; 1291 server = server->iser_next) { 1292 if (IN6_ARE_ADDR_EQUAL(&server->iser_addr_v6, &info->addr) || 1293 strcasecmp(server->iser_name, info->name) == 0) { 1294 break; 1295 } 1296 } 1297 if (server != NULL) { 1298 ret = EEXIST; 1299 goto end; 1300 } 1301 1302 if ((server = kmem_zalloc(sizeof (ilb_server_t), KM_NOSLEEP)) == NULL) { 1303 ret = ENOMEM; 1304 goto end; 1305 } 1306 1307 (void) memcpy(server->iser_name, info->name, ILB_SERVER_NAMESZ - 1); 1308 (void) inet_ntop(AF_INET6, &info->addr, server->iser_ip_addr, 1309 sizeof (server->iser_ip_addr)); 1310 stackid = (netstackid_t)(uintptr_t)ilbs->ilbs_ksp->ks_private; 1311 server->iser_ksp = ilb_server_kstat_init(stackid, rule, server); 1312 if (server->iser_ksp == NULL) { 1313 kmem_free(server, sizeof (ilb_server_t)); 1314 ret = EINVAL; 1315 goto end; 1316 } 1317 1318 server->iser_stackid = stackid; 1319 server->iser_addr_v6 = info->addr; 1320 server->iser_min_port = min_port; 1321 server->iser_max_port = max_port; 1322 if (min_port != max_port) 1323 server->iser_port_range = B_TRUE; 1324 else 1325 server->iser_port_range = B_FALSE; 1326 1327 /* 1328 * If the rule uses NAT, find/create the NAT source entry to use 1329 * for this server. 1330 */ 1331 if (rule->ir_topo == ILB_TOPO_IMPL_NAT) { 1332 in_port_t port; 1333 1334 /* 1335 * If the server uses a port range, our port allocation 1336 * scheme needs to treat it as a wildcard. Refer to the 1337 * comments in ilb_nat.c about the scheme. 1338 */ 1339 if (server->iser_port_range) 1340 port = 0; 1341 else 1342 port = server->iser_min_port; 1343 1344 if ((ret = ilb_create_nat_src(ilbs, &server->iser_nat_src, 1345 &server->iser_addr_v6, port, &rule->ir_nat_src_start, 1346 num_nat_src_v6(&rule->ir_nat_src_start, 1347 &rule->ir_nat_src_end))) != 0) { 1348 kstat_delete_netstack(server->iser_ksp, stackid); 1349 kmem_free(server, sizeof (ilb_server_t)); 1350 goto end; 1351 } 1352 } 1353 1354 /* 1355 * The iser_lock is only used to protect iser_refcnt. All the other 1356 * fields in ilb_server_t should not change, except for iser_enabled. 1357 * The worst thing that can happen if iser_enabled is messed up is 1358 * that one or two packets may not be load balanced to a server 1359 * correctly. 1360 */ 1361 server->iser_refcnt = 1; 1362 server->iser_enabled = info->flags & ILB_SERVER_ENABLED ? B_TRUE : 1363 B_FALSE; 1364 mutex_init(&server->iser_lock, NULL, MUTEX_DEFAULT, NULL); 1365 cv_init(&server->iser_cv, NULL, CV_DEFAULT, NULL); 1366 1367 /* Let the load balancing algorithm know about the addition. */ 1368 ASSERT(rule->ir_alg != NULL); 1369 if ((ret = rule->ir_alg->ilb_alg_server_add(server, 1370 rule->ir_alg->ilb_alg_data)) != 0) { 1371 kstat_delete_netstack(server->iser_ksp, stackid); 1372 kmem_free(server, sizeof (ilb_server_t)); 1373 goto end; 1374 } 1375 1376 /* 1377 * No need to hold ir_lock since no other thread should manipulate 1378 * the following fields until ILB_RULE_BUSY is cleared. 1379 */ 1380 if (rule->ir_servers == NULL) { 1381 server->iser_next = NULL; 1382 } else { 1383 server->iser_next = rule->ir_servers; 1384 } 1385 rule->ir_servers = server; 1386 ILB_R_KSTAT(rule, num_servers); 1387 1388 end: 1389 mutex_enter(&rule->ir_lock); 1390 rule->ir_flags &= ~ILB_RULE_BUSY; 1391 cv_signal(&rule->ir_cv); 1392 mutex_exit(&rule->ir_lock); 1393 return (ret); 1394 } 1395 1396 /* The routine executed by the delayed rule processing taskq. */ 1397 static void 1398 ilb_server_del_tq(void *arg) 1399 { 1400 ilb_server_t *server = (ilb_server_t *)arg; 1401 1402 mutex_enter(&server->iser_lock); 1403 while (server->iser_refcnt > 1) 1404 cv_wait(&server->iser_cv, &server->iser_lock); 1405 kstat_delete_netstack(server->iser_ksp, server->iser_stackid); 1406 kmem_free(server, sizeof (ilb_server_t)); 1407 } 1408 1409 /* 1410 * Delete a back end server from a rule. If the address is IPv4, it is assumed 1411 * to be passed in as a mapped address. 1412 */ 1413 int 1414 ilb_server_del(ilb_stack_t *ilbs, zoneid_t zoneid, const char *rule_name, 1415 ilb_rule_t *rule, in6_addr_t *addr) 1416 { 1417 ilb_server_t *server; 1418 ilb_server_t *prev_server; 1419 int ret = 0; 1420 1421 ASSERT((rule == NULL && rule_name != NULL) || 1422 (rule != NULL && rule_name == NULL)); 1423 if (rule == NULL) { 1424 if ((rule = ilb_find_rule(ilbs, zoneid, rule_name, 1425 &ret)) == NULL) { 1426 return (ret); 1427 } 1428 } 1429 1430 mutex_enter(&rule->ir_lock); 1431 /* If someone is already doing server add/del, sleeps and wait. */ 1432 while (rule->ir_flags & ILB_RULE_BUSY) { 1433 if (cv_wait_sig(&rule->ir_cv, &rule->ir_lock) == 0) { 1434 if (rule_name != NULL) { 1435 if (--rule->ir_refcnt <= 2) 1436 cv_signal(&rule->ir_cv); 1437 } 1438 mutex_exit(&rule->ir_lock); 1439 return (EINTR); 1440 } 1441 } 1442 /* 1443 * Set the rule to be busy to make sure that no new packet can 1444 * use this rule. 1445 */ 1446 rule->ir_flags |= ILB_RULE_BUSY; 1447 1448 /* Now wait for all other guys to finish their work. */ 1449 while (rule->ir_refcnt > 2) { 1450 if (cv_wait_sig(&rule->ir_cv, &rule->ir_lock) == 0) { 1451 mutex_exit(&rule->ir_lock); 1452 ret = EINTR; 1453 goto end; 1454 } 1455 } 1456 mutex_exit(&rule->ir_lock); 1457 1458 prev_server = NULL; 1459 for (server = rule->ir_servers; server != NULL; 1460 prev_server = server, server = server->iser_next) { 1461 if (IN6_ARE_ADDR_EQUAL(&server->iser_addr_v6, addr)) 1462 break; 1463 } 1464 if (server == NULL) { 1465 ret = ENOENT; 1466 goto end; 1467 } 1468 1469 /* 1470 * Let the load balancing algorithm know about the removal. 1471 * The algorithm may disallow the removal... 1472 */ 1473 if ((ret = rule->ir_alg->ilb_alg_server_del(server, 1474 rule->ir_alg->ilb_alg_data)) != 0) { 1475 goto end; 1476 } 1477 1478 if (prev_server == NULL) 1479 rule->ir_servers = server->iser_next; 1480 else 1481 prev_server->iser_next = server->iser_next; 1482 1483 ILB_R_KSTAT_UPDATE(rule, num_servers, -1); 1484 1485 /* 1486 * Mark the server as disabled so that if there is any sticky cache 1487 * using this server around, it won't be used. 1488 */ 1489 server->iser_enabled = B_FALSE; 1490 1491 mutex_enter(&server->iser_lock); 1492 1493 /* 1494 * De-allocate the NAT source array. The indiviual ilb_nat_src_entry_t 1495 * may not go away if there is still a conn using it. The NAT source 1496 * timer will do the garbage collection. 1497 */ 1498 ilb_destroy_nat_src(&server->iser_nat_src); 1499 1500 /* If there is a hard limit on when a server should die, set it. */ 1501 if (rule->ir_conn_drain_timeout != 0) { 1502 (void) atomic_swap_64((uint64_t *)&server->iser_die_time, 1503 ddi_get_lbolt64() + 1504 SEC_TO_TICK(rule->ir_conn_drain_timeout)); 1505 } 1506 1507 if (server->iser_refcnt > 1) { 1508 (void) taskq_dispatch(ilbs->ilbs_rule_taskq, ilb_server_del_tq, 1509 server, TQ_SLEEP); 1510 mutex_exit(&server->iser_lock); 1511 } else { 1512 kstat_delete_netstack(server->iser_ksp, server->iser_stackid); 1513 kmem_free(server, sizeof (ilb_server_t)); 1514 } 1515 1516 end: 1517 mutex_enter(&rule->ir_lock); 1518 rule->ir_flags &= ~ILB_RULE_BUSY; 1519 if (rule_name != NULL) 1520 rule->ir_refcnt--; 1521 cv_signal(&rule->ir_cv); 1522 mutex_exit(&rule->ir_lock); 1523 return (ret); 1524 } 1525 1526 /* 1527 * First check if the destination of the ICMP message matches a VIP of 1528 * a rule. If it does not, just return ILB_PASSED. 1529 * 1530 * If the destination matches a VIP: 1531 * 1532 * For ICMP_ECHO_REQUEST, generate a response on behalf of the back end 1533 * server. 1534 * 1535 * For ICMP_DEST_UNREACHABLE fragmentation needed, check inside the payload 1536 * and see which back end server we should send this message to. And we 1537 * need to do NAT on both the payload message and the outside IP packet. 1538 * 1539 * For other ICMP messages, drop them. 1540 */ 1541 /* ARGSUSED */ 1542 static int 1543 ilb_icmp_v4(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, ipha_t *ipha, 1544 icmph_t *icmph, ipaddr_t *lb_dst) 1545 { 1546 ipaddr_t vip; 1547 ilb_rule_t *rule; 1548 in6_addr_t addr6; 1549 1550 if (!ilb_rule_match_vip_v4(ilbs, ipha->ipha_dst, &rule)) 1551 return (ILB_PASSED); 1552 1553 1554 if ((uint8_t *)icmph + sizeof (icmph_t) > mp->b_wptr) { 1555 ILB_R_KSTAT(rule, icmp_dropped); 1556 ILB_RULE_REFRELE(rule); 1557 return (ILB_DROPPED); 1558 } 1559 1560 switch (icmph->icmph_type) { 1561 case ICMP_ECHO_REQUEST: 1562 ILB_R_KSTAT(rule, icmp_echo_processed); 1563 ILB_RULE_REFRELE(rule); 1564 1565 icmph->icmph_type = ICMP_ECHO_REPLY; 1566 icmph->icmph_checksum = 0; 1567 icmph->icmph_checksum = IP_CSUM(mp, IPH_HDR_LENGTH(ipha), 0); 1568 ipha->ipha_ttl = 1569 ilbs->ilbs_netstack->netstack_ip->ips_ip_def_ttl; 1570 *lb_dst = ipha->ipha_src; 1571 vip = ipha->ipha_dst; 1572 ipha->ipha_dst = ipha->ipha_src; 1573 ipha->ipha_src = vip; 1574 return (ILB_BALANCED); 1575 case ICMP_DEST_UNREACHABLE: { 1576 int ret; 1577 1578 if (icmph->icmph_code != ICMP_FRAGMENTATION_NEEDED) { 1579 ILB_R_KSTAT(rule, icmp_dropped); 1580 ILB_RULE_REFRELE(rule); 1581 return (ILB_DROPPED); 1582 } 1583 if (ilb_check_icmp_conn(ilbs, mp, IPPROTO_IP, ipha, icmph, 1584 &addr6)) { 1585 ILB_R_KSTAT(rule, icmp_2big_processed); 1586 ret = ILB_BALANCED; 1587 } else { 1588 ILB_R_KSTAT(rule, icmp_2big_dropped); 1589 ret = ILB_DROPPED; 1590 } 1591 ILB_RULE_REFRELE(rule); 1592 IN6_V4MAPPED_TO_IPADDR(&addr6, *lb_dst); 1593 return (ret); 1594 } 1595 default: 1596 ILB_R_KSTAT(rule, icmp_dropped); 1597 ILB_RULE_REFRELE(rule); 1598 return (ILB_DROPPED); 1599 } 1600 } 1601 1602 /* ARGSUSED */ 1603 static int 1604 ilb_icmp_v6(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, ip6_t *ip6h, 1605 icmp6_t *icmp6, in6_addr_t *lb_dst) 1606 { 1607 ilb_rule_t *rule; 1608 1609 if (!ilb_rule_match_vip_v6(ilbs, &ip6h->ip6_dst, &rule)) 1610 return (ILB_PASSED); 1611 1612 if ((uint8_t *)icmp6 + sizeof (icmp6_t) > mp->b_wptr) { 1613 ILB_R_KSTAT(rule, icmp_dropped); 1614 ILB_RULE_REFRELE(rule); 1615 return (ILB_DROPPED); 1616 } 1617 1618 switch (icmp6->icmp6_type) { 1619 case ICMP6_ECHO_REQUEST: { 1620 int hdr_len; 1621 1622 ILB_R_KSTAT(rule, icmp_echo_processed); 1623 ILB_RULE_REFRELE(rule); 1624 1625 icmp6->icmp6_type = ICMP6_ECHO_REPLY; 1626 icmp6->icmp6_cksum = ip6h->ip6_plen; 1627 hdr_len = (char *)icmp6 - (char *)ip6h; 1628 icmp6->icmp6_cksum = IP_CSUM(mp, hdr_len, 1629 ilb_pseudo_sum_v6(ip6h, IPPROTO_ICMPV6)); 1630 ip6h->ip6_vcf &= ~IPV6_FLOWINFO_FLOWLABEL; 1631 ip6h->ip6_hops = 1632 ilbs->ilbs_netstack->netstack_ip->ips_ipv6_def_hops; 1633 *lb_dst = ip6h->ip6_src; 1634 ip6h->ip6_src = ip6h->ip6_dst; 1635 ip6h->ip6_dst = *lb_dst; 1636 return (ILB_BALANCED); 1637 } 1638 case ICMP6_PACKET_TOO_BIG: { 1639 int ret; 1640 1641 if (ilb_check_icmp_conn(ilbs, mp, IPPROTO_IPV6, ip6h, icmp6, 1642 lb_dst)) { 1643 ILB_R_KSTAT(rule, icmp_2big_processed); 1644 ret = ILB_BALANCED; 1645 } else { 1646 ILB_R_KSTAT(rule, icmp_2big_dropped); 1647 ret = ILB_DROPPED; 1648 } 1649 ILB_RULE_REFRELE(rule); 1650 return (ret); 1651 } 1652 default: 1653 ILB_R_KSTAT(rule, icmp_dropped); 1654 ILB_RULE_REFRELE(rule); 1655 return (ILB_DROPPED); 1656 } 1657 } 1658 1659 /* 1660 * Common routine to check an incoming packet and decide what to do with it. 1661 * called by ilb_check_v4|v6(). 1662 */ 1663 static int 1664 ilb_check(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, in6_addr_t *src, 1665 in6_addr_t *dst, int l3, int l4, void *iph, uint8_t *tph, uint32_t pkt_len, 1666 in6_addr_t *lb_dst) 1667 { 1668 in_port_t sport, dport; 1669 tcpha_t *tcph; 1670 udpha_t *udph; 1671 ilb_rule_t *rule; 1672 ilb_server_t *server; 1673 boolean_t balanced; 1674 struct ilb_sticky_s *s = NULL; 1675 int ret; 1676 uint32_t ip_sum, tp_sum; 1677 ilb_nat_info_t info; 1678 uint16_t nat_src_idx; 1679 boolean_t busy; 1680 1681 /* 1682 * We don't really need to switch here since both protocols's 1683 * ports are at the same offset. Just prepare for future protocol 1684 * specific processing. 1685 */ 1686 switch (l4) { 1687 case IPPROTO_TCP: 1688 if (tph + TCP_MIN_HEADER_LENGTH > mp->b_wptr) 1689 return (ILB_DROPPED); 1690 tcph = (tcpha_t *)tph; 1691 sport = tcph->tha_lport; 1692 dport = tcph->tha_fport; 1693 break; 1694 case IPPROTO_UDP: 1695 if (tph + sizeof (udpha_t) > mp->b_wptr) 1696 return (ILB_DROPPED); 1697 udph = (udpha_t *)tph; 1698 sport = udph->uha_src_port; 1699 dport = udph->uha_dst_port; 1700 break; 1701 default: 1702 return (ILB_PASSED); 1703 } 1704 1705 /* Fast path, there is an existing conn. */ 1706 if (ilb_check_conn(ilbs, l3, iph, l4, tph, src, dst, sport, dport, 1707 pkt_len, lb_dst)) { 1708 return (ILB_BALANCED); 1709 } 1710 1711 /* 1712 * If there is no existing connection for the incoming packet, check 1713 * to see if the packet matches a rule. If not, just let IP decide 1714 * what to do with it. 1715 * 1716 * Note: a reply from back end server should not match a rule. A 1717 * reply should match one existing conn. 1718 */ 1719 rule = ilb_rule_hash(ilbs, l3, l4, dst, dport, ill->ill_zoneid, 1720 pkt_len, &busy); 1721 if (rule == NULL) { 1722 /* If the rule is busy, just drop the packet. */ 1723 if (busy) 1724 return (ILB_DROPPED); 1725 else 1726 return (ILB_PASSED); 1727 } 1728 1729 /* 1730 * The packet matches a rule, use the rule load balance algorithm 1731 * to find a server. 1732 */ 1733 balanced = rule->ir_alg->ilb_alg_lb(src, sport, dst, dport, 1734 rule->ir_alg->ilb_alg_data, &server); 1735 /* 1736 * This can only happen if there is no server in a rule or all 1737 * the servers are currently disabled. 1738 */ 1739 if (!balanced) 1740 goto no_server; 1741 1742 /* 1743 * If the rule is sticky enabled, we need to check the sticky table. 1744 * If there is a sticky entry for the client, use the previous server 1745 * instead of the one found above (note that both can be the same). 1746 * If there is no entry for that client, add an entry to the sticky 1747 * table. Both the find and add are done in ilb_sticky_find_add() 1748 * to avoid checking for duplicate when adding an entry. 1749 */ 1750 if (rule->ir_flags & ILB_RULE_STICKY) { 1751 in6_addr_t addr; 1752 1753 V6_MASK_COPY(*src, rule->ir_sticky_mask, addr); 1754 if ((server = ilb_sticky_find_add(ilbs, rule, &addr, server, 1755 &s, &nat_src_idx)) == NULL) { 1756 ILB_R_KSTAT(rule, nomem_pkt_dropped); 1757 ILB_R_KSTAT_UPDATE(rule, nomem_bytes_dropped, pkt_len); 1758 goto no_server; 1759 } 1760 } 1761 1762 /* 1763 * We are holding a reference on the rule, so the server 1764 * cannot go away. 1765 */ 1766 *lb_dst = server->iser_addr_v6; 1767 ILB_S_KSTAT(server, pkt_processed); 1768 ILB_S_KSTAT_UPDATE(server, bytes_processed, pkt_len); 1769 1770 switch (rule->ir_topo) { 1771 case ILB_TOPO_IMPL_NAT: { 1772 ilb_nat_src_entry_t *src_ent; 1773 uint16_t *src_idx; 1774 1775 /* 1776 * We create a cache even if it is not a SYN segment. 1777 * The server should return a RST. When we see the 1778 * RST, we will destroy this cache. But by having 1779 * a cache, we know how to NAT the returned RST. 1780 */ 1781 info.vip = *dst; 1782 info.dport = dport; 1783 info.src = *src; 1784 info.sport = sport; 1785 1786 /* If stickiness is enabled, use the same source address */ 1787 if (s != NULL) 1788 src_idx = &nat_src_idx; 1789 else 1790 src_idx = NULL; 1791 1792 if ((src_ent = ilb_alloc_nat_addr(server->iser_nat_src, 1793 &info.nat_src, &info.nat_sport, src_idx)) == NULL) { 1794 if (s != NULL) 1795 ilb_sticky_refrele(s); 1796 ILB_R_KSTAT(rule, pkt_dropped); 1797 ILB_R_KSTAT_UPDATE(rule, bytes_dropped, pkt_len); 1798 ILB_R_KSTAT(rule, noport_pkt_dropped); 1799 ILB_R_KSTAT_UPDATE(rule, noport_bytes_dropped, pkt_len); 1800 ret = ILB_DROPPED; 1801 break; 1802 } 1803 info.src_ent = src_ent; 1804 info.nat_dst = server->iser_addr_v6; 1805 if (rule->ir_port_range && server->iser_port_range) { 1806 info.nat_dport = htons(ntohs(dport) - 1807 rule->ir_min_port + server->iser_min_port); 1808 } else { 1809 info.nat_dport = htons(server->iser_min_port); 1810 } 1811 1812 /* 1813 * If ilb_conn_add() fails, it will release the reference on 1814 * sticky info and de-allocate the NAT source port allocated 1815 * above. 1816 */ 1817 if (ilb_conn_add(ilbs, rule, server, src, sport, dst, 1818 dport, &info, &ip_sum, &tp_sum, s) != 0) { 1819 ILB_R_KSTAT(rule, pkt_dropped); 1820 ILB_R_KSTAT_UPDATE(rule, bytes_dropped, pkt_len); 1821 ILB_R_KSTAT(rule, nomem_pkt_dropped); 1822 ILB_R_KSTAT_UPDATE(rule, nomem_bytes_dropped, pkt_len); 1823 ret = ILB_DROPPED; 1824 break; 1825 } 1826 ilb_full_nat(l3, iph, l4, tph, &info, ip_sum, tp_sum, B_TRUE); 1827 ret = ILB_BALANCED; 1828 break; 1829 } 1830 case ILB_TOPO_IMPL_HALF_NAT: 1831 info.vip = *dst; 1832 info.nat_dst = server->iser_addr_v6; 1833 info.dport = dport; 1834 if (rule->ir_port_range && server->iser_port_range) { 1835 info.nat_dport = htons(ntohs(dport) - 1836 rule->ir_min_port + server->iser_min_port); 1837 } else { 1838 info.nat_dport = htons(server->iser_min_port); 1839 } 1840 1841 if (ilb_conn_add(ilbs, rule, server, src, sport, dst, 1842 dport, &info, &ip_sum, &tp_sum, s) != 0) { 1843 ILB_R_KSTAT(rule, pkt_dropped); 1844 ILB_R_KSTAT_UPDATE(rule, bytes_dropped, pkt_len); 1845 ILB_R_KSTAT(rule, nomem_pkt_dropped); 1846 ILB_R_KSTAT_UPDATE(rule, nomem_bytes_dropped, pkt_len); 1847 ret = ILB_DROPPED; 1848 break; 1849 } 1850 ilb_half_nat(l3, iph, l4, tph, &info, ip_sum, tp_sum, B_TRUE); 1851 1852 ret = ILB_BALANCED; 1853 break; 1854 case ILB_TOPO_IMPL_DSR: 1855 /* 1856 * By decrementing the sticky refcnt, the period of 1857 * stickiness (life time of ilb_sticky_t) will be 1858 * from now to (now + default expiry time). 1859 */ 1860 if (s != NULL) 1861 ilb_sticky_refrele(s); 1862 ret = ILB_BALANCED; 1863 break; 1864 default: 1865 cmn_err(CE_PANIC, "data corruption unknown topology: %p", 1866 (void *) rule); 1867 break; 1868 } 1869 ILB_RULE_REFRELE(rule); 1870 return (ret); 1871 1872 no_server: 1873 /* This can only happen if there is no server available. */ 1874 ILB_R_KSTAT(rule, pkt_dropped); 1875 ILB_R_KSTAT_UPDATE(rule, bytes_dropped, pkt_len); 1876 ILB_RULE_REFRELE(rule); 1877 return (ILB_DROPPED); 1878 } 1879 1880 int 1881 ilb_check_v4(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, ipha_t *ipha, int l4, 1882 uint8_t *tph, ipaddr_t *lb_dst) 1883 { 1884 in6_addr_t v6_src, v6_dst, v6_lb_dst; 1885 int ret; 1886 1887 ASSERT(DB_REF(mp) == 1); 1888 1889 if (l4 == IPPROTO_ICMP) { 1890 return (ilb_icmp_v4(ilbs, ill, mp, ipha, (icmph_t *)tph, 1891 lb_dst)); 1892 } 1893 1894 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &v6_src); 1895 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &v6_dst); 1896 ret = ilb_check(ilbs, ill, mp, &v6_src, &v6_dst, IPPROTO_IP, l4, ipha, 1897 tph, ntohs(ipha->ipha_length), &v6_lb_dst); 1898 if (ret == ILB_BALANCED) 1899 IN6_V4MAPPED_TO_IPADDR(&v6_lb_dst, *lb_dst); 1900 return (ret); 1901 } 1902 1903 int 1904 ilb_check_v6(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, ip6_t *ip6h, int l4, 1905 uint8_t *tph, in6_addr_t *lb_dst) 1906 { 1907 uint32_t pkt_len; 1908 1909 ASSERT(DB_REF(mp) == 1); 1910 1911 if (l4 == IPPROTO_ICMPV6) { 1912 return (ilb_icmp_v6(ilbs, ill, mp, ip6h, (icmp6_t *)tph, 1913 lb_dst)); 1914 } 1915 1916 pkt_len = ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN; 1917 return (ilb_check(ilbs, ill, mp, &ip6h->ip6_src, &ip6h->ip6_dst, 1918 IPPROTO_IPV6, l4, ip6h, tph, pkt_len, lb_dst)); 1919 } 1920 1921 void 1922 ilb_get_num_rules(ilb_stack_t *ilbs, zoneid_t zoneid, uint32_t *num_rules) 1923 { 1924 ilb_rule_t *tmp_rule; 1925 1926 mutex_enter(&ilbs->ilbs_g_lock); 1927 *num_rules = 0; 1928 for (tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL; 1929 tmp_rule = tmp_rule->ir_next) { 1930 if (tmp_rule->ir_zoneid == zoneid) 1931 *num_rules += 1; 1932 } 1933 mutex_exit(&ilbs->ilbs_g_lock); 1934 } 1935 1936 int 1937 ilb_get_num_servers(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name, 1938 uint32_t *num_servers) 1939 { 1940 ilb_rule_t *rule; 1941 int err; 1942 1943 if ((rule = ilb_find_rule(ilbs, zoneid, name, &err)) == NULL) 1944 return (err); 1945 *num_servers = rule->ir_kstat.num_servers.value.ui64; 1946 ILB_RULE_REFRELE(rule); 1947 return (0); 1948 } 1949 1950 int 1951 ilb_get_servers(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name, 1952 ilb_server_info_t *servers, uint32_t *num_servers) 1953 { 1954 ilb_rule_t *rule; 1955 ilb_server_t *server; 1956 size_t cnt; 1957 int err; 1958 1959 if ((rule = ilb_find_rule(ilbs, zoneid, name, &err)) == NULL) 1960 return (err); 1961 for (server = rule->ir_servers, cnt = *num_servers; 1962 server != NULL && cnt > 0; 1963 server = server->iser_next, cnt--, servers++) { 1964 (void) memcpy(servers->name, server->iser_name, 1965 ILB_SERVER_NAMESZ); 1966 servers->addr = server->iser_addr_v6; 1967 servers->min_port = htons(server->iser_min_port); 1968 servers->max_port = htons(server->iser_max_port); 1969 servers->flags = server->iser_enabled ? ILB_SERVER_ENABLED : 0; 1970 servers->err = 0; 1971 } 1972 ILB_RULE_REFRELE(rule); 1973 *num_servers -= cnt; 1974 1975 return (0); 1976 } 1977 1978 void 1979 ilb_get_rulenames(ilb_stack_t *ilbs, zoneid_t zoneid, uint32_t *num_names, 1980 char *buf) 1981 { 1982 ilb_rule_t *tmp_rule; 1983 int cnt; 1984 1985 if (*num_names == 0) 1986 return; 1987 1988 mutex_enter(&ilbs->ilbs_g_lock); 1989 for (cnt = 0, tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL; 1990 tmp_rule = tmp_rule->ir_next) { 1991 if (tmp_rule->ir_zoneid != zoneid) 1992 continue; 1993 1994 (void) memcpy(buf, tmp_rule->ir_name, ILB_RULE_NAMESZ); 1995 buf += ILB_RULE_NAMESZ; 1996 if (++cnt == *num_names) 1997 break; 1998 } 1999 mutex_exit(&ilbs->ilbs_g_lock); 2000 *num_names = cnt; 2001 } 2002 2003 int 2004 ilb_rule_list(ilb_stack_t *ilbs, zoneid_t zoneid, ilb_rule_cmd_t *cmd) 2005 { 2006 ilb_rule_t *rule; 2007 int err; 2008 2009 if ((rule = ilb_find_rule(ilbs, zoneid, cmd->name, &err)) == NULL) { 2010 return (err); 2011 } 2012 2013 /* 2014 * Except the enabled flags, none of the following will change 2015 * in the life time of a rule. So we don't hold the mutex when 2016 * reading them. The worst is to report a wrong enabled flags. 2017 */ 2018 cmd->ip_ver = rule->ir_ipver; 2019 cmd->proto = rule->ir_proto; 2020 cmd->min_port = htons(rule->ir_min_port); 2021 cmd->max_port = htons(rule->ir_max_port); 2022 2023 cmd->vip = rule->ir_target_v6; 2024 cmd->algo = rule->ir_alg_type; 2025 cmd->topo = rule->ir_topo; 2026 2027 cmd->nat_src_start = rule->ir_nat_src_start; 2028 cmd->nat_src_end = rule->ir_nat_src_end; 2029 2030 cmd->conn_drain_timeout = rule->ir_conn_drain_timeout; 2031 cmd->nat_expiry = rule->ir_nat_expiry; 2032 cmd->sticky_expiry = rule->ir_sticky_expiry; 2033 2034 cmd->flags = 0; 2035 if (rule->ir_flags & ILB_RULE_ENABLED) 2036 cmd->flags |= ILB_RULE_ENABLED; 2037 if (rule->ir_flags & ILB_RULE_STICKY) { 2038 cmd->flags |= ILB_RULE_STICKY; 2039 cmd->sticky_mask = rule->ir_sticky_mask; 2040 } 2041 2042 ILB_RULE_REFRELE(rule); 2043 return (0); 2044 } 2045 2046 static void * 2047 ilb_stack_init(netstackid_t stackid, netstack_t *ns) 2048 { 2049 ilb_stack_t *ilbs; 2050 char tq_name[TASKQ_NAMELEN]; 2051 2052 ilbs = kmem_alloc(sizeof (ilb_stack_t), KM_SLEEP); 2053 ilbs->ilbs_netstack = ns; 2054 2055 ilbs->ilbs_rule_head = NULL; 2056 ilbs->ilbs_g_hash = NULL; 2057 mutex_init(&ilbs->ilbs_g_lock, NULL, MUTEX_DEFAULT, NULL); 2058 2059 ilbs->ilbs_kstat = kmem_alloc(sizeof (ilb_g_kstat_t), KM_SLEEP); 2060 if ((ilbs->ilbs_ksp = ilb_kstat_g_init(stackid, ilbs)) == NULL) { 2061 kmem_free(ilbs, sizeof (ilb_stack_t)); 2062 return (NULL); 2063 } 2064 2065 /* 2066 * ilbs_conn/sticky_hash related info is initialized in 2067 * ilb_conn/sticky_hash_init(). 2068 */ 2069 ilbs->ilbs_conn_taskq = NULL; 2070 ilbs->ilbs_rule_hash_size = ilb_rule_hash_size; 2071 ilbs->ilbs_conn_hash_size = ilb_conn_hash_size; 2072 ilbs->ilbs_c2s_conn_hash = NULL; 2073 ilbs->ilbs_s2c_conn_hash = NULL; 2074 ilbs->ilbs_conn_timer_list = NULL; 2075 2076 ilbs->ilbs_sticky_hash = NULL; 2077 ilbs->ilbs_sticky_hash_size = ilb_sticky_hash_size; 2078 ilbs->ilbs_sticky_timer_list = NULL; 2079 ilbs->ilbs_sticky_taskq = NULL; 2080 2081 /* The allocation is done later when there is a rule using NAT mode. */ 2082 ilbs->ilbs_nat_src = NULL; 2083 ilbs->ilbs_nat_src_hash_size = ilb_nat_src_hash_size; 2084 mutex_init(&ilbs->ilbs_nat_src_lock, NULL, MUTEX_DEFAULT, NULL); 2085 ilbs->ilbs_nat_src_tid = 0; 2086 2087 /* For listing the conn hash table */ 2088 mutex_init(&ilbs->ilbs_conn_list_lock, NULL, MUTEX_DEFAULT, NULL); 2089 cv_init(&ilbs->ilbs_conn_list_cv, NULL, CV_DEFAULT, NULL); 2090 ilbs->ilbs_conn_list_busy = B_FALSE; 2091 ilbs->ilbs_conn_list_cur = 0; 2092 ilbs->ilbs_conn_list_connp = NULL; 2093 2094 /* For listing the sticky hash table */ 2095 mutex_init(&ilbs->ilbs_sticky_list_lock, NULL, MUTEX_DEFAULT, NULL); 2096 cv_init(&ilbs->ilbs_sticky_list_cv, NULL, CV_DEFAULT, NULL); 2097 ilbs->ilbs_sticky_list_busy = B_FALSE; 2098 ilbs->ilbs_sticky_list_cur = 0; 2099 ilbs->ilbs_sticky_list_curp = NULL; 2100 2101 (void) snprintf(tq_name, sizeof (tq_name), "ilb_rule_taskq_%p", 2102 (void *)ns); 2103 ilbs->ilbs_rule_taskq = taskq_create(tq_name, ILB_RULE_TASKQ_NUM_THR, 2104 minclsyspri, 1, INT_MAX, TASKQ_PREPOPULATE|TASKQ_DYNAMIC); 2105 2106 return (ilbs); 2107 } 2108 2109 /* ARGSUSED */ 2110 static void 2111 ilb_stack_shutdown(netstackid_t stackid, void *arg) 2112 { 2113 ilb_stack_t *ilbs = (ilb_stack_t *)arg; 2114 ilb_rule_t *tmp_rule; 2115 2116 ilb_sticky_hash_fini(ilbs); 2117 ilb_conn_hash_fini(ilbs); 2118 mutex_enter(&ilbs->ilbs_g_lock); 2119 while ((tmp_rule = ilbs->ilbs_rule_head) != NULL) { 2120 ilb_rule_hash_del(tmp_rule); 2121 ilb_rule_g_del(ilbs, tmp_rule); 2122 mutex_exit(&ilbs->ilbs_g_lock); 2123 ilb_rule_del_common(ilbs, tmp_rule); 2124 mutex_enter(&ilbs->ilbs_g_lock); 2125 } 2126 mutex_exit(&ilbs->ilbs_g_lock); 2127 if (ilbs->ilbs_nat_src != NULL) 2128 ilb_nat_src_fini(ilbs); 2129 } 2130 2131 static void 2132 ilb_stack_fini(netstackid_t stackid, void * arg) 2133 { 2134 ilb_stack_t *ilbs = (ilb_stack_t *)arg; 2135 2136 ilb_rule_hash_fini(ilbs); 2137 taskq_destroy(ilbs->ilbs_rule_taskq); 2138 ilb_kstat_g_fini(stackid, ilbs); 2139 kmem_free(ilbs->ilbs_kstat, sizeof (ilb_g_kstat_t)); 2140 kmem_free(ilbs, sizeof (ilb_stack_t)); 2141 } 2142 2143 void 2144 ilb_ddi_g_init(void) 2145 { 2146 netstack_register(NS_ILB, ilb_stack_init, ilb_stack_shutdown, 2147 ilb_stack_fini); 2148 } 2149 2150 void 2151 ilb_ddi_g_destroy(void) 2152 { 2153 netstack_unregister(NS_ILB); 2154 ilb_conn_cache_fini(); 2155 ilb_sticky_cache_fini(); 2156 } 2157