dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * CDDL HEADER START
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The contents of this file are subject to the terms of the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Common Development and Distribution License (the "License").
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * You may not use this file except in compliance with the License.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * or http://www.opensolaris.org/os/licensing.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * See the License for the specific language governing permissions
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * and limitations under the License.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * When distributing Covered Code, include this CDDL HEADER in each
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If applicable, add the following below this CDDL HEADER, with the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * fields enclosed by brackets "[]" replaced with your own identifying
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * information: Portions Copyright [yyyy] [name of copyright owner]
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * CDDL HEADER END
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Use is subject to license terms.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek#include <sys/sysmacros.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/kmem.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/ksynch.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/systm.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/socket.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/disp.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/taskq.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/cmn_err.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/strsun.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/sdt.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <sys/atomic.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <netinet/in.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <inet/ip.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <inet/ip6.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <inet/tcp.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <inet/udp_impl.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <inet/kstatcom.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include <inet/ilb_ip.h>
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include "ilb_alg.h"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include "ilb_nat.h"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#include "ilb_conn.h"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* ILB kmem cache flag */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint ilb_kmem_flags = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The default size for the different hash tables. Global for all stacks.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * But each stack has its own table, just that their sizes are the same.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic size_t ilb_rule_hash_size = 2048;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic size_t ilb_conn_hash_size = 262144;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic size_t ilb_sticky_hash_size = 262144;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* This should be a prime number. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic size_t ilb_nat_src_hash_size = 97;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Default NAT cache entry expiry time. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic uint32_t ilb_conn_tcp_expiry = 120;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic uint32_t ilb_conn_udp_expiry = 60;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Default sticky entry expiry time. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic uint32_t ilb_sticky_expiry = 60;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* addr is assumed to be a uint8_t * to an ipaddr_t. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#define ILB_RULE_HASH(addr, hash_size) \
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ((*((addr) + 3) * 29791 + *((addr) + 2) * 961 + *((addr) + 1) * 31 + \
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *(addr)) & ((hash_size) - 1))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Note on ILB delayed processing
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * To avoid in line removal on some of the data structures, such as rules,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * servers and ilb_conn_hash entries, ILB delays such processing to a taskq.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * There are three types of ILB taskq:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 1. rule handling: created at stack initialialization time, ilb_stack_init()
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 2. conn hash handling: created at conn hash initialization time,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ilb_conn_hash_init()
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 3. sticky hash handling: created at sticky hash initialization time,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ilb_sticky_hash_init()
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The rule taskq is for processing rule and server removal. When a user
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * land rule/server removal request comes in, a taskq is dispatched after
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * removing the rule/server from all related hashes. This taskq will wait
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * until all references to the rule/server are gone before removing it.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * So the user land thread requesting the removal does not need to wait
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * for the removal completion.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The conn hash/sticky hash taskq is for processing ilb_conn_hash and
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ilb_sticky_hash table entry removal. There are ilb_conn_timer_size timers
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * and ilb_sticky_timer_size timers running for ilb_conn_hash and
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ilb_sticky_hash cleanup respectively. Each timer is responsible for one
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * portion (same size) of the hash table. When a timer fires, it dispatches
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * a conn hash taskq to clean up its portion of the table. This avoids in
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * line processing of the removal.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * There is another delayed processing, the clean up of NAT source address
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * table. We just use the timer to directly handle it instead of using
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * a taskq. The reason is that the table is small so it is OK to use the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * timer.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* ILB rule taskq constants. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#define ILB_RULE_TASKQ_NUM_THR 20
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Argument passed to ILB rule taskq routines. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misratypedef struct {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_stack_t *ilbs;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra} ilb_rule_tq_t;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* kstat handling routines. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic kstat_t *ilb_kstat_g_init(netstackid_t, ilb_stack_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_kstat_g_fini(netstackid_t, ilb_stack_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic kstat_t *ilb_rule_kstat_init(netstackid_t, ilb_rule_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic kstat_t *ilb_server_kstat_init(netstackid_t, ilb_rule_t *,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Rule hash handling routines. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_rule_hash_init(ilb_stack_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_rule_hash_fini(ilb_stack_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_rule_hash_add(ilb_stack_t *, ilb_rule_t *, const in6_addr_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_rule_hash_del(ilb_rule_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic ilb_rule_t *ilb_rule_hash(ilb_stack_t *, int, int, in6_addr_t *,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in_port_t, zoneid_t, uint32_t, boolean_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_rule_g_add(ilb_stack_t *, ilb_rule_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_rule_g_del(ilb_stack_t *, ilb_rule_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_del_rule_common(ilb_stack_t *, ilb_rule_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic ilb_rule_t *ilb_find_rule_locked(ilb_stack_t *, zoneid_t, const char *,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic boolean_t ilb_match_rule(ilb_stack_t *, zoneid_t, const char *, int,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int, in_port_t, in_port_t, const in6_addr_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Back end server handling routines. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_server_free(ilb_server_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Network stack handling routines. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void *ilb_stack_init(netstackid_t, netstack_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_stack_shutdown(netstackid_t, void *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_stack_fini(netstackid_t, void *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Sticky connection handling routines. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_rule_sticky_init(ilb_rule_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void ilb_rule_sticky_fini(ilb_rule_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Handy macro to check for unspecified address. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#define IS_ADDR_UNSPEC(addr) \
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (IN6_IS_ADDR_V4MAPPED(addr) ? IN6_IS_ADDR_V4MAPPED_ANY(addr) : \
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_UNSPECIFIED(addr))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Global kstat instance counter. When a rule is created, its kstat instance
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * number is assigned by ilb_kstat_instance and ilb_kstat_instance is
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * incremented.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic uint_t ilb_kstat_instance = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The ILB global kstat has name ILB_G_KS_NAME and class name ILB_G_KS_CNAME.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * A rule's kstat has ILB_RULE_KS_CNAME class name.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#define ILB_G_KS_NAME "global"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#define ILB_G_KS_CNAME "kstat"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#define ILB_RULE_KS_CNAME "rulestat"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic kstat_t *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_kstat_g_init(netstackid_t stackid, ilb_stack_t *ilbs)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_t *ksp;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_g_kstat_t template = {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "num_rules", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "ip_frag_in", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "ip_frag_dropped", KSTAT_DATA_UINT64, 0 }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra };
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp = kstat_create_netstack(ILB_KSTAT_MOD_NAME, 0, ILB_G_KS_NAME,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_G_KS_CNAME, KSTAT_TYPE_NAMED, NUM_OF_FIELDS(ilb_g_kstat_t),
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra KSTAT_FLAG_VIRTUAL, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ksp == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra bcopy(&template, ilbs->ilbs_kstat, sizeof (template));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp->ks_data = ilbs->ilbs_kstat;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp->ks_private = (void *)(uintptr_t)stackid;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_install(ksp);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ksp);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_kstat_g_fini(netstackid_t stackid, ilb_stack_t *ilbs)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilbs->ilbs_ksp != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(stackid == (netstackid_t)(uintptr_t)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_ksp->ks_private);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_delete_netstack(ilbs->ilbs_ksp, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_ksp = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic kstat_t *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_kstat_init(netstackid_t stackid, ilb_rule_t *rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_t *ksp;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_kstat_t template = {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "num_servers", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "bytes_not_processed", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "pkt_not_processed", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "bytes_dropped", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "pkt_dropped", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "nomem_bytes_dropped", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "nomem_pkt_dropped", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "noport_bytes_dropped", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "noport_pkt_dropped", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "icmp_echo_processed", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "icmp_dropped", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "icmp_too_big_processed", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "icmp_too_big_dropped", KSTAT_DATA_UINT64, 0 }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra };
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp = kstat_create_netstack(ILB_KSTAT_MOD_NAME, rule->ir_ks_instance,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_name, ILB_RULE_KS_CNAME, KSTAT_TYPE_NAMED,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra NUM_OF_FIELDS(ilb_rule_kstat_t), KSTAT_FLAG_VIRTUAL, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ksp == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra bcopy(&template, &rule->ir_kstat, sizeof (template));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp->ks_data = &rule->ir_kstat;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp->ks_private = (void *)(uintptr_t)stackid;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_install(ksp);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ksp);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic kstat_t *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_server_kstat_init(netstackid_t stackid, ilb_rule_t *rule,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *server)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_t *ksp;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_kstat_t template = {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "bytes_processed", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "pkt_processed", KSTAT_DATA_UINT64, 0 },
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra { "ip_address", KSTAT_DATA_STRING, 0 }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra };
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra char cname_buf[KSTAT_STRLEN];
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* 7 is "-sstat" */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(strlen(rule->ir_name) + 7 < KSTAT_STRLEN);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) sprintf(cname_buf, "%s-sstat", rule->ir_name);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp = kstat_create_netstack(ILB_KSTAT_MOD_NAME, rule->ir_ks_instance,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_name, cname_buf, KSTAT_TYPE_NAMED,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra NUM_OF_FIELDS(ilb_server_kstat_t), KSTAT_FLAG_VIRTUAL, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ksp == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra bcopy(&template, &server->iser_kstat, sizeof (template));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp->ks_data = &server->iser_kstat;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp->ks_private = (void *)(uintptr_t)stackid;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_named_setstr(&server->iser_kstat.ip_address,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_ip_addr);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* We never change the IP address */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ksp->ks_data_size += strlen(server->iser_ip_addr) + 1;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_install(ksp);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ksp);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Initialize the rule hash table. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_hash_init(ilb_stack_t *ilbs)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int i;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If ilbs->ilbs_rule_hash_size is not a power of 2, bump it up to
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * the next power of 2.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
de710d24d2fae4468e64da999e1d952a247f142cJosef 'Jeff' Sipek if (!ISP2(ilbs->ilbs_rule_hash_size)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (i = 0; i < 31; i++) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilbs->ilbs_rule_hash_size < (1 << i))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_hash_size = 1 << i;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_g_hash = kmem_zalloc(sizeof (ilb_hash_t) *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_hash_size, KM_SLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (i = 0; i < ilbs->ilbs_rule_hash_size; i++) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_init(&ilbs->ilbs_g_hash[i].ilb_hash_lock, NULL,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra MUTEX_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Clean up the rule hash table. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_hash_fini(ilb_stack_t *ilbs)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilbs->ilbs_g_hash == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(ilbs->ilbs_g_hash, sizeof (ilb_hash_t) *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_hash_size);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Add a rule to the rule hash table. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_hash_add(ilb_stack_t *ilbs, ilb_rule_t *rule, const in6_addr_t *addr)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int i;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra i = ILB_RULE_HASH((uint8_t *)&addr->s6_addr32[3],
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_hash_size);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra DTRACE_PROBE2(ilb__rule__hash__add, ilb_rule_t *, rule, int, i);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_hash[i].ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_next = ilbs->ilbs_g_hash[i].ilb_hash_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilbs->ilbs_g_hash[i].ilb_hash_rule != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_g_hash[i].ilb_hash_rule->ir_hash_prev = rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_prev = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_g_hash[i].ilb_hash_rule = rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash = &ilbs->ilbs_g_hash[i];
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_hash[i].ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Remove a rule from the rule hash table. Note that the rule is not freed
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * in this routine.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_hash_del(ilb_rule_t *rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_hash->ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_hash->ilb_hash_rule == rule) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash->ilb_hash_rule = rule->ir_hash_next;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_hash_next != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_next->ir_hash_prev = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_hash_prev != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_prev->ir_hash_next =
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_next;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_hash_next != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_next->ir_hash_prev =
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_prev;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_hash->ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_next = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash_prev = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_hash = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Given the info of a packet, look for a match in the rule hash table.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic ilb_rule_t *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_hash(ilb_stack_t *ilbs, int l3, int l4, in6_addr_t *addr,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in_port_t port, zoneid_t zoneid, uint32_t len, boolean_t *busy)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int i;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ipaddr_t v4_addr;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *busy = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_V4MAPPED_TO_IPADDR(addr, v4_addr);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra i = ILB_RULE_HASH((uint8_t *)&v4_addr, ilbs->ilbs_rule_hash_size);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra port = ntohs(port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_hash[i].ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (rule = ilbs->ilbs_g_hash[i].ilb_hash_rule; rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule = rule->ir_hash_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (!rule->ir_port_range) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_min_port != port)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (port < rule->ir_min_port ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra port > rule->ir_max_port) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_ipver != l3 || rule->ir_proto != l4 ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_zoneid != zoneid) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (l3 == IPPROTO_IP) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_target_v4 != INADDR_ANY &&
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_target_v4 != v4_addr) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (!IN6_IS_ADDR_UNSPECIFIED(&rule->ir_target_v6) &&
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra !IN6_ARE_ADDR_EQUAL(addr, &rule->ir_target_v6)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Just update the stats if the rule is disabled.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (!(rule->ir_flags & ILB_RULE_ENABLED)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, pkt_not_processed);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, bytes_not_processed, len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else if (rule->ir_flags & ILB_RULE_BUSY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If we are busy...
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * XXX we should have a queue to postpone the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * packet processing. But this requires a
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * mechanism in IP to re-start the packet
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * processing. So for now, just drop the packet.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, bytes_dropped, len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *busy = B_TRUE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_refcnt++;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(rule->ir_refcnt != 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_hash[i].ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Add a rule to the global rule list. This list is for finding all rules
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * in an IP stack. The caller is assumed to hold the ilbs_g_lock.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_g_add(ilb_stack_t *ilbs, ilb_rule_t *rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(mutex_owned(&ilbs->ilbs_g_lock));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_next = ilbs->ilbs_rule_head;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_head = rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_KSTAT_UPDATE(ilbs, num_rules, 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* The call is assumed to hold the ilbs_g_lock. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_g_del(ilb_stack_t *ilbs, ilb_rule_t *rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *prev_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(mutex_owned(&ilbs->ilbs_g_lock));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra prev_rule = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra prev_rule = tmp_rule, tmp_rule = tmp_rule->ir_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule == rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (prev_rule == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_head = tmp_rule->ir_next;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra else
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra prev_rule->ir_next = tmp_rule->ir_next;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_KSTAT_UPDATE(ilbs, num_rules, -1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Helper routine to calculate how many source addresses are in a given
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * range.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic int64_t
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misranum_nat_src_v6(const in6_addr_t *a1, const in6_addr_t *a2)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int64_t ret;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra uint32_t addr1, addr2;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Here we assume that the max number of NAT source cannot be
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * large such that the most significant 2 s6_addr32 must be
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * equal.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra addr1 = ntohl(a1->s6_addr32[3]);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra addr2 = ntohl(a2->s6_addr32[3]);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (a1->s6_addr32[0] != a2->s6_addr32[0] ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra a1->s6_addr32[1] != a2->s6_addr32[1] ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra a1->s6_addr32[2] > a2->s6_addr32[2] ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (a1->s6_addr32[2] == a2->s6_addr32[2] && addr1 > addr2)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (-1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (a1->s6_addr32[2] == a2->s6_addr32[2]) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (addr2 - addr1 + 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = (ntohl(a2->s6_addr32[2]) - ntohl(a1->s6_addr32[2]));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret <<= 32;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ret + addr1 - addr2;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret + 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Add an ILB rule.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_add(ilb_stack_t *ilbs, zoneid_t zoneid, const ilb_rule_cmd_t *cmd)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra netstackid_t stackid;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int ret;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in_port_t min_port, max_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int64_t num_src;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Sanity checks. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->ip_ver != IPPROTO_IP && cmd->ip_ver != IPPROTO_IPV6)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Need to support SCTP... */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->proto != IPPROTO_TCP && cmd->proto != IPPROTO_UDP)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* For full NAT, the NAT source must be supplied. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->topo == ILB_TOPO_IMPL_NAT) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (IS_ADDR_UNSPEC(&cmd->nat_src_start) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IS_ADDR_UNSPEC(&cmd->nat_src_end)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Check invalid mask */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((cmd->flags & ILB_RULE_STICKY) &&
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IS_ADDR_UNSPEC(&cmd->sticky_mask)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Port is passed in network byte order. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra min_port = ntohs(cmd->min_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra max_port = ntohs(cmd->max_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (min_port > max_port)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* min_port == 0 means "all ports". Make it so */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (min_port == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra min_port = 1;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra max_port = 65535;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Funny address checking. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->ip_ver == IPPROTO_IP) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in_addr_t v4_addr1, v4_addr2;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra v4_addr1 = cmd->vip.s6_addr32[3];
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((*(uchar_t *)&v4_addr1) == IN_LOOPBACKNET ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CLASSD(v4_addr1) || v4_addr1 == INADDR_BROADCAST ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra v4_addr1 == INADDR_ANY ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra !IN6_IS_ADDR_V4MAPPED(&cmd->vip)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->topo == ILB_TOPO_IMPL_NAT) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra v4_addr1 = ntohl(cmd->nat_src_start.s6_addr32[3]);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra v4_addr2 = ntohl(cmd->nat_src_end.s6_addr32[3]);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((*(uchar_t *)&v4_addr1) == IN_LOOPBACKNET ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (*(uchar_t *)&v4_addr2) == IN_LOOPBACKNET ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra v4_addr1 == INADDR_BROADCAST ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra v4_addr2 == INADDR_BROADCAST ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra v4_addr1 == INADDR_ANY || v4_addr2 == INADDR_ANY ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CLASSD(v4_addr1) || CLASSD(v4_addr2) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra !IN6_IS_ADDR_V4MAPPED(&cmd->nat_src_start) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra !IN6_IS_ADDR_V4MAPPED(&cmd->nat_src_end)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra num_src = v4_addr2 - v4_addr1 + 1;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (v4_addr1 > v4_addr2 || num_src > ILB_MAX_NAT_SRC)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (IN6_IS_ADDR_LOOPBACK(&cmd->vip) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_MULTICAST(&cmd->vip) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_UNSPECIFIED(&cmd->vip) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_V4MAPPED(&cmd->vip)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->topo == ILB_TOPO_IMPL_NAT) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (IN6_IS_ADDR_LOOPBACK(&cmd->nat_src_start) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_LOOPBACK(&cmd->nat_src_end) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_MULTICAST(&cmd->nat_src_start) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_MULTICAST(&cmd->nat_src_end) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_UNSPECIFIED(&cmd->nat_src_start) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_UNSPECIFIED(&cmd->nat_src_end) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_V4MAPPED(&cmd->nat_src_start) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IS_ADDR_V4MAPPED(&cmd->nat_src_end)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((num_src = num_nat_src_v6(&cmd->nat_src_start,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &cmd->nat_src_end)) < 0 ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra num_src > ILB_MAX_NAT_SRC) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilbs->ilbs_g_hash == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_hash_init(ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilbs->ilbs_c2s_conn_hash == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(ilbs->ilbs_s2c_conn_hash == NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_conn_hash_init(ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_nat_src_init(ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Make sure that the new rule does not duplicate an existing one. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilb_match_rule(ilbs, zoneid, cmd->name, cmd->ip_ver, cmd->proto,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra min_port, max_port, &cmd->vip)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EEXIST);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule = kmem_zalloc(sizeof (ilb_rule_t), KM_NOSLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ENOMEM);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* ir_name is all 0 to begin with */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) memcpy(rule->ir_name, cmd->name, ILB_RULE_NAMESZ - 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek rule->ir_ks_instance = atomic_inc_uint_nv(&ilb_kstat_instance);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra stackid = (netstackid_t)(uintptr_t)ilbs->ilbs_ksp->ks_private;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule->ir_ksp = ilb_rule_kstat_init(stackid, rule)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ENOMEM;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto error;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->topo == ILB_TOPO_IMPL_NAT) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_nat_src_start = cmd->nat_src_start;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_nat_src_end = cmd->nat_src_end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_ipver = cmd->ip_ver;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_proto = cmd->proto;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_topo = cmd->topo;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_min_port = min_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_max_port = max_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_min_port != rule->ir_max_port)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_port_range = B_TRUE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra else
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_port_range = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_zoneid = zoneid;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_target_v6 = cmd->vip;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_servers = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The default connection drain timeout is indefinite (value 0),
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * meaning we will wait for all connections to finish. So we
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * can assign cmd->conn_drain_timeout to it directly.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_conn_drain_timeout = cmd->conn_drain_timeout;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->nat_expiry != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_nat_expiry = cmd->nat_expiry;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra switch (rule->ir_proto) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case IPPROTO_TCP:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_nat_expiry = ilb_conn_tcp_expiry;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case IPPROTO_UDP:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_nat_expiry = ilb_conn_udp_expiry;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra default:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmn_err(CE_PANIC, "data corruption: wrong ir_proto: %p",
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void *)rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->sticky_expiry != 0)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_sticky_expiry = cmd->sticky_expiry;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra else
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_sticky_expiry = ilb_sticky_expiry;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->flags & ILB_RULE_STICKY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_flags |= ILB_RULE_STICKY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_sticky_mask = cmd->sticky_mask;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilbs->ilbs_sticky_hash == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_sticky_hash_init(ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cmd->flags & ILB_RULE_ENABLED)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_flags |= ILB_RULE_ENABLED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_init(&rule->ir_lock, NULL, MUTEX_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_init(&rule->ir_cv, NULL, CV_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_refcnt = 1;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra switch (cmd->algo) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ILB_ALG_IMPL_ROUNDROBIN:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule->ir_alg = ilb_alg_rr_init(rule, NULL)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ENOMEM;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto error;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_alg_type = ILB_ALG_IMPL_ROUNDROBIN;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ILB_ALG_IMPL_HASH_IP:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ILB_ALG_IMPL_HASH_IP_SPORT:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ILB_ALG_IMPL_HASH_IP_VIP:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule->ir_alg = ilb_alg_hash_init(rule,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &cmd->algo)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ENOMEM;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto error;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_alg_type = cmd->algo;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra default:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = EINVAL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto error;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Add it to the global list and hash array at the end. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_g_add(ilbs, rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_hash_add(ilbs, rule, &cmd->vip);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (0);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraerror:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_ksp != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* stackid must be initialized if ir_ksp != NULL */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_delete_netstack(rule->ir_ksp, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(rule, sizeof (ilb_rule_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The final part in deleting a rule. Either called directly or by the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * taskq dispatched.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_del_common(ilb_stack_t *ilbs, ilb_rule_t *tmp_rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra netstackid_t stackid;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra stackid = (netstackid_t)(uintptr_t)ilbs->ilbs_ksp->ks_private;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Let the algorithm know that the rule is going away. The
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * algorithm fini routine will free all its resources with this
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * rule.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule->ir_alg->ilb_alg_fini(&tmp_rule->ir_alg);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while ((server = tmp_rule->ir_servers) != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&server->iser_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_destroy_nat_src(&server->iser_nat_src);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule->ir_conn_drain_timeout != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The garbage collection thread checks this value
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * without grabing a lock. So we need to use
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * atomic_swap_64() to make sure that the value seen
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * by gc thread is intact.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) atomic_swap_64(
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (uint64_t *)&server->iser_die_time,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ddi_get_lbolt64() +
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra SEC_TO_TICK(tmp_rule->ir_conn_drain_timeout));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (server->iser_refcnt > 1)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_wait(&server->iser_cv, &server->iser_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule->ir_servers = server->iser_next;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_delete_netstack(server->iser_ksp, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(server, sizeof (ilb_server_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(tmp_rule->ir_ksp != NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_delete_netstack(tmp_rule->ir_ksp, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(tmp_rule, sizeof (ilb_rule_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* The routine executed by the delayed rule taskq. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_del_tq(void *arg)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_stack_t *ilbs = ((ilb_rule_tq_t *)arg)->ilbs;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule = ((ilb_rule_tq_t *)arg)->rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (rule->ir_refcnt > 1)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_wait(&rule->ir_cv, &rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_del_common(ilbs, rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(arg, sizeof (ilb_rule_tq_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Routine to delete a rule. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_del(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_tq_t *arg;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int err;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((tmp_rule = ilb_find_rule_locked(ilbs, zoneid, name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &err)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (err);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * First remove the rule from the hash array and the global list so
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * that no one can find this rule any more.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_hash_del(tmp_rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_g_del(ilbs, tmp_rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(tmp_rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Now no one can find this rule, we can remove it once all
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * references to it are dropped and all references to the list
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * of servers are dropped. So dispatch a task to finish the deletion.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * We do this instead of letting the last one referencing the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * rule do it. The reason is that the last one may be the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * interrupt thread. We want to minimize the work it needs to
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * do. Rule deletion is not a critical task so it can be delayed.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra arg = kmem_alloc(sizeof (ilb_rule_tq_t), KM_SLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra arg->ilbs = ilbs;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra arg->rule = tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) taskq_dispatch(ilbs->ilbs_rule_taskq, ilb_rule_del_tq, arg,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra TQ_SLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (0);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Given an IP address, check to see if there is a rule using this
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * as the VIP. It can be used to check if we need to drop a fragment.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraboolean_t
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_match_vip_v6(ilb_stack_t *ilbs, in6_addr_t *vip, ilb_rule_t **ret_rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int i;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra boolean_t ret = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra i = ILB_RULE_HASH((uint8_t *)&vip->s6_addr32[3],
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_hash_size);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_hash[i].ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (rule = ilbs->ilbs_g_hash[i].ilb_hash_rule; rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule = rule->ir_hash_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (IN6_ARE_ADDR_EQUAL(vip, &rule->ir_target_v6)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_flags & ILB_RULE_BUSY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ret_rule != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_refcnt++;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *ret_rule = rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = B_TRUE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_hash[i].ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraboolean_t
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_match_vip_v4(ilb_stack_t *ilbs, ipaddr_t addr, ilb_rule_t **ret_rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int i;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra boolean_t ret = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra i = ILB_RULE_HASH((uint8_t *)&addr, ilbs->ilbs_rule_hash_size);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_hash[i].ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (rule = ilbs->ilbs_g_hash[i].ilb_hash_rule; rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule = rule->ir_hash_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_target_v6.s6_addr32[3] == addr) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_flags & ILB_RULE_BUSY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ret_rule != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_refcnt++;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *ret_rule = rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = B_TRUE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_hash[i].ilb_hash_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic ilb_rule_t *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_find_rule_locked(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int *err)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(mutex_owned(&ilbs->ilbs_g_lock));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule = tmp_rule->ir_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule->ir_zoneid != zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (strcasecmp(tmp_rule->ir_name, name) == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&tmp_rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule->ir_flags & ILB_RULE_BUSY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&tmp_rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *err = EINPROGRESS;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule->ir_refcnt++;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&tmp_rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *err = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (tmp_rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *err = ENOENT;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* To find a rule with a given name and zone in the global rule list. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_t *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_find_rule(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int *err)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule = ilb_find_rule_locked(ilbs, zoneid, name, err);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (tmp_rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* Try to match the given packet info and zone ID with a rule. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic boolean_t
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_match_rule(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name, int l3,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int l4, in_port_t min_port, in_port_t max_port, const in6_addr_t *addr)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(mutex_owned(&ilbs->ilbs_g_lock));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule = tmp_rule->ir_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule->ir_zoneid != zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * We don't allow the same name in different rules even if all
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * the other rule components are different.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (strcasecmp(tmp_rule->ir_name, name) == 0)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (B_TRUE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule->ir_ipver != l3 || tmp_rule->ir_proto != l4)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ir_min_port and ir_max_port are the same if ir_port_range
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * is false. In this case, if the ir_min|max_port (same) is
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * outside of the given port range, it is OK. In other cases,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * check if min and max port are outside a rule's range.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule->ir_max_port < min_port ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule->ir_min_port > max_port) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If l3 is IPv4, the addr passed in is assumed to be
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * mapped address.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (V6_OR_V4_INADDR_ANY(*addr) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra V6_OR_V4_INADDR_ANY(tmp_rule->ir_target_v6) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_ARE_ADDR_EQUAL(addr, &tmp_rule->ir_target_v6)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (B_TRUE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (B_FALSE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_enable(ilb_stack_t *ilbs, zoneid_t zoneid,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra const char *rule_name, ilb_rule_t *in_rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int err;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT((in_rule == NULL && rule_name != NULL) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (in_rule != NULL && rule_name == NULL));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = in_rule) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = ilb_find_rule(ilbs, zoneid, rule_name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &err)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (err);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_flags |= ILB_RULE_ENABLED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Only refrele if the rule is passed in. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (in_rule == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (0);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_disable(ilb_stack_t *ilbs, zoneid_t zoneid,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra const char *rule_name, ilb_rule_t *in_rule)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int err;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT((in_rule == NULL && rule_name != NULL) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (in_rule != NULL && rule_name == NULL));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = in_rule) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = ilb_find_rule(ilbs, zoneid, rule_name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &err)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (err);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_flags &= ~ILB_RULE_ENABLED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Only refrele if the rule is passed in. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (in_rule == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (0);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * XXX We should probably have a walker function to walk all rules. For
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * now, just add a simple loop for enable/disable/del.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misravoid
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_enable_all(ilb_stack_t *ilbs, zoneid_t zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (rule = ilbs->ilbs_rule_head; rule != NULL; rule = rule->ir_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_zoneid != zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * No need to hold the rule as we are holding the global
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * lock so it won't go away. Ignore the return value here
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * as the rule is provided so the call cannot fail.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) ilb_rule_enable(ilbs, zoneid, NULL, rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misravoid
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_disable_all(ilb_stack_t *ilbs, zoneid_t zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (rule = ilbs->ilbs_rule_head; rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule = rule->ir_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_zoneid != zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) ilb_rule_disable(ilbs, zoneid, NULL, rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misravoid
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_del_all(ilb_stack_t *ilbs, zoneid_t zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_tq_t *arg;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while ((rule = ilbs->ilbs_rule_head) != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_zoneid != zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_hash_del(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_g_del(ilbs, rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra arg = kmem_alloc(sizeof (ilb_rule_tq_t), KM_SLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra arg->ilbs = ilbs;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra arg->rule = rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) taskq_dispatch(ilbs->ilbs_rule_taskq, ilb_rule_del_tq,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra arg, TQ_SLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * This is just an optimization, so don't grab the global lock. The
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * worst case is that we missed a couple packets.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraboolean_t
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_has_rules(ilb_stack_t *ilbs)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ilbs->ilbs_rule_head != NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic int
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_server_toggle(ilb_stack_t *ilbs, zoneid_t zoneid, const char *rule_name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule, in6_addr_t *addr, boolean_t enable)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *tmp_server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int ret;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT((rule == NULL && rule_name != NULL) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (rule != NULL && rule_name == NULL));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = ilb_find_rule(ilbs, zoneid, rule_name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &ret)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Once we get a hold on the rule, no server can be added/deleted. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (tmp_server = rule->ir_servers; tmp_server != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_server = tmp_server->iser_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (IN6_ARE_ADDR_EQUAL(&tmp_server->iser_addr_v6, addr))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_server == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ENOENT;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto done;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (enable) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = rule->ir_alg->ilb_alg_server_enable(tmp_server,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_alg->ilb_alg_data);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ret == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_server->iser_enabled = B_TRUE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_server->iser_die_time = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = rule->ir_alg->ilb_alg_server_disable(tmp_server,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_alg->ilb_alg_data);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ret == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_server->iser_enabled = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_conn_drain_timeout != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) atomic_swap_64(
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (uint64_t *)&tmp_server->iser_die_time,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ddi_get_lbolt64() + SEC_TO_TICK(
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_conn_drain_timeout));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misradone:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule_name != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_server_enable(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule, in6_addr_t *addr)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ilb_server_toggle(ilbs, zoneid, name, rule, addr, B_TRUE));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_server_disable(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule, in6_addr_t *addr)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ilb_server_toggle(ilbs, zoneid, name, rule, addr, B_FALSE));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Add a back end server to a rule. If the address is IPv4, it is assumed
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * to be passed in as a mapped address.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_server_add(ilb_stack_t *ilbs, ilb_rule_t *rule, ilb_server_info_t *info)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra netstackid_t stackid;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int ret = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in_port_t min_port, max_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in_port_t range;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Port is passed in network byte order. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra min_port = ntohs(info->min_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra max_port = ntohs(info->max_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (min_port > max_port)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINVAL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* min_port == 0 means "all ports". Make it so */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (min_port == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra min_port = 1;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra max_port = 65535;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra range = max_port - min_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* If someone is already doing server add/del, sleeps and wait. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (rule->ir_flags & ILB_RULE_BUSY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cv_wait_sig(&rule->ir_cv, &rule->ir_lock) == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINTR);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Set the rule to be busy to make sure that no new packet can
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * use this rule.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_flags |= ILB_RULE_BUSY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Now wait for all other guys to finish their work. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (rule->ir_refcnt > 2) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cv_wait_sig(&rule->ir_cv, &rule->ir_lock) == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = EINTR;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Sanity checks... */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((IN6_IS_ADDR_V4MAPPED(&info->addr) &&
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_ipver != IPPROTO_IP) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (!IN6_IS_ADDR_V4MAPPED(&info->addr) &&
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_ipver != IPPROTO_IPV6)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = EINVAL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Check for valid port range.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * For DSR, there can be no port shifting. Hence the server
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * specification must be the same as the rule's.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * For half-NAT/NAT, the range must either be 0 (port collapsing) or
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * it must be equal to the same value as the rule port range.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_topo == ILB_TOPO_IMPL_DSR) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_max_port != max_port ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_min_port != min_port) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = EINVAL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((range != rule->ir_max_port - rule->ir_min_port) &&
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra range != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = EINVAL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Check for duplicate. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (server = rule->ir_servers; server != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server = server->iser_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (IN6_ARE_ADDR_EQUAL(&server->iser_addr_v6, &info->addr) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra strcasecmp(server->iser_name, info->name) == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (server != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = EEXIST;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((server = kmem_zalloc(sizeof (ilb_server_t), KM_NOSLEEP)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ENOMEM;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) memcpy(server->iser_name, info->name, ILB_SERVER_NAMESZ - 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) inet_ntop(AF_INET6, &info->addr, server->iser_ip_addr,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra sizeof (server->iser_ip_addr));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra stackid = (netstackid_t)(uintptr_t)ilbs->ilbs_ksp->ks_private;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_ksp = ilb_server_kstat_init(stackid, rule, server);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (server->iser_ksp == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(server, sizeof (ilb_server_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = EINVAL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_stackid = stackid;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_addr_v6 = info->addr;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_min_port = min_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_max_port = max_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (min_port != max_port)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_port_range = B_TRUE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra else
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_port_range = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If the rule uses NAT, find/create the NAT source entry to use
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * for this server.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_topo == ILB_TOPO_IMPL_NAT) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in_port_t port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If the server uses a port range, our port allocation
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * scheme needs to treat it as a wildcard. Refer to the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * comments in ilb_nat.c about the scheme.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (server->iser_port_range)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra port = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra else
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra port = server->iser_min_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((ret = ilb_create_nat_src(ilbs, &server->iser_nat_src,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &server->iser_addr_v6, port, &rule->ir_nat_src_start,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra num_nat_src_v6(&rule->ir_nat_src_start,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &rule->ir_nat_src_end))) != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_delete_netstack(server->iser_ksp, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(server, sizeof (ilb_server_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The iser_lock is only used to protect iser_refcnt. All the other
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * fields in ilb_server_t should not change, except for iser_enabled.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The worst thing that can happen if iser_enabled is messed up is
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * that one or two packets may not be load balanced to a server
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * correctly.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_refcnt = 1;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_enabled = info->flags & ILB_SERVER_ENABLED ? B_TRUE :
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_init(&server->iser_lock, NULL, MUTEX_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_init(&server->iser_cv, NULL, CV_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Let the load balancing algorithm know about the addition. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(rule->ir_alg != NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((ret = rule->ir_alg->ilb_alg_server_add(server,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_alg->ilb_alg_data)) != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_delete_netstack(server->iser_ksp, stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(server, sizeof (ilb_server_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * No need to hold ir_lock since no other thread should manipulate
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * the following fields until ILB_RULE_BUSY is cleared.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_servers == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_next = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_next = rule->ir_servers;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_servers = server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, num_servers);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraend:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_flags &= ~ILB_RULE_BUSY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_signal(&rule->ir_cv);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* The routine executed by the delayed rule processing taskq. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_server_del_tq(void *arg)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *server = (ilb_server_t *)arg;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&server->iser_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (server->iser_refcnt > 1)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_wait(&server->iser_cv, &server->iser_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_delete_netstack(server->iser_ksp, server->iser_stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(server, sizeof (ilb_server_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Delete a back end server from a rule. If the address is IPv4, it is assumed
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * to be passed in as a mapped address.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_server_del(ilb_stack_t *ilbs, zoneid_t zoneid, const char *rule_name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule, in6_addr_t *addr)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *prev_server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int ret = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT((rule == NULL && rule_name != NULL) ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (rule != NULL && rule_name == NULL));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = ilb_find_rule(ilbs, zoneid, rule_name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &ret)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* If someone is already doing server add/del, sleeps and wait. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (rule->ir_flags & ILB_RULE_BUSY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cv_wait_sig(&rule->ir_cv, &rule->ir_lock) == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule_name != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (--rule->ir_refcnt <= 2)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_signal(&rule->ir_cv);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (EINTR);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Set the rule to be busy to make sure that no new packet can
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * use this rule.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_flags |= ILB_RULE_BUSY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Now wait for all other guys to finish their work. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (rule->ir_refcnt > 2) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (cv_wait_sig(&rule->ir_cv, &rule->ir_lock) == 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = EINTR;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra prev_server = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (server = rule->ir_servers; server != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra prev_server = server, server = server->iser_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (IN6_ARE_ADDR_EQUAL(&server->iser_addr_v6, addr))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (server == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ENOENT;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Let the load balancing algorithm know about the removal.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The algorithm may disallow the removal...
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((ret = rule->ir_alg->ilb_alg_server_del(server,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_alg->ilb_alg_data)) != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (prev_server == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_servers = server->iser_next;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra else
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra prev_server->iser_next = server->iser_next;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, num_servers, -1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Mark the server as disabled so that if there is any sticky cache
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * using this server around, it won't be used.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server->iser_enabled = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&server->iser_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * De-allocate the NAT source array. The indiviual ilb_nat_src_entry_t
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * may not go away if there is still a conn using it. The NAT source
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * timer will do the garbage collection.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_destroy_nat_src(&server->iser_nat_src);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* If there is a hard limit on when a server should die, set it. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_conn_drain_timeout != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) atomic_swap_64((uint64_t *)&server->iser_die_time,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni ddi_get_lbolt64() +
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni SEC_TO_TICK(rule->ir_conn_drain_timeout));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (server->iser_refcnt > 1) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) taskq_dispatch(ilbs->ilbs_rule_taskq, ilb_server_del_tq,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server, TQ_SLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&server->iser_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kstat_delete_netstack(server->iser_ksp, server->iser_stackid);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(server, sizeof (ilb_server_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraend:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_flags &= ~ILB_RULE_BUSY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule_name != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_refcnt--;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_signal(&rule->ir_cv);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&rule->ir_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * First check if the destination of the ICMP message matches a VIP of
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * a rule. If it does not, just return ILB_PASSED.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If the destination matches a VIP:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * For ICMP_ECHO_REQUEST, generate a response on behalf of the back end
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * server.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * For ICMP_DEST_UNREACHABLE fragmentation needed, check inside the payload
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * and see which back end server we should send this message to. And we
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * need to do NAT on both the payload message and the outside IP packet.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * For other ICMP messages, drop them.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* ARGSUSED */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic int
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_icmp_v4(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, ipha_t *ipha,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra icmph_t *icmph, ipaddr_t *lb_dst)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ipaddr_t vip;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in6_addr_t addr6;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (!ilb_rule_match_vip_v4(ilbs, ipha->ipha_dst, &rule))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_PASSED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((uint8_t *)icmph + sizeof (icmph_t) > mp->b_wptr) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra switch (icmph->icmph_type) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ICMP_ECHO_REQUEST:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_echo_processed);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra icmph->icmph_type = ICMP_ECHO_REPLY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra icmph->icmph_checksum = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra icmph->icmph_checksum = IP_CSUM(mp, IPH_HDR_LENGTH(ipha), 0);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ipha->ipha_ttl =
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_netstack->netstack_ip->ips_ip_def_ttl;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *lb_dst = ipha->ipha_src;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra vip = ipha->ipha_dst;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ipha->ipha_dst = ipha->ipha_src;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ipha->ipha_src = vip;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_BALANCED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ICMP_DEST_UNREACHABLE: {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int ret;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (icmph->icmph_code != ICMP_FRAGMENTATION_NEEDED) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilb_check_icmp_conn(ilbs, mp, IPPROTO_IP, ipha, icmph,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &addr6)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_2big_processed);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_BALANCED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_2big_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_DROPPED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_V4MAPPED_TO_IPADDR(&addr6, *lb_dst);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra default:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* ARGSUSED */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic int
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_icmp_v6(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, ip6_t *ip6h,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra icmp6_t *icmp6, in6_addr_t *lb_dst)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (!ilb_rule_match_vip_v6(ilbs, &ip6h->ip6_dst, &rule))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_PASSED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((uint8_t *)icmp6 + sizeof (icmp6_t) > mp->b_wptr) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra switch (icmp6->icmp6_type) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ICMP6_ECHO_REQUEST: {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int hdr_len;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_echo_processed);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra icmp6->icmp6_type = ICMP6_ECHO_REPLY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra icmp6->icmp6_cksum = ip6h->ip6_plen;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra hdr_len = (char *)icmp6 - (char *)ip6h;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra icmp6->icmp6_cksum = IP_CSUM(mp, hdr_len,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_pseudo_sum_v6(ip6h, IPPROTO_ICMPV6));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ip6h->ip6_vcf &= ~IPV6_FLOWINFO_FLOWLABEL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ip6h->ip6_hops =
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_netstack->netstack_ip->ips_ipv6_def_hops;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *lb_dst = ip6h->ip6_src;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ip6h->ip6_src = ip6h->ip6_dst;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ip6h->ip6_dst = *lb_dst;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_BALANCED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ICMP6_PACKET_TOO_BIG: {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int ret;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilb_check_icmp_conn(ilbs, mp, IPPROTO_IPV6, ip6h, icmp6,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra lb_dst)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_2big_processed);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_BALANCED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_2big_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_DROPPED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra default:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, icmp_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Common routine to check an incoming packet and decide what to do with it.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * called by ilb_check_v4|v6().
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic int
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_check(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, in6_addr_t *src,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in6_addr_t *dst, int l3, int l4, void *iph, uint8_t *tph, uint32_t pkt_len,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in6_addr_t *lb_dst)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in_port_t sport, dport;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tcpha_t *tcph;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra udpha_t *udph;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra boolean_t balanced;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra struct ilb_sticky_s *s = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int ret;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra uint32_t ip_sum, tp_sum;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_nat_info_t info;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra uint16_t nat_src_idx;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra boolean_t busy;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * We don't really need to switch here since both protocols's
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ports are at the same offset. Just prepare for future protocol
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * specific processing.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra switch (l4) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case IPPROTO_TCP:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tph + TCP_MIN_HEADER_LENGTH > mp->b_wptr)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tcph = (tcpha_t *)tph;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra sport = tcph->tha_lport;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra dport = tcph->tha_fport;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case IPPROTO_UDP:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tph + sizeof (udpha_t) > mp->b_wptr)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra udph = (udpha_t *)tph;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra sport = udph->uha_src_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra dport = udph->uha_dst_port;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra default:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_PASSED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Fast path, there is an existing conn. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilb_check_conn(ilbs, l3, iph, l4, tph, src, dst, sport, dport,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra pkt_len, lb_dst)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_BALANCED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If there is no existing connection for the incoming packet, check
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * to see if the packet matches a rule. If not, just let IP decide
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * what to do with it.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Note: a reply from back end server should not match a rule. A
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * reply should match one existing conn.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule = ilb_rule_hash(ilbs, l3, l4, dst, dport, ill->ill_zoneid,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra pkt_len, &busy);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* If the rule is busy, just drop the packet. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (busy)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra else
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_PASSED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The packet matches a rule, use the rule load balance algorithm
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * to find a server.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra balanced = rule->ir_alg->ilb_alg_lb(src, sport, dst, dport,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_alg->ilb_alg_data, &server);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * This can only happen if there is no server in a rule or all
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * the servers are currently disabled.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (!balanced)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto no_server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If the rule is sticky enabled, we need to check the sticky table.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If there is a sticky entry for the client, use the previous server
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * instead of the one found above (note that both can be the same).
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If there is no entry for that client, add an entry to the sticky
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * table. Both the find and add are done in ilb_sticky_find_add()
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * to avoid checking for duplicate when adding an entry.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_flags & ILB_RULE_STICKY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in6_addr_t addr;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra V6_MASK_COPY(*src, rule->ir_sticky_mask, addr);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((server = ilb_sticky_find_add(ilbs, rule, &addr, server,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &s, &nat_src_idx)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, nomem_pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, nomem_bytes_dropped, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra goto no_server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * We are holding a reference on the rule, so the server
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * cannot go away.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *lb_dst = server->iser_addr_v6;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_S_KSTAT(server, pkt_processed);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_S_KSTAT_UPDATE(server, bytes_processed, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra switch (rule->ir_topo) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ILB_TOPO_IMPL_NAT: {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_nat_src_entry_t *src_ent;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra uint16_t *src_idx;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * We create a cache even if it is not a SYN segment.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The server should return a RST. When we see the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * RST, we will destroy this cache. But by having
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * a cache, we know how to NAT the returned RST.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.vip = *dst;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.dport = dport;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.src = *src;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.sport = sport;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* If stickiness is enabled, use the same source address */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (s != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra src_idx = &nat_src_idx;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra else
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra src_idx = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((src_ent = ilb_alloc_nat_addr(server->iser_nat_src,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra &info.nat_src, &info.nat_sport, src_idx)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (s != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_sticky_refrele(s);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, bytes_dropped, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, noport_pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, noport_bytes_dropped, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_DROPPED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.src_ent = src_ent;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.nat_dst = server->iser_addr_v6;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_port_range && server->iser_port_range) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.nat_dport = htons(ntohs(dport) -
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_min_port + server->iser_min_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.nat_dport = htons(server->iser_min_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If ilb_conn_add() fails, it will release the reference on
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * sticky info and de-allocate the NAT source port allocated
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * above.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilb_conn_add(ilbs, rule, server, src, sport, dst,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra dport, &info, &ip_sum, &tp_sum, s) != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, bytes_dropped, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, nomem_pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, nomem_bytes_dropped, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_DROPPED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_full_nat(l3, iph, l4, tph, &info, ip_sum, tp_sum, B_TRUE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_BALANCED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ILB_TOPO_IMPL_HALF_NAT:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.vip = *dst;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.nat_dst = server->iser_addr_v6;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.dport = dport;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_port_range && server->iser_port_range) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.nat_dport = htons(ntohs(dport) -
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rule->ir_min_port + server->iser_min_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } else {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra info.nat_dport = htons(server->iser_min_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilb_conn_add(ilbs, rule, server, src, sport, dst,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra dport, &info, &ip_sum, &tp_sum, s) != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, bytes_dropped, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, nomem_pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, nomem_bytes_dropped, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_DROPPED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_half_nat(l3, iph, l4, tph, &info, ip_sum, tp_sum, B_TRUE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_BALANCED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra case ILB_TOPO_IMPL_DSR:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * By decrementing the sticky refcnt, the period of
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * stickiness (life time of ilb_sticky_t) will be
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * from now to (now + default expiry time).
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (s != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_sticky_refrele(s);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ILB_BALANCED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra default:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmn_err(CE_PANIC, "data corruption unknown topology: %p",
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void *) rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrano_server:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* This can only happen if there is no server available. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT(rule, pkt_dropped);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_R_KSTAT_UPDATE(rule, bytes_dropped, pkt_len);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ILB_DROPPED);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_check_v4(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, ipha_t *ipha, int l4,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra uint8_t *tph, ipaddr_t *lb_dst)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra in6_addr_t v6_src, v6_dst, v6_lb_dst;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int ret;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(DB_REF(mp) == 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (l4 == IPPROTO_ICMP) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ilb_icmp_v4(ilbs, ill, mp, ipha, (icmph_t *)tph,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra lb_dst));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &v6_src);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &v6_dst);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ret = ilb_check(ilbs, ill, mp, &v6_src, &v6_dst, IPPROTO_IP, l4, ipha,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tph, ntohs(ipha->ipha_length), &v6_lb_dst);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ret == ILB_BALANCED)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IN6_V4MAPPED_TO_IPADDR(&v6_lb_dst, *lb_dst);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ret);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_check_v6(ilb_stack_t *ilbs, ill_t *ill, mblk_t *mp, ip6_t *ip6h, int l4,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra uint8_t *tph, in6_addr_t *lb_dst)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra uint32_t pkt_len;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ASSERT(DB_REF(mp) == 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (l4 == IPPROTO_ICMPV6) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ilb_icmp_v6(ilbs, ill, mp, ip6h, (icmp6_t *)tph,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra lb_dst));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra pkt_len = ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ilb_check(ilbs, ill, mp, &ip6h->ip6_src, &ip6h->ip6_dst,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IPPROTO_IPV6, l4, ip6h, tph, pkt_len, lb_dst));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misravoid
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_get_num_rules(ilb_stack_t *ilbs, zoneid_t zoneid, uint32_t *num_rules)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *num_rules = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule = tmp_rule->ir_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule->ir_zoneid == zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *num_rules += 1;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_get_num_servers(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra uint32_t *num_servers)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int err;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = ilb_find_rule(ilbs, zoneid, name, &err)) == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (err);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *num_servers = rule->ir_kstat.num_servers.value.ui64;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (0);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_get_servers(ilb_stack_t *ilbs, zoneid_t zoneid, const char *name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_info_t *servers, uint32_t *num_servers)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_server_t *server;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra size_t cnt;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int err;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = ilb_find_rule(ilbs, zoneid, name, &err)) == NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (err);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (server = rule->ir_servers, cnt = *num_servers;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server != NULL && cnt > 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra server = server->iser_next, cnt--, servers++) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) memcpy(servers->name, server->iser_name,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_SERVER_NAMESZ);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra servers->addr = server->iser_addr_v6;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra servers->min_port = htons(server->iser_min_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra servers->max_port = htons(server->iser_max_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra servers->flags = server->iser_enabled ? ILB_SERVER_ENABLED : 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra servers->err = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *num_servers -= cnt;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (0);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misravoid
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_get_rulenames(ilb_stack_t *ilbs, zoneid_t zoneid, uint32_t *num_names,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra char *buf)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int cnt;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (*num_names == 0)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (cnt = 0, tmp_rule = ilbs->ilbs_rule_head; tmp_rule != NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra tmp_rule = tmp_rule->ir_next) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (tmp_rule->ir_zoneid != zoneid)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra continue;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) memcpy(buf, tmp_rule->ir_name, ILB_RULE_NAMESZ);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra buf += ILB_RULE_NAMESZ;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (++cnt == *num_names)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra break;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra *num_names = cnt;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraint
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_rule_list(ilb_stack_t *ilbs, zoneid_t zoneid, ilb_rule_cmd_t *cmd)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra int err;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((rule = ilb_find_rule(ilbs, zoneid, cmd->name, &err)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (err);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Except the enabled flags, none of the following will change
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * in the life time of a rule. So we don't hold the mutex when
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * reading them. The worst is to report a wrong enabled flags.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->ip_ver = rule->ir_ipver;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->proto = rule->ir_proto;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->min_port = htons(rule->ir_min_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->max_port = htons(rule->ir_max_port);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->vip = rule->ir_target_v6;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->algo = rule->ir_alg_type;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->topo = rule->ir_topo;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->nat_src_start = rule->ir_nat_src_start;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->nat_src_end = rule->ir_nat_src_end;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->conn_drain_timeout = rule->ir_conn_drain_timeout;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->nat_expiry = rule->ir_nat_expiry;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->sticky_expiry = rule->ir_sticky_expiry;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->flags = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_flags & ILB_RULE_ENABLED)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->flags |= ILB_RULE_ENABLED;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rule->ir_flags & ILB_RULE_STICKY) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->flags |= ILB_RULE_STICKY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cmd->sticky_mask = rule->ir_sticky_mask;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ILB_RULE_REFRELE(rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (0);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void *
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_stack_init(netstackid_t stackid, netstack_t *ns)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_stack_t *ilbs;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra char tq_name[TASKQ_NAMELEN];
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs = kmem_alloc(sizeof (ilb_stack_t), KM_SLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_netstack = ns;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_head = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_g_hash = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_init(&ilbs->ilbs_g_lock, NULL, MUTEX_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_kstat = kmem_alloc(sizeof (ilb_g_kstat_t), KM_SLEEP);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((ilbs->ilbs_ksp = ilb_kstat_g_init(stackid, ilbs)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(ilbs, sizeof (ilb_stack_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ilbs_conn/sticky_hash related info is initialized in
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ilb_conn/sticky_hash_init().
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_conn_taskq = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_hash_size = ilb_rule_hash_size;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_conn_hash_size = ilb_conn_hash_size;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_c2s_conn_hash = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_s2c_conn_hash = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_conn_timer_list = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_sticky_hash = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_sticky_hash_size = ilb_sticky_hash_size;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_sticky_timer_list = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_sticky_taskq = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* The allocation is done later when there is a rule using NAT mode. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_nat_src = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_nat_src_hash_size = ilb_nat_src_hash_size;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_init(&ilbs->ilbs_nat_src_lock, NULL, MUTEX_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_nat_src_tid = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* For listing the conn hash table */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_init(&ilbs->ilbs_conn_list_lock, NULL, MUTEX_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_init(&ilbs->ilbs_conn_list_cv, NULL, CV_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_conn_list_busy = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_conn_list_cur = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_conn_list_connp = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* For listing the sticky hash table */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_init(&ilbs->ilbs_sticky_list_lock, NULL, MUTEX_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra cv_init(&ilbs->ilbs_sticky_list_cv, NULL, CV_DEFAULT, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_sticky_list_busy = B_FALSE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_sticky_list_cur = 0;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_sticky_list_curp = NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
6e0672ac23ea9d93b3e86c7f6e2fd7a79fdd78d3Sangeeta Misra (void) snprintf(tq_name, sizeof (tq_name), "ilb_rule_taskq_%p",
6e0672ac23ea9d93b3e86c7f6e2fd7a79fdd78d3Sangeeta Misra (void *)ns);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbs->ilbs_rule_taskq = taskq_create(tq_name, ILB_RULE_TASKQ_NUM_THR,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra minclsyspri, 1, INT_MAX, TASKQ_PREPOPULATE|TASKQ_DYNAMIC);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* ARGSUSED */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_stack_shutdown(netstackid_t stackid, void *arg)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_stack_t *ilbs = (ilb_stack_t *)arg;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_t *tmp_rule;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_sticky_hash_fini(ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_conn_hash_fini(ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while ((tmp_rule = ilbs->ilbs_rule_head) != NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_hash_del(tmp_rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_g_del(ilbs, tmp_rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_del_common(ilbs, tmp_rule);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_enter(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra }
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mutex_exit(&ilbs->ilbs_g_lock);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (ilbs->ilbs_nat_src != NULL)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_nat_src_fini(ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrastatic void
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_stack_fini(netstackid_t stackid, void * arg)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_stack_t *ilbs = (ilb_stack_t *)arg;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_hash_fini(ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra taskq_destroy(ilbs->ilbs_rule_taskq);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_kstat_g_fini(stackid, ilbs);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(ilbs->ilbs_kstat, sizeof (ilb_g_kstat_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra kmem_free(ilbs, sizeof (ilb_stack_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misravoid
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_ddi_g_init(void)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra netstack_register(NS_ILB, ilb_stack_init, ilb_stack_shutdown,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_stack_fini);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misravoid
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailb_ddi_g_destroy(void)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra{
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra netstack_unregister(NS_ILB);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_conn_cache_fini();
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_sticky_cache_fini();
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra}