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