1dbed73cbSSangeeta Misra /* 2dbed73cbSSangeeta Misra * CDDL HEADER START 3dbed73cbSSangeeta Misra * 4dbed73cbSSangeeta Misra * The contents of this file are subject to the terms of the 5dbed73cbSSangeeta Misra * Common Development and Distribution License (the "License"). 6dbed73cbSSangeeta Misra * You may not use this file except in compliance with the License. 7dbed73cbSSangeeta Misra * 8dbed73cbSSangeeta Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9dbed73cbSSangeeta Misra * or http://www.opensolaris.org/os/licensing. 10dbed73cbSSangeeta Misra * See the License for the specific language governing permissions 11dbed73cbSSangeeta Misra * and limitations under the License. 12dbed73cbSSangeeta Misra * 13dbed73cbSSangeeta Misra * When distributing Covered Code, include this CDDL HEADER in each 14dbed73cbSSangeeta Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15dbed73cbSSangeeta Misra * If applicable, add the following below this CDDL HEADER, with the 16dbed73cbSSangeeta Misra * fields enclosed by brackets "[]" replaced with your own identifying 17dbed73cbSSangeeta Misra * information: Portions Copyright [yyyy] [name of copyright owner] 18dbed73cbSSangeeta Misra * 19dbed73cbSSangeeta Misra * CDDL HEADER END 20dbed73cbSSangeeta Misra */ 21dbed73cbSSangeeta Misra 22dbed73cbSSangeeta Misra /* 233ae6a67dSSangeeta Misra * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24dbed73cbSSangeeta Misra */ 25dbed73cbSSangeeta Misra 26dbed73cbSSangeeta Misra #include <stdlib.h> 27dbed73cbSSangeeta Misra #include <strings.h> 28dbed73cbSSangeeta Misra #include <stddef.h> 29dbed73cbSSangeeta Misra #include <unistd.h> 30dbed73cbSSangeeta Misra #include <sys/types.h> 31dbed73cbSSangeeta Misra #include <sys/socket.h> 32dbed73cbSSangeeta Misra #include <netinet/in.h> 33dbed73cbSSangeeta Misra #include <arpa/inet.h> 34dbed73cbSSangeeta Misra #include <sys/list.h> 35dbed73cbSSangeeta Misra #include <net/if.h> 36dbed73cbSSangeeta Misra #include <assert.h> 37dbed73cbSSangeeta Misra #include <errno.h> 38dbed73cbSSangeeta Misra #include <libintl.h> 39dbed73cbSSangeeta Misra #include <libilb.h> 40dbed73cbSSangeeta Misra #include <inet/ilb.h> 41dbed73cbSSangeeta Misra #include "libilb_impl.h" 42dbed73cbSSangeeta Misra #include "ilbd.h" 43dbed73cbSSangeeta Misra 44dbed73cbSSangeeta Misra /* until we all use AF_* macros ... */ 45dbed73cbSSangeeta Misra #define AF_2_IPPROTO(_af) (_af == AF_INET)?IPPROTO_IP:IPPROTO_IPV6 46dbed73cbSSangeeta Misra #define IPPROTO_2_AF(_i) (_i == IPPROTO_IP)?AF_INET:AF_INET6 47dbed73cbSSangeeta Misra 483ae6a67dSSangeeta Misra #define PROTOCOL_LEN 16 /* protocol type */ 493ae6a67dSSangeeta Misra #define ADDR_LEN (2 * INET6_ADDRSTRLEN + 1) /* prxy src range */ 503ae6a67dSSangeeta Misra #define PORT_LEN 6 /* hcport:1-65535 or "ANY" */ 513ae6a67dSSangeeta Misra 52dbed73cbSSangeeta Misra static ilb_status_t ilbd_disable_one_rule(ilbd_rule_t *, boolean_t); 53dbed73cbSSangeeta Misra static uint32_t i_flags_d2k(int); 54dbed73cbSSangeeta Misra 55dbed73cbSSangeeta Misra #define ILB_SGSRV_2_KSRV(s, k) \ 56dbed73cbSSangeeta Misra (k)->addr = (s)->sgs_addr; \ 57dbed73cbSSangeeta Misra (k)->min_port = (s)->sgs_minport; \ 58dbed73cbSSangeeta Misra (k)->max_port = (s)->sgs_maxport; \ 59dbed73cbSSangeeta Misra (k)->flags = i_flags_d2k((s)->sgs_flags); \ 60dbed73cbSSangeeta Misra (k)->err = 0; \ 61dbed73cbSSangeeta Misra (void) strlcpy((k)->name, (s)->sgs_srvID, sizeof ((k)->name)) 62dbed73cbSSangeeta Misra 63dbed73cbSSangeeta Misra list_t ilbd_rule_hlist; 64dbed73cbSSangeeta Misra 65dbed73cbSSangeeta Misra static ilb_algo_t 66dbed73cbSSangeeta Misra algo_impl2lib(ilb_algo_impl_t a) 67dbed73cbSSangeeta Misra { 68dbed73cbSSangeeta Misra switch (a) { 69dbed73cbSSangeeta Misra case ILB_ALG_IMPL_ROUNDROBIN: 70dbed73cbSSangeeta Misra return (ILB_ALG_ROUNDROBIN); 71dbed73cbSSangeeta Misra case ILB_ALG_IMPL_HASH_IP: 72dbed73cbSSangeeta Misra return (ILB_ALG_HASH_IP); 73dbed73cbSSangeeta Misra case ILB_ALG_IMPL_HASH_IP_SPORT: 74dbed73cbSSangeeta Misra return (ILB_ALG_HASH_IP_SPORT); 75dbed73cbSSangeeta Misra case ILB_ALG_IMPL_HASH_IP_VIP: 76dbed73cbSSangeeta Misra return (ILB_ALG_HASH_IP_VIP); 77dbed73cbSSangeeta Misra } 78dbed73cbSSangeeta Misra return (0); 79dbed73cbSSangeeta Misra } 80dbed73cbSSangeeta Misra 81dbed73cbSSangeeta Misra static ilb_topo_t 82dbed73cbSSangeeta Misra topo_impl2lib(ilb_topo_impl_t t) 83dbed73cbSSangeeta Misra { 84dbed73cbSSangeeta Misra switch (t) { 85dbed73cbSSangeeta Misra case ILB_TOPO_IMPL_DSR: 86dbed73cbSSangeeta Misra return (ILB_TOPO_DSR); 87dbed73cbSSangeeta Misra case ILB_TOPO_IMPL_NAT: 88dbed73cbSSangeeta Misra return (ILB_TOPO_NAT); 89dbed73cbSSangeeta Misra case ILB_TOPO_IMPL_HALF_NAT: 90dbed73cbSSangeeta Misra return (ILB_TOPO_HALF_NAT); 91dbed73cbSSangeeta Misra } 92dbed73cbSSangeeta Misra return (0); 93dbed73cbSSangeeta Misra } 94dbed73cbSSangeeta Misra 95dbed73cbSSangeeta Misra ilb_algo_impl_t 96dbed73cbSSangeeta Misra algo_lib2impl(ilb_algo_t a) 97dbed73cbSSangeeta Misra { 98dbed73cbSSangeeta Misra switch (a) { 99dbed73cbSSangeeta Misra case ILB_ALG_ROUNDROBIN: 100dbed73cbSSangeeta Misra return (ILB_ALG_IMPL_ROUNDROBIN); 101dbed73cbSSangeeta Misra case ILB_ALG_HASH_IP: 102dbed73cbSSangeeta Misra return (ILB_ALG_IMPL_HASH_IP); 103dbed73cbSSangeeta Misra case ILB_ALG_HASH_IP_SPORT: 104dbed73cbSSangeeta Misra return (ILB_ALG_IMPL_HASH_IP_SPORT); 105dbed73cbSSangeeta Misra case ILB_ALG_HASH_IP_VIP: 106dbed73cbSSangeeta Misra return (ILB_ALG_IMPL_HASH_IP_VIP); 107dbed73cbSSangeeta Misra } 108dbed73cbSSangeeta Misra return (0); 109dbed73cbSSangeeta Misra } 110dbed73cbSSangeeta Misra 111dbed73cbSSangeeta Misra ilb_topo_impl_t 112dbed73cbSSangeeta Misra topo_lib2impl(ilb_topo_t t) 113dbed73cbSSangeeta Misra { 114dbed73cbSSangeeta Misra switch (t) { 115dbed73cbSSangeeta Misra case ILB_TOPO_DSR: 116dbed73cbSSangeeta Misra return (ILB_TOPO_IMPL_DSR); 117dbed73cbSSangeeta Misra case ILB_TOPO_NAT: 118dbed73cbSSangeeta Misra return (ILB_TOPO_IMPL_NAT); 119dbed73cbSSangeeta Misra case ILB_TOPO_HALF_NAT: 120dbed73cbSSangeeta Misra return (ILB_TOPO_IMPL_HALF_NAT); 121dbed73cbSSangeeta Misra } 122dbed73cbSSangeeta Misra return (0); 123dbed73cbSSangeeta Misra } 124dbed73cbSSangeeta Misra 125dbed73cbSSangeeta Misra /* 126dbed73cbSSangeeta Misra * Walk the list of rules and check if its safe to add the 127dbed73cbSSangeeta Misra * the server to the rule (this is a list of rules hanging 128dbed73cbSSangeeta Misra * off of a server group) 129dbed73cbSSangeeta Misra */ 130dbed73cbSSangeeta Misra ilb_status_t 131dbed73cbSSangeeta Misra i_check_srv2rules(list_t *rlist, ilb_sg_srv_t *srv) 132dbed73cbSSangeeta Misra { 133dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 134dbed73cbSSangeeta Misra ilbd_rule_t *rl; 135dbed73cbSSangeeta Misra int server_portrange, rule_portrange; 136dbed73cbSSangeeta Misra int srv_minport, srv_maxport; 137dbed73cbSSangeeta Misra int r_minport, r_maxport; 138dbed73cbSSangeeta Misra 139dbed73cbSSangeeta Misra if (srv == NULL) 140dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 141dbed73cbSSangeeta Misra 142dbed73cbSSangeeta Misra srv_minport = ntohs(srv->sgs_minport); 143dbed73cbSSangeeta Misra srv_maxport = ntohs(srv->sgs_maxport); 144dbed73cbSSangeeta Misra 145dbed73cbSSangeeta Misra for (rl = list_head(rlist); rl != NULL; rl = list_next(rlist, rl)) { 146dbed73cbSSangeeta Misra r_minport = ntohs(rl->irl_minport); 147dbed73cbSSangeeta Misra r_maxport = ntohs(rl->irl_maxport); 148dbed73cbSSangeeta Misra 149dbed73cbSSangeeta Misra if ((srv_minport != 0) && (srv_minport == srv_maxport)) { 150dbed73cbSSangeeta Misra /* server has single port */ 151dbed73cbSSangeeta Misra if (rl->irl_topo == ILB_TOPO_DSR) { 152dbed73cbSSangeeta Misra /* 153dbed73cbSSangeeta Misra * either we have a DSR rule with a port 154dbed73cbSSangeeta Misra * range, or both server and rule 155dbed73cbSSangeeta Misra * have single ports but their values 156dbed73cbSSangeeta Misra * don't match - this is incompatible 157dbed73cbSSangeeta Misra */ 158dbed73cbSSangeeta Misra if (r_maxport > r_minport) { 159dbed73cbSSangeeta Misra rc = ILB_STATUS_INVAL_SRVR; 160dbed73cbSSangeeta Misra break; 161dbed73cbSSangeeta Misra } else if (srv_minport != r_minport) { 162dbed73cbSSangeeta Misra rc = ILB_STATUS_BADPORT; 163dbed73cbSSangeeta Misra break; 164dbed73cbSSangeeta Misra } 165dbed73cbSSangeeta Misra } 166dbed73cbSSangeeta Misra if (rl->irl_hcpflag == ILB_HCI_PROBE_FIX && 167dbed73cbSSangeeta Misra rl->irl_hcport != srv_minport) { 168dbed73cbSSangeeta Misra rc = ILB_STATUS_BADPORT; 169dbed73cbSSangeeta Misra break; 170dbed73cbSSangeeta Misra } 171dbed73cbSSangeeta Misra } else if (srv_maxport > srv_minport) { 172dbed73cbSSangeeta Misra /* server has a port range */ 173dbed73cbSSangeeta Misra if ((rl->irl_topo == ILB_TOPO_DSR) && 174dbed73cbSSangeeta Misra (r_maxport > r_minport)) { 175dbed73cbSSangeeta Misra if ((r_minport != srv_minport) || 176dbed73cbSSangeeta Misra (r_maxport != srv_maxport)) { 177dbed73cbSSangeeta Misra /* 178dbed73cbSSangeeta Misra * we have a DSR rule with a port range 179dbed73cbSSangeeta Misra * and its min and max port values 180dbed73cbSSangeeta Misra * does not meet that of server's 181dbed73cbSSangeeta Misra * - this is incompatible 182dbed73cbSSangeeta Misra */ 183dbed73cbSSangeeta Misra rc = ILB_STATUS_BADPORT; 184dbed73cbSSangeeta Misra break; 185dbed73cbSSangeeta Misra } 186dbed73cbSSangeeta Misra } else if ((rl->irl_topo == ILB_TOPO_DSR) && 187dbed73cbSSangeeta Misra (r_maxport == r_minport)) { 188dbed73cbSSangeeta Misra /* 189dbed73cbSSangeeta Misra * we have a DSR rule with a single 190dbed73cbSSangeeta Misra * port and a server with a port range 191dbed73cbSSangeeta Misra * - this is incompatible 192dbed73cbSSangeeta Misra */ 193dbed73cbSSangeeta Misra rc = ILB_STATUS_INVAL_SRVR; 194dbed73cbSSangeeta Misra break; 195dbed73cbSSangeeta Misra } else if (((rl->irl_topo == ILB_TOPO_NAT) || 196dbed73cbSSangeeta Misra (rl->irl_topo == ILB_TOPO_HALF_NAT)) && 197dbed73cbSSangeeta Misra (r_maxport > r_minport)) { 198dbed73cbSSangeeta Misra server_portrange = srv_maxport - srv_minport; 199dbed73cbSSangeeta Misra rule_portrange = r_maxport - r_minport; 200dbed73cbSSangeeta Misra if (rule_portrange != server_portrange) { 201dbed73cbSSangeeta Misra /* 202dbed73cbSSangeeta Misra * we have a NAT/Half-NAT rule with 203dbed73cbSSangeeta Misra * a port range and server with a port 204dbed73cbSSangeeta Misra * range and there is a mismatch in the 205dbed73cbSSangeeta Misra * sizes of the port ranges - this is 206dbed73cbSSangeeta Misra * incompatible 207dbed73cbSSangeeta Misra */ 208dbed73cbSSangeeta Misra rc = ILB_STATUS_INVAL_SRVR; 209dbed73cbSSangeeta Misra break; 210dbed73cbSSangeeta Misra } 211dbed73cbSSangeeta Misra } 212dbed73cbSSangeeta Misra if (rl->irl_hcpflag == ILB_HCI_PROBE_FIX && 213dbed73cbSSangeeta Misra (rl->irl_hcport > srv_maxport || 214dbed73cbSSangeeta Misra rl->irl_hcport < srv_minport)) { 215dbed73cbSSangeeta Misra rc = ILB_STATUS_BADPORT; 216dbed73cbSSangeeta Misra break; 217dbed73cbSSangeeta Misra } 218dbed73cbSSangeeta Misra } 219dbed73cbSSangeeta Misra } 220dbed73cbSSangeeta Misra 221dbed73cbSSangeeta Misra return (rc); 222dbed73cbSSangeeta Misra } 223dbed73cbSSangeeta Misra 224dbed73cbSSangeeta Misra void 225dbed73cbSSangeeta Misra i_setup_rule_hlist(void) 226dbed73cbSSangeeta Misra { 227dbed73cbSSangeeta Misra list_create(&ilbd_rule_hlist, sizeof (ilbd_rule_t), 228dbed73cbSSangeeta Misra offsetof(ilbd_rule_t, irl_link)); 229dbed73cbSSangeeta Misra } 230dbed73cbSSangeeta Misra 231dbed73cbSSangeeta Misra ilb_status_t 232dbed73cbSSangeeta Misra i_ilbd_save_rule(ilbd_rule_t *irl, ilbd_scf_cmd_t scf_cmd) 233dbed73cbSSangeeta Misra { 234dbed73cbSSangeeta Misra boolean_t enable = irl->irl_flags & ILB_FLAGS_RULE_ENABLED; 235dbed73cbSSangeeta Misra 236dbed73cbSSangeeta Misra switch (scf_cmd) { 237dbed73cbSSangeeta Misra case ILBD_SCF_CREATE: 238dbed73cbSSangeeta Misra return (ilbd_create_pg(ILBD_SCF_RULE, (void *)irl)); 239dbed73cbSSangeeta Misra case ILBD_SCF_DESTROY: 240dbed73cbSSangeeta Misra return (ilbd_destroy_pg(ILBD_SCF_RULE, irl->irl_name)); 241dbed73cbSSangeeta Misra case ILBD_SCF_ENABLE_DISABLE: 242dbed73cbSSangeeta Misra return (ilbd_change_prop(ILBD_SCF_RULE, irl->irl_name, 243dbed73cbSSangeeta Misra "status", &enable)); 244dbed73cbSSangeeta Misra default: 245dbed73cbSSangeeta Misra logdebug("i_ilbd_save_rule: invalid scf cmd %d", scf_cmd); 246dbed73cbSSangeeta Misra return (ILB_STATUS_INVAL_CMD); 247dbed73cbSSangeeta Misra } 248dbed73cbSSangeeta Misra } 249dbed73cbSSangeeta Misra 250dbed73cbSSangeeta Misra /* 251dbed73cbSSangeeta Misra * allocate a new daemon-specific rule from the "template" passed 252dbed73cbSSangeeta Misra * in in *r 253dbed73cbSSangeeta Misra */ 254dbed73cbSSangeeta Misra static ilbd_rule_t * 255dbed73cbSSangeeta Misra i_alloc_ilbd_rule(ilb_rule_info_t *r) 256dbed73cbSSangeeta Misra { 257dbed73cbSSangeeta Misra ilbd_rule_t *rl; 258dbed73cbSSangeeta Misra 259dbed73cbSSangeeta Misra rl = calloc(sizeof (*rl), 1); 260dbed73cbSSangeeta Misra if (rl != NULL && r != NULL) 261dbed73cbSSangeeta Misra bcopy(r, &rl->irl_info, sizeof (*r)); 262dbed73cbSSangeeta Misra 263dbed73cbSSangeeta Misra return (rl); 264dbed73cbSSangeeta Misra } 265dbed73cbSSangeeta Misra 266dbed73cbSSangeeta Misra static ilbd_rule_t * 267dbed73cbSSangeeta Misra i_find_rule_byname(const char *name) 268dbed73cbSSangeeta Misra { 269dbed73cbSSangeeta Misra ilbd_rule_t *rl; 270dbed73cbSSangeeta Misra 271dbed73cbSSangeeta Misra /* find position of rule in list */ 272dbed73cbSSangeeta Misra rl = list_head(&ilbd_rule_hlist); 273dbed73cbSSangeeta Misra while (rl != NULL && 274dbed73cbSSangeeta Misra strncmp(rl->irl_name, name, sizeof (rl->irl_name)) != 0) { 275dbed73cbSSangeeta Misra rl = list_next(&ilbd_rule_hlist, rl); 276dbed73cbSSangeeta Misra } 277dbed73cbSSangeeta Misra 278dbed73cbSSangeeta Misra return (rl); 279dbed73cbSSangeeta Misra } 280dbed73cbSSangeeta Misra 281dbed73cbSSangeeta Misra /* 282dbed73cbSSangeeta Misra * get exactly one rule (named in rl->irl_name) data from kernel 283dbed73cbSSangeeta Misra */ 284dbed73cbSSangeeta Misra static ilb_status_t 285dbed73cbSSangeeta Misra ilb_get_krule(ilb_rule_info_t *rl) 286dbed73cbSSangeeta Misra { 287dbed73cbSSangeeta Misra ilb_status_t rc; 288dbed73cbSSangeeta Misra ilb_rule_cmd_t kcmd; 289dbed73cbSSangeeta Misra 290dbed73cbSSangeeta Misra kcmd.cmd = ILB_LIST_RULE; 291dbed73cbSSangeeta Misra (void) strlcpy(kcmd.name, rl->rl_name, sizeof (kcmd.name)); 292dbed73cbSSangeeta Misra kcmd.flags = 0; 293dbed73cbSSangeeta Misra 294dbed73cbSSangeeta Misra rc = do_ioctl(&kcmd, 0); 295dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 296dbed73cbSSangeeta Misra return (rc); 297dbed73cbSSangeeta Misra 298dbed73cbSSangeeta Misra rl->rl_flags = kcmd.flags; 299dbed73cbSSangeeta Misra rl->rl_ipversion = IPPROTO_2_AF(kcmd.ip_ver); 300dbed73cbSSangeeta Misra rl->rl_vip = kcmd.vip; 301dbed73cbSSangeeta Misra rl->rl_proto = kcmd.proto; 302dbed73cbSSangeeta Misra rl->rl_minport = kcmd.min_port; 303dbed73cbSSangeeta Misra rl->rl_maxport = kcmd.max_port; 304dbed73cbSSangeeta Misra rl->rl_algo = algo_impl2lib(kcmd.algo); 305dbed73cbSSangeeta Misra rl->rl_topo = topo_impl2lib(kcmd.topo); 306dbed73cbSSangeeta Misra rl->rl_stickymask = kcmd.sticky_mask; 307dbed73cbSSangeeta Misra rl->rl_nat_src_start = kcmd.nat_src_start; 308dbed73cbSSangeeta Misra rl->rl_nat_src_end = kcmd.nat_src_end; 309dbed73cbSSangeeta Misra (void) strlcpy(rl->rl_name, kcmd.name, sizeof (rl->rl_name)); 310dbed73cbSSangeeta Misra rl->rl_conndrain = kcmd.conn_drain_timeout; 311dbed73cbSSangeeta Misra rl->rl_nat_timeout = kcmd.nat_expiry; 312dbed73cbSSangeeta Misra rl->rl_sticky_timeout = kcmd.sticky_expiry; 313dbed73cbSSangeeta Misra 314dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 315dbed73cbSSangeeta Misra } 316dbed73cbSSangeeta Misra 317dbed73cbSSangeeta Misra ilb_status_t 318dbed73cbSSangeeta Misra ilbd_retrieve_rule(ilbd_name_t rl_name, uint32_t *rbuf, size_t *rbufsz) 319dbed73cbSSangeeta Misra { 320dbed73cbSSangeeta Misra ilbd_rule_t *irl = NULL; 321dbed73cbSSangeeta Misra ilb_status_t rc; 322dbed73cbSSangeeta Misra ilb_rule_info_t *rinfo; 323dbed73cbSSangeeta Misra 324dbed73cbSSangeeta Misra irl = i_find_rule_byname(rl_name); 325dbed73cbSSangeeta Misra if (irl == NULL) 326dbed73cbSSangeeta Misra return (ILB_STATUS_ENOENT); 327dbed73cbSSangeeta Misra 328dbed73cbSSangeeta Misra ilbd_reply_ok(rbuf, rbufsz); 329dbed73cbSSangeeta Misra rinfo = (ilb_rule_info_t *)&((ilb_comm_t *)rbuf)->ic_data; 330dbed73cbSSangeeta Misra bcopy(&irl->irl_info, rinfo, sizeof (*rinfo)); 331dbed73cbSSangeeta Misra 332dbed73cbSSangeeta Misra /* 333dbed73cbSSangeeta Misra * Check if the various timeout values are 0. If one is, get the 334dbed73cbSSangeeta Misra * default values from kernel. 335dbed73cbSSangeeta Misra */ 336dbed73cbSSangeeta Misra if (rinfo->rl_conndrain == 0 || rinfo->rl_nat_timeout == 0 || 337dbed73cbSSangeeta Misra rinfo->rl_sticky_timeout == 0) { 338dbed73cbSSangeeta Misra ilb_rule_info_t tmp_info; 339dbed73cbSSangeeta Misra 340dbed73cbSSangeeta Misra (void) strcpy(tmp_info.rl_name, rinfo->rl_name); 341dbed73cbSSangeeta Misra rc = ilb_get_krule(&tmp_info); 342dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 343dbed73cbSSangeeta Misra return (rc); 344dbed73cbSSangeeta Misra if (rinfo->rl_conndrain == 0) 345dbed73cbSSangeeta Misra rinfo->rl_conndrain = tmp_info.rl_conndrain; 346*2c2d21e9SRichard Lowe if ((rinfo->rl_topo == ILB_TOPO_NAT || 347*2c2d21e9SRichard Lowe rinfo->rl_topo == ILB_TOPO_HALF_NAT) && 348dbed73cbSSangeeta Misra rinfo->rl_nat_timeout == 0) { 349dbed73cbSSangeeta Misra rinfo->rl_nat_timeout = tmp_info.rl_nat_timeout; 350dbed73cbSSangeeta Misra } 351dbed73cbSSangeeta Misra if ((rinfo->rl_flags & ILB_FLAGS_RULE_STICKY) && 352dbed73cbSSangeeta Misra rinfo->rl_sticky_timeout == 0) { 353dbed73cbSSangeeta Misra rinfo->rl_sticky_timeout = tmp_info.rl_sticky_timeout; 354dbed73cbSSangeeta Misra } 355dbed73cbSSangeeta Misra } 356dbed73cbSSangeeta Misra *rbufsz += sizeof (ilb_rule_info_t); 357dbed73cbSSangeeta Misra 358dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 359dbed73cbSSangeeta Misra } 360dbed73cbSSangeeta Misra 361dbed73cbSSangeeta Misra static ilb_status_t 362dbed73cbSSangeeta Misra ilbd_destroy_one_rule(ilbd_rule_t *irl) 363dbed73cbSSangeeta Misra { 364dbed73cbSSangeeta Misra ilb_status_t rc; 365dbed73cbSSangeeta Misra ilb_name_cmd_t kcmd; 366dbed73cbSSangeeta Misra 367dbed73cbSSangeeta Misra /* 368dbed73cbSSangeeta Misra * as far as talking to the kernel is concerned, "all rules" 369dbed73cbSSangeeta Misra * is handled in one go somewhere else, so we only 370dbed73cbSSangeeta Misra * tell the kernel about single rules here. 371dbed73cbSSangeeta Misra */ 372dbed73cbSSangeeta Misra if ((irl->irl_flags & ILB_FLAGS_RULE_ALLRULES) == 0) { 373dbed73cbSSangeeta Misra kcmd.cmd = ILB_DESTROY_RULE; 374dbed73cbSSangeeta Misra (void) strlcpy(kcmd.name, irl->irl_name, sizeof (kcmd.name)); 375dbed73cbSSangeeta Misra kcmd.flags = 0; 376dbed73cbSSangeeta Misra 377dbed73cbSSangeeta Misra rc = do_ioctl(&kcmd, 0); 378dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 379dbed73cbSSangeeta Misra return (rc); 380dbed73cbSSangeeta Misra 381dbed73cbSSangeeta Misra } 382dbed73cbSSangeeta Misra list_remove(&irl->irl_sg->isg_rulelist, irl); 383dbed73cbSSangeeta Misra list_remove(&ilbd_rule_hlist, irl); 384dbed73cbSSangeeta Misra 385dbed73cbSSangeeta Misra /* 386dbed73cbSSangeeta Misra * When dissociating a rule, only two errors can happen. The hc 387dbed73cbSSangeeta Misra * name is incorrect or the rule is not associated with the hc 388dbed73cbSSangeeta Misra * object. Both should not happen.... The check is for debugging 389dbed73cbSSangeeta Misra * purpose. 390dbed73cbSSangeeta Misra */ 391dbed73cbSSangeeta Misra if (RULE_HAS_HC(irl) && (rc = ilbd_hc_dissociate_rule(irl)) != 392dbed73cbSSangeeta Misra ILB_STATUS_OK) { 393dbed73cbSSangeeta Misra logerr("ilbd_destroy_one_rule: cannot " 394dbed73cbSSangeeta Misra "dissociate %s from hc object %s: %d", 395dbed73cbSSangeeta Misra irl->irl_name, irl->irl_hcname, rc); 396dbed73cbSSangeeta Misra } 397dbed73cbSSangeeta Misra 398dbed73cbSSangeeta Misra rc = i_ilbd_save_rule(irl, ILBD_SCF_DESTROY); 399dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 400dbed73cbSSangeeta Misra logdebug("ilbd_destroy_rule: save rule failed"); 401dbed73cbSSangeeta Misra 402dbed73cbSSangeeta Misra free(irl); 403dbed73cbSSangeeta Misra return (rc); 404dbed73cbSSangeeta Misra } 405dbed73cbSSangeeta Misra 406dbed73cbSSangeeta Misra /* 407dbed73cbSSangeeta Misra * the following two functions are the other's opposite, and can 408dbed73cbSSangeeta Misra * call into each other for roll back purposes in case of error. 409dbed73cbSSangeeta Misra * To avoid endless recursion, the 'is_rollback' parameter must be 410dbed73cbSSangeeta Misra * set to B_TRUE in the roll back case. 411dbed73cbSSangeeta Misra */ 412dbed73cbSSangeeta Misra static ilb_status_t 413dbed73cbSSangeeta Misra ilbd_enable_one_rule(ilbd_rule_t *irl, boolean_t is_rollback) 414dbed73cbSSangeeta Misra { 415dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 416dbed73cbSSangeeta Misra ilb_name_cmd_t kcmd; 417dbed73cbSSangeeta Misra 418dbed73cbSSangeeta Misra /* no use sending a no-op to the kernel */ 419dbed73cbSSangeeta Misra if ((irl->irl_flags & ILB_FLAGS_RULE_ENABLED) != 0) 420dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 421dbed73cbSSangeeta Misra 422dbed73cbSSangeeta Misra irl->irl_flags |= ILB_FLAGS_RULE_ENABLED; 423dbed73cbSSangeeta Misra 424dbed73cbSSangeeta Misra /* "all rules" is handled in one go somewhere else, not here */ 425dbed73cbSSangeeta Misra if ((irl->irl_flags & ILB_FLAGS_RULE_ALLRULES) == 0) { 426dbed73cbSSangeeta Misra kcmd.cmd = ILB_ENABLE_RULE; 427dbed73cbSSangeeta Misra (void) strlcpy(kcmd.name, irl->irl_name, sizeof (kcmd.name)); 428dbed73cbSSangeeta Misra kcmd.flags = 0; 429dbed73cbSSangeeta Misra 430dbed73cbSSangeeta Misra rc = do_ioctl(&kcmd, 0); 431dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 432dbed73cbSSangeeta Misra return (rc); 433dbed73cbSSangeeta Misra } 434dbed73cbSSangeeta Misra if (RULE_HAS_HC(irl) && (rc = ilbd_hc_enable_rule(irl)) != 435dbed73cbSSangeeta Misra ILB_STATUS_OK) { 436dbed73cbSSangeeta Misra /* Undo the kernel work */ 437dbed73cbSSangeeta Misra kcmd.cmd = ILB_DISABLE_RULE; 438dbed73cbSSangeeta Misra /* Cannot do much if ioctl fails... */ 439dbed73cbSSangeeta Misra (void) do_ioctl(&kcmd, 0); 440dbed73cbSSangeeta Misra return (rc); 441dbed73cbSSangeeta Misra } 442dbed73cbSSangeeta Misra 443dbed73cbSSangeeta Misra if (!is_rollback) { 444dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) 445dbed73cbSSangeeta Misra rc = i_ilbd_save_rule(irl, ILBD_SCF_ENABLE_DISABLE); 446dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 447dbed73cbSSangeeta Misra /* ignore rollback return code */ 448dbed73cbSSangeeta Misra (void) ilbd_disable_one_rule(irl, B_TRUE); 449dbed73cbSSangeeta Misra } 450dbed73cbSSangeeta Misra 451dbed73cbSSangeeta Misra return (rc); 452dbed73cbSSangeeta Misra } 453dbed73cbSSangeeta Misra 454dbed73cbSSangeeta Misra static ilb_status_t 455dbed73cbSSangeeta Misra ilbd_disable_one_rule(ilbd_rule_t *irl, boolean_t is_rollback) 456dbed73cbSSangeeta Misra { 457dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 458dbed73cbSSangeeta Misra ilb_name_cmd_t kcmd; 459dbed73cbSSangeeta Misra 460dbed73cbSSangeeta Misra /* no use sending a no-op to the kernel */ 461dbed73cbSSangeeta Misra if ((irl->irl_flags & ILB_FLAGS_RULE_ENABLED) == 0) 462dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 463dbed73cbSSangeeta Misra 464dbed73cbSSangeeta Misra irl->irl_flags &= ~ILB_FLAGS_RULE_ENABLED; 465dbed73cbSSangeeta Misra 466dbed73cbSSangeeta Misra /* "all rules" is handled in one go somewhere else, not here */ 467dbed73cbSSangeeta Misra if ((irl->irl_flags & ILB_FLAGS_RULE_ALLRULES) == 0) { 468dbed73cbSSangeeta Misra kcmd.cmd = ILB_DISABLE_RULE; 469dbed73cbSSangeeta Misra (void) strlcpy(kcmd.name, irl->irl_name, sizeof (kcmd.name)); 470dbed73cbSSangeeta Misra kcmd.flags = 0; 471dbed73cbSSangeeta Misra 472dbed73cbSSangeeta Misra rc = do_ioctl(&kcmd, 0); 473dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 474dbed73cbSSangeeta Misra return (rc); 475dbed73cbSSangeeta Misra } 476dbed73cbSSangeeta Misra 477dbed73cbSSangeeta Misra if (RULE_HAS_HC(irl) && (rc = ilbd_hc_disable_rule(irl)) != 478dbed73cbSSangeeta Misra ILB_STATUS_OK) { 479dbed73cbSSangeeta Misra /* Undo the kernel work */ 480dbed73cbSSangeeta Misra kcmd.cmd = ILB_ENABLE_RULE; 481dbed73cbSSangeeta Misra /* Cannot do much if ioctl fails... */ 482dbed73cbSSangeeta Misra (void) do_ioctl(&kcmd, 0); 483dbed73cbSSangeeta Misra return (rc); 484dbed73cbSSangeeta Misra } 485dbed73cbSSangeeta Misra 486dbed73cbSSangeeta Misra if (!is_rollback) { 487dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) 488dbed73cbSSangeeta Misra rc = i_ilbd_save_rule(irl, ILBD_SCF_ENABLE_DISABLE); 489dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 490dbed73cbSSangeeta Misra /* ignore rollback return code */ 491dbed73cbSSangeeta Misra (void) ilbd_enable_one_rule(irl, B_TRUE); 492dbed73cbSSangeeta Misra } 493dbed73cbSSangeeta Misra 494dbed73cbSSangeeta Misra return (rc); 495dbed73cbSSangeeta Misra } 496dbed73cbSSangeeta Misra 497dbed73cbSSangeeta Misra /* 498dbed73cbSSangeeta Misra * Generates an audit record for a supplied rule name 499dbed73cbSSangeeta Misra * Used for enable_rule, disable_rule, delete_rule, 500dbed73cbSSangeeta Misra * and create_rule subcommands 501dbed73cbSSangeeta Misra */ 502dbed73cbSSangeeta Misra static void 503dbed73cbSSangeeta Misra ilbd_audit_rule_event(const char *audit_rule_name, 504dbed73cbSSangeeta Misra ilb_rule_info_t *rlinfo, ilbd_cmd_t cmd, ilb_status_t rc, 505dbed73cbSSangeeta Misra ucred_t *ucredp) 506dbed73cbSSangeeta Misra { 507dbed73cbSSangeeta Misra adt_session_data_t *ah; 508dbed73cbSSangeeta Misra adt_event_data_t *event; 509dbed73cbSSangeeta Misra au_event_t flag; 510dbed73cbSSangeeta Misra int scf_val_len = ILBD_MAX_VALUE_LEN; 5113ae6a67dSSangeeta Misra char *aobuf = NULL; /* algo:topo */ 5123ae6a67dSSangeeta Misra char *valstr1 = NULL; 5133ae6a67dSSangeeta Misra char *valstr2 = NULL; 5143ae6a67dSSangeeta Misra char pbuf[PROTOCOL_LEN]; /* protocol */ 5153ae6a67dSSangeeta Misra char hcpbuf[PORT_LEN]; /* hcport */ 516dbed73cbSSangeeta Misra int audit_error; 517dbed73cbSSangeeta Misra 518dbed73cbSSangeeta Misra if ((ucredp == NULL) && (cmd == ILBD_CREATE_RULE)) { 519dbed73cbSSangeeta Misra /* 520dbed73cbSSangeeta Misra * we came here from the path where ilbd incorporates 521dbed73cbSSangeeta Misra * the configuration that is listed in SCF : 522dbed73cbSSangeeta Misra * i_ilbd_read_config->ilbd_walk_rule_pgs-> 523dbed73cbSSangeeta Misra * ->ilbd_scf_instance_walk_pg->ilbd_create_rule 524dbed73cbSSangeeta Misra * We skip auditing in that case 525dbed73cbSSangeeta Misra */ 526dbed73cbSSangeeta Misra return; 527dbed73cbSSangeeta Misra } 528dbed73cbSSangeeta Misra if (adt_start_session(&ah, NULL, 0) != 0) { 529dbed73cbSSangeeta Misra logerr("ilbd_audit_rule_event: adt_start_session failed"); 530dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 531dbed73cbSSangeeta Misra } 532dbed73cbSSangeeta Misra if (adt_set_from_ucred(ah, ucredp, ADT_NEW) != 0) { 533dbed73cbSSangeeta Misra (void) adt_end_session(ah); 534dbed73cbSSangeeta Misra logerr("ilbd_audit_rule_event: adt_set_from_ucred failed"); 535dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 536dbed73cbSSangeeta Misra } 537dbed73cbSSangeeta Misra if (cmd == ILBD_ENABLE_RULE) 538dbed73cbSSangeeta Misra flag = ADT_ilb_enable_rule; 539dbed73cbSSangeeta Misra else if (cmd == ILBD_DISABLE_RULE) 540dbed73cbSSangeeta Misra flag = ADT_ilb_disable_rule; 541dbed73cbSSangeeta Misra else if (cmd == ILBD_DESTROY_RULE) 542dbed73cbSSangeeta Misra flag = ADT_ilb_delete_rule; 543dbed73cbSSangeeta Misra else if (cmd == ILBD_CREATE_RULE) 544dbed73cbSSangeeta Misra flag = ADT_ilb_create_rule; 545dbed73cbSSangeeta Misra 546dbed73cbSSangeeta Misra if ((event = adt_alloc_event(ah, flag)) == NULL) { 547dbed73cbSSangeeta Misra logerr("ilbd_audit_rule_event: adt_alloc_event failed"); 548dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 549dbed73cbSSangeeta Misra } 550dbed73cbSSangeeta Misra 551dbed73cbSSangeeta Misra (void) memset((char *)event, 0, sizeof (adt_event_data_t)); 552dbed73cbSSangeeta Misra 553dbed73cbSSangeeta Misra switch (cmd) { 554dbed73cbSSangeeta Misra case ILBD_DESTROY_RULE: 555dbed73cbSSangeeta Misra event->adt_ilb_delete_rule.auth_used = NET_ILB_CONFIG_AUTH; 556dbed73cbSSangeeta Misra event->adt_ilb_delete_rule.rule_name = (char *)audit_rule_name; 557dbed73cbSSangeeta Misra break; 558dbed73cbSSangeeta Misra case ILBD_ENABLE_RULE: 559dbed73cbSSangeeta Misra event->adt_ilb_enable_rule.auth_used = NET_ILB_ENABLE_AUTH; 560dbed73cbSSangeeta Misra event->adt_ilb_enable_rule.rule_name = (char *)audit_rule_name; 561dbed73cbSSangeeta Misra break; 562dbed73cbSSangeeta Misra case ILBD_DISABLE_RULE: 563dbed73cbSSangeeta Misra event->adt_ilb_disable_rule.auth_used = NET_ILB_ENABLE_AUTH; 564dbed73cbSSangeeta Misra event->adt_ilb_disable_rule.rule_name = (char *)audit_rule_name; 565dbed73cbSSangeeta Misra break; 566dbed73cbSSangeeta Misra case ILBD_CREATE_RULE: 5673ae6a67dSSangeeta Misra if (((aobuf = malloc(scf_val_len)) == NULL) || 5683ae6a67dSSangeeta Misra ((valstr1 = malloc(scf_val_len)) == NULL) || 5693ae6a67dSSangeeta Misra ((valstr2 = malloc(scf_val_len)) == NULL)) { 5703ae6a67dSSangeeta Misra logerr("ilbd_audit_rule_event: could not" 5713ae6a67dSSangeeta Misra " allocate buffer"); 5723ae6a67dSSangeeta Misra exit(EXIT_FAILURE); 5733ae6a67dSSangeeta Misra } 574dbed73cbSSangeeta Misra 575dbed73cbSSangeeta Misra event->adt_ilb_create_rule.auth_used = NET_ILB_CONFIG_AUTH; 576dbed73cbSSangeeta Misra 5775df82708SSangeeta Misra /* Fill in virtual IP address type */ 5785df82708SSangeeta Misra if (IN6_IS_ADDR_V4MAPPED(&rlinfo->rl_vip)) { 5795df82708SSangeeta Misra event->adt_ilb_create_rule.virtual_ipaddress_type = 5805df82708SSangeeta Misra ADT_IPv4; 5815df82708SSangeeta Misra cvt_addr(event->adt_ilb_create_rule.virtual_ipaddress, 5825df82708SSangeeta Misra ADT_IPv4, rlinfo->rl_vip); 5835df82708SSangeeta Misra } else { 5845df82708SSangeeta Misra event->adt_ilb_create_rule.virtual_ipaddress_type = 5855df82708SSangeeta Misra ADT_IPv6; 5865df82708SSangeeta Misra cvt_addr(event->adt_ilb_create_rule.virtual_ipaddress, 5875df82708SSangeeta Misra ADT_IPv6, rlinfo->rl_vip); 5885df82708SSangeeta Misra } 589dbed73cbSSangeeta Misra /* Fill in port - could be a single value or a range */ 590dbed73cbSSangeeta Misra event->adt_ilb_create_rule.min_port = ntohs(rlinfo->rl_minport); 591dbed73cbSSangeeta Misra if (ntohs(rlinfo->rl_maxport) > ntohs(rlinfo->rl_minport)) { 592dbed73cbSSangeeta Misra /* port range */ 593dbed73cbSSangeeta Misra event->adt_ilb_create_rule.max_port = 594dbed73cbSSangeeta Misra ntohs(rlinfo->rl_maxport); 595dbed73cbSSangeeta Misra } else { 596dbed73cbSSangeeta Misra /* in audit record, max=min when single port */ 597dbed73cbSSangeeta Misra event->adt_ilb_create_rule.max_port = 598dbed73cbSSangeeta Misra ntohs(rlinfo->rl_minport); 599dbed73cbSSangeeta Misra } 600dbed73cbSSangeeta Misra 601dbed73cbSSangeeta Misra /* 602dbed73cbSSangeeta Misra * Fill in protocol - if user does not specify it, 603dbed73cbSSangeeta Misra * its TCP by default 604dbed73cbSSangeeta Misra */ 605dbed73cbSSangeeta Misra if (rlinfo->rl_proto == IPPROTO_UDP) 6063ae6a67dSSangeeta Misra (void) snprintf(pbuf, PROTOCOL_LEN, "UDP"); 607dbed73cbSSangeeta Misra else 6083ae6a67dSSangeeta Misra (void) snprintf(pbuf, PROTOCOL_LEN, "TCP"); 609dbed73cbSSangeeta Misra event->adt_ilb_create_rule.protocol = pbuf; 610dbed73cbSSangeeta Misra 611dbed73cbSSangeeta Misra /* Fill in algorithm and operation type */ 612dbed73cbSSangeeta Misra ilbd_algo_to_str(rlinfo->rl_algo, valstr1); 613dbed73cbSSangeeta Misra ilbd_topo_to_str(rlinfo->rl_topo, valstr2); 6143ae6a67dSSangeeta Misra (void) snprintf(aobuf, scf_val_len, "%s:%s", 615dbed73cbSSangeeta Misra valstr1, valstr2); 616dbed73cbSSangeeta Misra event->adt_ilb_create_rule.algo_optype = aobuf; 617dbed73cbSSangeeta Misra 618dbed73cbSSangeeta Misra /* Fill in proxy-src for the NAT case */ 619dbed73cbSSangeeta Misra if (rlinfo->rl_topo == ILB_TOPO_NAT) { 6205df82708SSangeeta Misra /* copy starting proxy-src address */ 6215df82708SSangeeta Misra if (IN6_IS_ADDR_V4MAPPED(&rlinfo->rl_nat_src_start)) { 6225df82708SSangeeta Misra /* V4 case */ 6235df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_min_type = 6245df82708SSangeeta Misra ADT_IPv4; 6255df82708SSangeeta Misra cvt_addr( 6265df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_min, 6275df82708SSangeeta Misra ADT_IPv4, rlinfo->rl_nat_src_start); 6285df82708SSangeeta Misra } else { 6295df82708SSangeeta Misra /* V6 case */ 6305df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_min_type = 6315df82708SSangeeta Misra ADT_IPv6; 6325df82708SSangeeta Misra cvt_addr( 6335df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_min, 6345df82708SSangeeta Misra ADT_IPv6, rlinfo->rl_nat_src_start); 6355df82708SSangeeta Misra } 6365df82708SSangeeta Misra 6375df82708SSangeeta Misra /* copy ending proxy-src address */ 638dbed73cbSSangeeta Misra if (&rlinfo->rl_nat_src_end == 0) { 6395df82708SSangeeta Misra /* proxy-src is a single address */ 6405df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_max_type = 6415df82708SSangeeta Misra event-> 6425df82708SSangeeta Misra adt_ilb_create_rule.proxy_src_min_type; 6435df82708SSangeeta Misra (void) memcpy( 6445df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_max, 6455df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_min, 6465df82708SSangeeta Misra (4 * sizeof (uint32_t))); 6475df82708SSangeeta Misra } else if ( 6485df82708SSangeeta Misra IN6_IS_ADDR_V4MAPPED(&rlinfo->rl_nat_src_end)) { 6495df82708SSangeeta Misra /* 6505df82708SSangeeta Misra * proxy-src is a address range - copy ending 6515df82708SSangeeta Misra * proxy-src address 6525df82708SSangeeta Misra * V4 case 6535df82708SSangeeta Misra */ 6545df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_max_type = 6555df82708SSangeeta Misra ADT_IPv4; 6565df82708SSangeeta Misra cvt_addr( 6575df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_max, 6585df82708SSangeeta Misra ADT_IPv4, rlinfo->rl_nat_src_end); 659dbed73cbSSangeeta Misra } else { 6605df82708SSangeeta Misra /* V6 case */ 6615df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_max_type = 6625df82708SSangeeta Misra ADT_IPv6; 6635df82708SSangeeta Misra cvt_addr( 6645df82708SSangeeta Misra event->adt_ilb_create_rule.proxy_src_max, 6655df82708SSangeeta Misra ADT_IPv6, rlinfo->rl_nat_src_end); 666dbed73cbSSangeeta Misra } 667dbed73cbSSangeeta Misra } 668dbed73cbSSangeeta Misra 669dbed73cbSSangeeta Misra /* 670dbed73cbSSangeeta Misra * Fill in pmask if user has specified one - 0 means 671dbed73cbSSangeeta Misra * no persistence 672dbed73cbSSangeeta Misra */ 673dbed73cbSSangeeta Misra valstr1[0] = '\0'; 674dbed73cbSSangeeta Misra ilbd_ip_to_str(rlinfo->rl_ipversion, &rlinfo->rl_stickymask, 675dbed73cbSSangeeta Misra valstr1); 676dbed73cbSSangeeta Misra event->adt_ilb_create_rule.persist_mask = valstr1; 677dbed73cbSSangeeta Misra 678dbed73cbSSangeeta Misra /* If there is a hcname */ 679dbed73cbSSangeeta Misra if (rlinfo->rl_hcname[0] != '\0') 680dbed73cbSSangeeta Misra event->adt_ilb_create_rule.hcname = rlinfo->rl_hcname; 681dbed73cbSSangeeta Misra 682dbed73cbSSangeeta Misra /* Fill in hcport */ 683dbed73cbSSangeeta Misra if (rlinfo->rl_hcpflag == ILB_HCI_PROBE_FIX) { 684dbed73cbSSangeeta Misra /* hcport is specified by user */ 6853ae6a67dSSangeeta Misra (void) snprintf(hcpbuf, PORT_LEN, "%d", 686dbed73cbSSangeeta Misra rlinfo->rl_hcport); 687dbed73cbSSangeeta Misra event->adt_ilb_create_rule.hcport = hcpbuf; 688dbed73cbSSangeeta Misra } else if (rlinfo->rl_hcpflag == ILB_HCI_PROBE_ANY) { 689dbed73cbSSangeeta Misra /* user has specified "ANY" */ 6903ae6a67dSSangeeta Misra (void) snprintf(hcpbuf, PORT_LEN, "ANY"); 691dbed73cbSSangeeta Misra event->adt_ilb_create_rule.hcport = hcpbuf; 692dbed73cbSSangeeta Misra } 693dbed73cbSSangeeta Misra /* 694dbed73cbSSangeeta Misra * Fill out the conndrain, nat_timeout and persist_timeout 695dbed73cbSSangeeta Misra * If the user does not specify them, the default value 696dbed73cbSSangeeta Misra * is set in the kernel. Userland does not know what 697dbed73cbSSangeeta Misra * the values are. So if the user 698dbed73cbSSangeeta Misra * does not specify these values they will show up as 699dbed73cbSSangeeta Misra * 0 in the audit record. 700dbed73cbSSangeeta Misra */ 701dbed73cbSSangeeta Misra event->adt_ilb_create_rule.conndrain_timeout = 702dbed73cbSSangeeta Misra rlinfo->rl_conndrain; 703dbed73cbSSangeeta Misra event->adt_ilb_create_rule.nat_timeout = 704dbed73cbSSangeeta Misra rlinfo->rl_nat_timeout; 705dbed73cbSSangeeta Misra event->adt_ilb_create_rule.persist_timeout = 706dbed73cbSSangeeta Misra rlinfo->rl_sticky_timeout; 707dbed73cbSSangeeta Misra 708dbed73cbSSangeeta Misra /* Fill out servergroup and rule name */ 709dbed73cbSSangeeta Misra event->adt_ilb_create_rule.server_group = rlinfo->rl_sgname; 710dbed73cbSSangeeta Misra event->adt_ilb_create_rule.rule_name = rlinfo->rl_name; 711dbed73cbSSangeeta Misra break; 712dbed73cbSSangeeta Misra } 713dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) { 714dbed73cbSSangeeta Misra if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 715dbed73cbSSangeeta Misra logerr("ilbd_audit_rule_event:adt_put_event failed"); 716dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 717dbed73cbSSangeeta Misra } 718dbed73cbSSangeeta Misra } else { 719dbed73cbSSangeeta Misra audit_error = ilberror2auditerror(rc); 720dbed73cbSSangeeta Misra if (adt_put_event(event, ADT_FAILURE, audit_error) != 0) { 721dbed73cbSSangeeta Misra logerr("ilbd_audit_rule_event: adt_put_event failed"); 722dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 723dbed73cbSSangeeta Misra } 724dbed73cbSSangeeta Misra } 725dbed73cbSSangeeta Misra adt_free_event(event); 7263ae6a67dSSangeeta Misra free(aobuf); 7273ae6a67dSSangeeta Misra free(valstr1); 7283ae6a67dSSangeeta Misra free(valstr2); 729dbed73cbSSangeeta Misra (void) adt_end_session(ah); 730dbed73cbSSangeeta Misra } 7315df82708SSangeeta Misra /* 7325df82708SSangeeta Misra * converts IP address from in6_addr format to uint32_t[4] 7335df82708SSangeeta Misra * This conversion is needed for recording IP address in 7345df82708SSangeeta Misra * audit records. 7355df82708SSangeeta Misra */ 7365df82708SSangeeta Misra void 7375df82708SSangeeta Misra cvt_addr(uint32_t *audit, int32_t type, struct in6_addr address) 7385df82708SSangeeta Misra { 7395df82708SSangeeta Misra 7405df82708SSangeeta Misra if (type == ADT_IPv4) { 7415df82708SSangeeta Misra /* address is IPv4 */ 7425df82708SSangeeta Misra audit[0] = address._S6_un._S6_u32[3]; 7435df82708SSangeeta Misra } else { 7445df82708SSangeeta Misra /* address is IPv6 */ 7455df82708SSangeeta Misra (void) memcpy(audit, address._S6_un._S6_u32, 7465df82708SSangeeta Misra (4 * sizeof (uint32_t))); 7475df82708SSangeeta Misra } 7485df82708SSangeeta Misra } 749dbed73cbSSangeeta Misra 750dbed73cbSSangeeta Misra static ilb_status_t 751dbed73cbSSangeeta Misra i_ilbd_action_switch(ilbd_rule_t *irl, ilbd_cmd_t cmd, 752dbed73cbSSangeeta Misra boolean_t is_rollback, ucred_t *ucredp) 753dbed73cbSSangeeta Misra { 754dbed73cbSSangeeta Misra ilb_status_t rc; 755dbed73cbSSangeeta Misra 756dbed73cbSSangeeta Misra switch (cmd) { 757dbed73cbSSangeeta Misra case ILBD_DESTROY_RULE: 758dbed73cbSSangeeta Misra rc = ilbd_destroy_one_rule(irl); 759dbed73cbSSangeeta Misra if (!is_rollback) { 760dbed73cbSSangeeta Misra ilbd_audit_rule_event(irl->irl_name, NULL, 761dbed73cbSSangeeta Misra cmd, rc, ucredp); 762dbed73cbSSangeeta Misra } 763dbed73cbSSangeeta Misra return (rc); 764dbed73cbSSangeeta Misra case ILBD_ENABLE_RULE: 765dbed73cbSSangeeta Misra rc = ilbd_enable_one_rule(irl, is_rollback); 766dbed73cbSSangeeta Misra if (!is_rollback) { 767dbed73cbSSangeeta Misra ilbd_audit_rule_event(irl->irl_name, NULL, cmd, 768dbed73cbSSangeeta Misra rc, ucredp); 769dbed73cbSSangeeta Misra } 770dbed73cbSSangeeta Misra return (rc); 771dbed73cbSSangeeta Misra case ILBD_DISABLE_RULE: 772dbed73cbSSangeeta Misra rc = ilbd_disable_one_rule(irl, is_rollback); 773dbed73cbSSangeeta Misra if (!is_rollback) { 774dbed73cbSSangeeta Misra ilbd_audit_rule_event(irl->irl_name, NULL, cmd, 775dbed73cbSSangeeta Misra rc, ucredp); 776dbed73cbSSangeeta Misra } 777dbed73cbSSangeeta Misra return (rc); 778dbed73cbSSangeeta Misra } 779dbed73cbSSangeeta Misra return (ILB_STATUS_INVAL_CMD); 780dbed73cbSSangeeta Misra } 781dbed73cbSSangeeta Misra 782dbed73cbSSangeeta Misra static ilb_cmd_t 783dbed73cbSSangeeta Misra i_ilbd2ilb_cmd(ilbd_cmd_t c) 784dbed73cbSSangeeta Misra { 785dbed73cbSSangeeta Misra ilb_cmd_t r; 786dbed73cbSSangeeta Misra 787dbed73cbSSangeeta Misra switch (c) { 788dbed73cbSSangeeta Misra case ILBD_CREATE_RULE: 789dbed73cbSSangeeta Misra r = ILB_CREATE_RULE; 790dbed73cbSSangeeta Misra break; 791dbed73cbSSangeeta Misra case ILBD_DESTROY_RULE: 792dbed73cbSSangeeta Misra r = ILB_DESTROY_RULE; 793dbed73cbSSangeeta Misra break; 794dbed73cbSSangeeta Misra case ILBD_ENABLE_RULE: 795dbed73cbSSangeeta Misra r = ILB_ENABLE_RULE; 796dbed73cbSSangeeta Misra break; 797dbed73cbSSangeeta Misra case ILBD_DISABLE_RULE: 798dbed73cbSSangeeta Misra r = ILB_DISABLE_RULE; 799dbed73cbSSangeeta Misra break; 800dbed73cbSSangeeta Misra } 801dbed73cbSSangeeta Misra return (r); 802dbed73cbSSangeeta Misra } 803dbed73cbSSangeeta Misra 804dbed73cbSSangeeta Misra static ilbd_cmd_t 805dbed73cbSSangeeta Misra get_undo_cmd(ilbd_cmd_t cmd) 806dbed73cbSSangeeta Misra { 807dbed73cbSSangeeta Misra ilbd_cmd_t u_cmd; 808dbed73cbSSangeeta Misra 809dbed73cbSSangeeta Misra switch (cmd) { 810dbed73cbSSangeeta Misra case ILBD_DESTROY_RULE: 811dbed73cbSSangeeta Misra u_cmd = ILBD_BAD_CMD; 812dbed73cbSSangeeta Misra break; 813dbed73cbSSangeeta Misra case ILBD_ENABLE_RULE: 814dbed73cbSSangeeta Misra u_cmd = ILBD_DISABLE_RULE; 815dbed73cbSSangeeta Misra break; 816dbed73cbSSangeeta Misra case ILBD_DISABLE_RULE: 817dbed73cbSSangeeta Misra u_cmd = ILBD_ENABLE_RULE; 818dbed73cbSSangeeta Misra break; 819dbed73cbSSangeeta Misra } 820dbed73cbSSangeeta Misra 821dbed73cbSSangeeta Misra return (u_cmd); 822dbed73cbSSangeeta Misra } 823dbed73cbSSangeeta Misra 824dbed73cbSSangeeta Misra static ilb_status_t 825dbed73cbSSangeeta Misra i_ilbd_rule_action(const char *rule_name, const struct passwd *ps, 826dbed73cbSSangeeta Misra ilbd_cmd_t cmd, ucred_t *ucredp) 827dbed73cbSSangeeta Misra { 828dbed73cbSSangeeta Misra ilbd_rule_t *irl, *irl_next; 829dbed73cbSSangeeta Misra boolean_t is_all_rules = B_FALSE; 830dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 831dbed73cbSSangeeta Misra ilb_name_cmd_t kcmd; 832dbed73cbSSangeeta Misra ilbd_cmd_t u_cmd; 833dbed73cbSSangeeta Misra char rulename[ILB_NAMESZ]; 834dbed73cbSSangeeta Misra 835dbed73cbSSangeeta Misra if (ps != NULL) { 836dbed73cbSSangeeta Misra if ((cmd == ILBD_ENABLE_RULE) || (cmd == ILBD_DISABLE_RULE)) 837dbed73cbSSangeeta Misra rc = ilbd_check_client_enable_auth(ps); 838dbed73cbSSangeeta Misra else 839dbed73cbSSangeeta Misra rc = ilbd_check_client_config_auth(ps); 840dbed73cbSSangeeta Misra /* generate the audit record before bailing out */ 841dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 842dbed73cbSSangeeta Misra if (rule_name != '\0') { 843dbed73cbSSangeeta Misra ilbd_audit_rule_event(rule_name, NULL, 844dbed73cbSSangeeta Misra cmd, rc, ucredp); 845dbed73cbSSangeeta Misra } else { 846dbed73cbSSangeeta Misra (void) snprintf(rulename, sizeof (rulename), 847dbed73cbSSangeeta Misra "all"); 848dbed73cbSSangeeta Misra ilbd_audit_rule_event(rulename, NULL, cmd, rc, 849dbed73cbSSangeeta Misra ucredp); 850dbed73cbSSangeeta Misra } 851dbed73cbSSangeeta Misra goto out; 852dbed73cbSSangeeta Misra } 853dbed73cbSSangeeta Misra } 854dbed73cbSSangeeta Misra is_all_rules = rule_name[0] == 0; 855dbed73cbSSangeeta Misra 856dbed73cbSSangeeta Misra /* just one rule */ 857dbed73cbSSangeeta Misra if (!is_all_rules) { 858dbed73cbSSangeeta Misra irl = i_find_rule_byname(rule_name); 859dbed73cbSSangeeta Misra if (irl == NULL) { 860dbed73cbSSangeeta Misra rc = ILB_STATUS_ENORULE; 861dbed73cbSSangeeta Misra ilbd_audit_rule_event(rule_name, NULL, cmd, rc, ucredp); 862dbed73cbSSangeeta Misra goto out; 863dbed73cbSSangeeta Misra } 864dbed73cbSSangeeta Misra /* auditing will be done by i_ilbd_action_switch() */ 865dbed73cbSSangeeta Misra rc = i_ilbd_action_switch(irl, cmd, B_FALSE, ucredp); 866dbed73cbSSangeeta Misra goto out; 867dbed73cbSSangeeta Misra } 868dbed73cbSSangeeta Misra 869dbed73cbSSangeeta Misra /* all rules: first tell the kernel, then walk the daemon's list */ 870dbed73cbSSangeeta Misra kcmd.cmd = i_ilbd2ilb_cmd(cmd); 871dbed73cbSSangeeta Misra kcmd.flags = ILB_RULE_ALLRULES; 872dbed73cbSSangeeta Misra 873dbed73cbSSangeeta Misra rc = do_ioctl(&kcmd, 0); 874dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 875dbed73cbSSangeeta Misra (void) snprintf(rulename, sizeof (rulename), "all"); 876dbed73cbSSangeeta Misra ilbd_audit_rule_event(rulename, NULL, cmd, rc, ucredp); 877dbed73cbSSangeeta Misra goto out; 878dbed73cbSSangeeta Misra } 879dbed73cbSSangeeta Misra 880dbed73cbSSangeeta Misra irl = list_head(&ilbd_rule_hlist); 881dbed73cbSSangeeta Misra while (irl != NULL) { 882dbed73cbSSangeeta Misra irl_next = list_next(&ilbd_rule_hlist, irl); 883dbed73cbSSangeeta Misra irl->irl_flags |= ILB_FLAGS_RULE_ALLRULES; 884dbed73cbSSangeeta Misra /* auditing will be done by i_ilbd_action_switch() */ 885dbed73cbSSangeeta Misra rc = i_ilbd_action_switch(irl, cmd, B_FALSE, ucredp); 886dbed73cbSSangeeta Misra irl->irl_flags &= ~ILB_FLAGS_RULE_ALLRULES; 887dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 888dbed73cbSSangeeta Misra goto rollback_list; 889dbed73cbSSangeeta Misra irl = irl_next; 890dbed73cbSSangeeta Misra } 891dbed73cbSSangeeta Misra return (rc); 892dbed73cbSSangeeta Misra 893dbed73cbSSangeeta Misra rollback_list: 894dbed73cbSSangeeta Misra u_cmd = get_undo_cmd(cmd); 895dbed73cbSSangeeta Misra if (u_cmd == ILBD_BAD_CMD) 896dbed73cbSSangeeta Misra return (rc); 897dbed73cbSSangeeta Misra 898dbed73cbSSangeeta Misra if (is_all_rules) { 899dbed73cbSSangeeta Misra kcmd.cmd = i_ilbd2ilb_cmd(u_cmd); 900dbed73cbSSangeeta Misra (void) do_ioctl(&kcmd, 0); 901dbed73cbSSangeeta Misra } 902dbed73cbSSangeeta Misra /* current list element failed, so we start with previous one */ 903dbed73cbSSangeeta Misra irl = list_prev(&ilbd_rule_hlist, irl); 904dbed73cbSSangeeta Misra while (irl != NULL) { 905dbed73cbSSangeeta Misra if (is_all_rules) 906dbed73cbSSangeeta Misra irl->irl_flags |= ILB_FLAGS_RULE_ALLRULES; 907dbed73cbSSangeeta Misra 908dbed73cbSSangeeta Misra /* 909dbed73cbSSangeeta Misra * When the processing of a command consists of 910dbed73cbSSangeeta Misra * multiple sequential steps, and one of them fails, 911dbed73cbSSangeeta Misra * ilbd performs rollback to undo the steps taken before the 912dbed73cbSSangeeta Misra * failing step. Since ilbd is initiating these steps 913dbed73cbSSangeeta Misra * there is not need to audit them. 914dbed73cbSSangeeta Misra */ 915dbed73cbSSangeeta Misra rc = i_ilbd_action_switch(irl, u_cmd, B_TRUE, NULL); 916dbed73cbSSangeeta Misra irl->irl_flags &= ~ILB_FLAGS_RULE_ALLRULES; 917dbed73cbSSangeeta Misra 918dbed73cbSSangeeta Misra irl = list_prev(&ilbd_rule_hlist, irl); 919dbed73cbSSangeeta Misra } 920dbed73cbSSangeeta Misra out: 921dbed73cbSSangeeta Misra return (rc); 922dbed73cbSSangeeta Misra } 923dbed73cbSSangeeta Misra 924dbed73cbSSangeeta Misra ilb_status_t 925dbed73cbSSangeeta Misra ilbd_destroy_rule(ilbd_name_t rule_name, const struct passwd *ps, 926dbed73cbSSangeeta Misra ucred_t *ucredp) 927dbed73cbSSangeeta Misra { 928dbed73cbSSangeeta Misra return (i_ilbd_rule_action(rule_name, ps, ILBD_DESTROY_RULE, ucredp)); 929dbed73cbSSangeeta Misra } 930dbed73cbSSangeeta Misra 931dbed73cbSSangeeta Misra ilb_status_t 932dbed73cbSSangeeta Misra ilbd_enable_rule(ilbd_name_t rule_name, const struct passwd *ps, 933dbed73cbSSangeeta Misra ucred_t *ucredp) 934dbed73cbSSangeeta Misra { 935dbed73cbSSangeeta Misra return (i_ilbd_rule_action(rule_name, ps, ILBD_ENABLE_RULE, ucredp)); 936dbed73cbSSangeeta Misra 937dbed73cbSSangeeta Misra } 938dbed73cbSSangeeta Misra 939dbed73cbSSangeeta Misra ilb_status_t 940dbed73cbSSangeeta Misra ilbd_disable_rule(ilbd_name_t rule_name, const struct passwd *ps, 941dbed73cbSSangeeta Misra ucred_t *ucredp) 942dbed73cbSSangeeta Misra { 943dbed73cbSSangeeta Misra return (i_ilbd_rule_action(rule_name, ps, ILBD_DISABLE_RULE, ucredp)); 944dbed73cbSSangeeta Misra } 945dbed73cbSSangeeta Misra 946dbed73cbSSangeeta Misra /* 947dbed73cbSSangeeta Misra * allocate storage for a kernel rule command and fill from 948dbed73cbSSangeeta Misra * "template" irl, if non-NULL 949dbed73cbSSangeeta Misra */ 950dbed73cbSSangeeta Misra static ilb_rule_cmd_t * 951dbed73cbSSangeeta Misra i_alloc_kernel_rule_cmd(ilbd_rule_t *irl) 952dbed73cbSSangeeta Misra { 953dbed73cbSSangeeta Misra ilb_rule_cmd_t *kcmd; 954dbed73cbSSangeeta Misra 955dbed73cbSSangeeta Misra kcmd = (ilb_rule_cmd_t *)malloc(sizeof (*kcmd)); 956dbed73cbSSangeeta Misra if (kcmd == NULL) 957dbed73cbSSangeeta Misra return (kcmd); 958dbed73cbSSangeeta Misra 959dbed73cbSSangeeta Misra bzero(kcmd, sizeof (*kcmd)); 960dbed73cbSSangeeta Misra 961dbed73cbSSangeeta Misra if (irl != NULL) { 962dbed73cbSSangeeta Misra kcmd->flags = irl->irl_flags; 963dbed73cbSSangeeta Misra kcmd->ip_ver = AF_2_IPPROTO(irl->irl_ipversion); 964dbed73cbSSangeeta Misra kcmd->vip = irl->irl_vip; 965dbed73cbSSangeeta Misra kcmd->proto = irl->irl_proto; 966dbed73cbSSangeeta Misra kcmd->min_port = irl->irl_minport; 967dbed73cbSSangeeta Misra kcmd->max_port = irl->irl_maxport; 968dbed73cbSSangeeta Misra kcmd->algo = algo_lib2impl(irl->irl_algo); 969dbed73cbSSangeeta Misra kcmd->topo = topo_lib2impl(irl->irl_topo); 970dbed73cbSSangeeta Misra kcmd->sticky_mask = irl->irl_stickymask; 971dbed73cbSSangeeta Misra kcmd->nat_src_start = irl->irl_nat_src_start; 972dbed73cbSSangeeta Misra kcmd->nat_src_end = irl->irl_nat_src_end; 973dbed73cbSSangeeta Misra kcmd->conn_drain_timeout = irl->irl_conndrain; 974dbed73cbSSangeeta Misra kcmd->nat_expiry = irl->irl_nat_timeout; 975dbed73cbSSangeeta Misra kcmd->sticky_expiry = irl->irl_sticky_timeout; 976dbed73cbSSangeeta Misra (void) strlcpy(kcmd->name, irl->irl_name, 977dbed73cbSSangeeta Misra sizeof (kcmd->name)); 978dbed73cbSSangeeta Misra } 979dbed73cbSSangeeta Misra return (kcmd); 980dbed73cbSSangeeta Misra } 981dbed73cbSSangeeta Misra 982dbed73cbSSangeeta Misra /* 983dbed73cbSSangeeta Misra * ncount is the next to be used index into (*kcmdp)->servers 984dbed73cbSSangeeta Misra */ 985dbed73cbSSangeeta Misra static ilb_status_t 986dbed73cbSSangeeta Misra adjust_srv_info_cmd(ilb_servers_info_cmd_t **kcmdp, int index) 987dbed73cbSSangeeta Misra { 988dbed73cbSSangeeta Misra ilb_servers_info_cmd_t *kcmd = *kcmdp; 989dbed73cbSSangeeta Misra size_t sz; 990dbed73cbSSangeeta Misra 991dbed73cbSSangeeta Misra if (kcmd != NULL && kcmd->num_servers > index + 1) 992dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 993dbed73cbSSangeeta Misra 994dbed73cbSSangeeta Misra /* 995dbed73cbSSangeeta Misra * the first ilb_server_info_t is part of *kcmd, so 996dbed73cbSSangeeta Misra * by using index (which is one less than the total needed) here, 997dbed73cbSSangeeta Misra * we allocate exactly the amount we need. 998dbed73cbSSangeeta Misra */ 999dbed73cbSSangeeta Misra sz = sizeof (*kcmd) + (index * sizeof (ilb_server_info_t)); 1000dbed73cbSSangeeta Misra kcmd = (ilb_servers_info_cmd_t *)realloc(kcmd, sz); 1001dbed73cbSSangeeta Misra if (kcmd == NULL) 1002dbed73cbSSangeeta Misra return (ILB_STATUS_ENOMEM); 1003dbed73cbSSangeeta Misra 1004dbed73cbSSangeeta Misra /* 1005dbed73cbSSangeeta Misra * we don't count the slot we newly allocated yet. 1006dbed73cbSSangeeta Misra */ 1007dbed73cbSSangeeta Misra kcmd->num_servers = index; 1008dbed73cbSSangeeta Misra *kcmdp = kcmd; 1009dbed73cbSSangeeta Misra 1010dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1011dbed73cbSSangeeta Misra } 1012dbed73cbSSangeeta Misra 1013dbed73cbSSangeeta Misra /* 1014dbed73cbSSangeeta Misra * this function adds all servers in srvlist to the kernel(!) rule 1015dbed73cbSSangeeta Misra * the name of which is passed as argument. 1016dbed73cbSSangeeta Misra */ 1017dbed73cbSSangeeta Misra static ilb_status_t 1018dbed73cbSSangeeta Misra i_update_ksrv_rules(char *name, ilbd_sg_t *sg, ilbd_rule_t *rl) 1019dbed73cbSSangeeta Misra { 1020dbed73cbSSangeeta Misra ilb_status_t rc; 1021dbed73cbSSangeeta Misra ilbd_srv_t *srvp; 1022dbed73cbSSangeeta Misra ilb_servers_info_cmd_t *kcmd = NULL; 1023dbed73cbSSangeeta Misra int i; 1024dbed73cbSSangeeta Misra 1025dbed73cbSSangeeta Misra /* 1026dbed73cbSSangeeta Misra * If the servergroup doesn't have any servers associated with 1027dbed73cbSSangeeta Misra * it yet, there's nothing more to do here. 1028dbed73cbSSangeeta Misra */ 1029dbed73cbSSangeeta Misra if (sg->isg_srvcount == 0) 1030dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1031dbed73cbSSangeeta Misra 1032dbed73cbSSangeeta Misra /* 1033dbed73cbSSangeeta Misra * walk the list of servers attached to this SG 1034dbed73cbSSangeeta Misra */ 1035dbed73cbSSangeeta Misra srvp = list_head(&sg->isg_srvlist); 1036dbed73cbSSangeeta Misra for (i = 0; srvp != NULL; srvp = list_next(&sg->isg_srvlist, srvp)) { 1037dbed73cbSSangeeta Misra rc = adjust_srv_info_cmd(&kcmd, i); 1038dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 1039dbed73cbSSangeeta Misra return (rc); 1040dbed73cbSSangeeta Misra 1041dbed73cbSSangeeta Misra ILB_SGSRV_2_KSRV(&srvp->isv_srv, &kcmd->servers[i]); 1042dbed73cbSSangeeta Misra /* 1043dbed73cbSSangeeta Misra * "no port" means "copy rule's port" (for kernel rule) 1044dbed73cbSSangeeta Misra */ 1045dbed73cbSSangeeta Misra if (kcmd->servers[i].min_port == 0) { 1046dbed73cbSSangeeta Misra kcmd->servers[i].min_port = rl->irl_minport; 1047dbed73cbSSangeeta Misra kcmd->servers[i].max_port = rl->irl_maxport; 1048dbed73cbSSangeeta Misra } 1049dbed73cbSSangeeta Misra i++; 1050dbed73cbSSangeeta Misra } 1051dbed73cbSSangeeta Misra 1052dbed73cbSSangeeta Misra kcmd->cmd = ILB_ADD_SERVERS; 1053dbed73cbSSangeeta Misra kcmd->num_servers = i; 1054dbed73cbSSangeeta Misra (void) strlcpy(kcmd->name, name, sizeof (kcmd->name)); 1055dbed73cbSSangeeta Misra 1056dbed73cbSSangeeta Misra rc = do_ioctl(kcmd, 0); 1057dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 1058dbed73cbSSangeeta Misra return (rc); 1059dbed73cbSSangeeta Misra 1060dbed73cbSSangeeta Misra for (i = 0; i < kcmd->num_servers; i++) { 1061dbed73cbSSangeeta Misra int e; 1062dbed73cbSSangeeta Misra 1063dbed73cbSSangeeta Misra if ((e = kcmd->servers[i].err) != 0) { 1064dbed73cbSSangeeta Misra logerr("i_update_ksrv_rules " 1065dbed73cbSSangeeta Misra "ioctl indicates failure: %s", strerror(e)); 1066dbed73cbSSangeeta Misra rc = ilb_map_errno2ilbstat(e); 1067dbed73cbSSangeeta Misra /* 1068dbed73cbSSangeeta Misra * if adding even a single server failed, we need to 1069dbed73cbSSangeeta Misra * roll back the whole wad. We ignore any errors and 1070dbed73cbSSangeeta Misra * return the one that was returned by the first ioctl. 1071dbed73cbSSangeeta Misra */ 1072dbed73cbSSangeeta Misra kcmd->cmd = ILB_DEL_SERVERS; 1073dbed73cbSSangeeta Misra (void) do_ioctl(kcmd, 0); 1074dbed73cbSSangeeta Misra return (rc); 1075dbed73cbSSangeeta Misra } 1076dbed73cbSSangeeta Misra } 1077dbed73cbSSangeeta Misra 1078dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1079dbed73cbSSangeeta Misra } 1080dbed73cbSSangeeta Misra 1081dbed73cbSSangeeta Misra /* convert a struct in6_addr to valstr */ 1082dbed73cbSSangeeta Misra void 1083dbed73cbSSangeeta Misra ilbd_ip_to_str(uint16_t ipversion, struct in6_addr *addr, char *valstr) 1084dbed73cbSSangeeta Misra { 1085dbed73cbSSangeeta Misra size_t vallen; 1086dbed73cbSSangeeta Misra ilb_ip_addr_t ipaddr; 1087dbed73cbSSangeeta Misra void *addrptr; 1088dbed73cbSSangeeta Misra 1089dbed73cbSSangeeta Misra vallen = (ipversion == AF_INET) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; 1090dbed73cbSSangeeta Misra 1091dbed73cbSSangeeta Misra IP_COPY_IMPL_2_CLI(addr, &ipaddr); 1092dbed73cbSSangeeta Misra addrptr = (ipversion == AF_INET) ? 1093dbed73cbSSangeeta Misra (void *)&ipaddr.ia_v4 : (void *)&ipaddr.ia_v6; 1094dbed73cbSSangeeta Misra if (inet_ntop(ipversion, (void *)addrptr, valstr, vallen == NULL)) 1095dbed73cbSSangeeta Misra logerr("ilbd_ip_to_str: inet_ntop failed"); 1096dbed73cbSSangeeta Misra return; 1097dbed73cbSSangeeta Misra 1098dbed73cbSSangeeta Misra } 1099dbed73cbSSangeeta Misra 1100dbed73cbSSangeeta Misra ilb_status_t 1101dbed73cbSSangeeta Misra ilbd_create_rule(ilb_rule_info_t *rl, int ev_port, 1102dbed73cbSSangeeta Misra const struct passwd *ps, ucred_t *ucredp) 1103dbed73cbSSangeeta Misra { 1104dbed73cbSSangeeta Misra ilb_status_t rc; 1105dbed73cbSSangeeta Misra ilbd_rule_t *irl = NULL; 1106dbed73cbSSangeeta Misra ilbd_sg_t *sg; 1107dbed73cbSSangeeta Misra ilb_rule_cmd_t *kcmd = NULL; 1108dbed73cbSSangeeta Misra 1109dbed73cbSSangeeta Misra if (ps != NULL) { 1110dbed73cbSSangeeta Misra if ((rc = ilbd_check_client_config_auth(ps)) != ILB_STATUS_OK) 1111dbed73cbSSangeeta Misra goto out; 1112dbed73cbSSangeeta Misra } 1113dbed73cbSSangeeta Misra 1114dbed73cbSSangeeta Misra if (i_find_rule_byname(rl->rl_name) != NULL) { 1115dbed73cbSSangeeta Misra logdebug("ilbd_create_rule: rule %s" 1116dbed73cbSSangeeta Misra " already exists", rl->rl_name); 1117dbed73cbSSangeeta Misra ilbd_audit_rule_event(NULL, rl, ILBD_CREATE_RULE, 1118dbed73cbSSangeeta Misra ILB_STATUS_DUP_RULE, ucredp); 1119dbed73cbSSangeeta Misra return (ILB_STATUS_DUP_RULE); 1120dbed73cbSSangeeta Misra } 1121dbed73cbSSangeeta Misra 1122dbed73cbSSangeeta Misra sg = i_find_sg_byname(rl->rl_sgname); 1123dbed73cbSSangeeta Misra if (sg == NULL) { 1124dbed73cbSSangeeta Misra logdebug("ilbd_create_rule: rule %s uses non-existent" 1125dbed73cbSSangeeta Misra " servergroup name %s", rl->rl_name, rl->rl_sgname); 1126dbed73cbSSangeeta Misra ilbd_audit_rule_event(NULL, rl, ILBD_CREATE_RULE, 1127dbed73cbSSangeeta Misra ILB_STATUS_SGUNAVAIL, ucredp); 1128dbed73cbSSangeeta Misra return (ILB_STATUS_SGUNAVAIL); 1129dbed73cbSSangeeta Misra } 1130dbed73cbSSangeeta Misra 1131dbed73cbSSangeeta Misra if ((rc = ilbd_sg_check_rule_port(sg, rl)) != ILB_STATUS_OK) { 1132dbed73cbSSangeeta Misra ilbd_audit_rule_event(NULL, rl, ILBD_CREATE_RULE, rc, ucredp); 1133dbed73cbSSangeeta Misra return (rc); 1134dbed73cbSSangeeta Misra } 1135dbed73cbSSangeeta Misra 1136dbed73cbSSangeeta Misra /* allocs and copies contents of arg (if != NULL) into new rule */ 1137dbed73cbSSangeeta Misra irl = i_alloc_ilbd_rule(rl); 1138dbed73cbSSangeeta Misra if (irl == NULL) { 1139dbed73cbSSangeeta Misra ilbd_audit_rule_event(NULL, rl, ILBD_CREATE_RULE, 1140dbed73cbSSangeeta Misra ILB_STATUS_ENOMEM, ucredp); 1141dbed73cbSSangeeta Misra return (ILB_STATUS_ENOMEM); 1142dbed73cbSSangeeta Misra } 1143dbed73cbSSangeeta Misra 1144dbed73cbSSangeeta Misra /* make sure rule's IPversion (via vip) and SG's match */ 1145dbed73cbSSangeeta Misra if (sg->isg_srvcount > 0) { 1146dbed73cbSSangeeta Misra ilbd_srv_t *srv = list_head(&sg->isg_srvlist); 1147dbed73cbSSangeeta Misra int32_t r_af = rl->rl_ipversion; 1148dbed73cbSSangeeta Misra int32_t s_af = GET_AF(&srv->isv_addr); 1149dbed73cbSSangeeta Misra 1150dbed73cbSSangeeta Misra if (r_af != s_af) { 1151dbed73cbSSangeeta Misra logdebug("address family mismatch with servergroup"); 1152dbed73cbSSangeeta Misra rc = ILB_STATUS_MISMATCHSG; 1153dbed73cbSSangeeta Misra goto out; 1154dbed73cbSSangeeta Misra } 1155dbed73cbSSangeeta Misra } 1156dbed73cbSSangeeta Misra irl->irl_sg = sg; 1157dbed73cbSSangeeta Misra 1158dbed73cbSSangeeta Misra /* Try associating the rule with the given hc oject. */ 1159dbed73cbSSangeeta Misra if (RULE_HAS_HC(irl)) { 1160dbed73cbSSangeeta Misra if ((rc = ilbd_hc_associate_rule(irl, ev_port)) != 1161dbed73cbSSangeeta Misra ILB_STATUS_OK) 1162dbed73cbSSangeeta Misra goto out; 1163dbed73cbSSangeeta Misra } 1164dbed73cbSSangeeta Misra 1165dbed73cbSSangeeta Misra /* 1166dbed73cbSSangeeta Misra * checks are done, now: 1167dbed73cbSSangeeta Misra * 1. create rule in kernel 1168dbed73cbSSangeeta Misra * 2. tell it about the backend server (which we maintain in SG) 1169dbed73cbSSangeeta Misra * 3. attach the rule in memory 1170dbed73cbSSangeeta Misra */ 1171dbed73cbSSangeeta Misra /* 1. */ 1172dbed73cbSSangeeta Misra /* allocs and copies contents of arg (if != NULL) into new rule */ 1173dbed73cbSSangeeta Misra kcmd = i_alloc_kernel_rule_cmd(irl); 1174dbed73cbSSangeeta Misra if (kcmd == NULL) { 1175dbed73cbSSangeeta Misra rc = ILB_STATUS_ENOMEM; 1176dbed73cbSSangeeta Misra goto rollback_hc; 1177dbed73cbSSangeeta Misra } 1178dbed73cbSSangeeta Misra kcmd->cmd = ILB_CREATE_RULE; 1179dbed73cbSSangeeta Misra 1180dbed73cbSSangeeta Misra rc = do_ioctl(kcmd, 0); 1181dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 1182dbed73cbSSangeeta Misra goto rollback_kcmd; 1183dbed73cbSSangeeta Misra 1184dbed73cbSSangeeta Misra /* 2. */ 1185dbed73cbSSangeeta Misra rc = i_update_ksrv_rules(kcmd->name, sg, irl); 1186dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 1187dbed73cbSSangeeta Misra goto rollback_kcmd; 1188dbed73cbSSangeeta Misra 1189dbed73cbSSangeeta Misra /* 3. */ 1190dbed73cbSSangeeta Misra (void) i_attach_rule2sg(sg, irl); 1191dbed73cbSSangeeta Misra list_insert_tail(&ilbd_rule_hlist, irl); 1192dbed73cbSSangeeta Misra 1193dbed73cbSSangeeta Misra if (ps != NULL) { 1194dbed73cbSSangeeta Misra rc = i_ilbd_save_rule(irl, ILBD_SCF_CREATE); 1195dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 1196dbed73cbSSangeeta Misra goto rollback_rule; 1197dbed73cbSSangeeta Misra } 1198dbed73cbSSangeeta Misra 1199dbed73cbSSangeeta Misra free(kcmd); 1200dbed73cbSSangeeta Misra ilbd_audit_rule_event(NULL, rl, ILBD_CREATE_RULE, 1201dbed73cbSSangeeta Misra ILB_STATUS_OK, ucredp); 1202dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1203dbed73cbSSangeeta Misra 1204dbed73cbSSangeeta Misra rollback_rule: 1205dbed73cbSSangeeta Misra /* 1206dbed73cbSSangeeta Misra * ilbd_destroy_one_rule() also frees irl, as well as dissociate 1207dbed73cbSSangeeta Misra * rule and HC, so all we need to do afterwards is free the kcmd 1208dbed73cbSSangeeta Misra * and return. 1209dbed73cbSSangeeta Misra */ 1210dbed73cbSSangeeta Misra (void) ilbd_destroy_one_rule(irl); 1211dbed73cbSSangeeta Misra ilbd_audit_rule_event(NULL, rl, ILBD_CREATE_RULE, rc, ucredp); 1212dbed73cbSSangeeta Misra free(kcmd); 1213dbed73cbSSangeeta Misra return (rc); 1214dbed73cbSSangeeta Misra 1215dbed73cbSSangeeta Misra rollback_kcmd: 1216dbed73cbSSangeeta Misra free(kcmd); 1217dbed73cbSSangeeta Misra rollback_hc: 1218dbed73cbSSangeeta Misra /* Cannot fail since the rule is just associated with the hc object. */ 1219dbed73cbSSangeeta Misra if (RULE_HAS_HC(irl)) 1220dbed73cbSSangeeta Misra (void) ilbd_hc_dissociate_rule(irl); 1221dbed73cbSSangeeta Misra out: 1222dbed73cbSSangeeta Misra ilbd_audit_rule_event(NULL, rl, ILBD_CREATE_RULE, rc, ucredp); 1223dbed73cbSSangeeta Misra free(irl); 1224dbed73cbSSangeeta Misra return (rc); 1225dbed73cbSSangeeta Misra } 1226dbed73cbSSangeeta Misra 1227dbed73cbSSangeeta Misra static uint32_t 1228dbed73cbSSangeeta Misra i_flags_d2k(int f) 1229dbed73cbSSangeeta Misra { 1230dbed73cbSSangeeta Misra uint32_t r = 0; 1231dbed73cbSSangeeta Misra 1232dbed73cbSSangeeta Misra if (ILB_IS_SRV_ENABLED(f)) 1233dbed73cbSSangeeta Misra r |= ILB_SERVER_ENABLED; 1234dbed73cbSSangeeta Misra /* more as they are defined */ 1235dbed73cbSSangeeta Misra 1236dbed73cbSSangeeta Misra return (r); 1237dbed73cbSSangeeta Misra } 1238dbed73cbSSangeeta Misra 1239dbed73cbSSangeeta Misra /* 1240dbed73cbSSangeeta Misra * walk the list of rules and add srv to the *kernel* rule 1241dbed73cbSSangeeta Misra * (this is a list of rules hanging off of a server group) 1242dbed73cbSSangeeta Misra */ 1243dbed73cbSSangeeta Misra ilb_status_t 1244dbed73cbSSangeeta Misra i_add_srv2krules(list_t *rlist, ilb_sg_srv_t *srv, int ev_port) 1245dbed73cbSSangeeta Misra { 1246dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 1247dbed73cbSSangeeta Misra ilbd_rule_t *rl, *del_rl; 1248dbed73cbSSangeeta Misra ilb_servers_info_cmd_t kcmd; 1249dbed73cbSSangeeta Misra ilb_servers_cmd_t del_kcmd; 1250dbed73cbSSangeeta Misra 1251dbed73cbSSangeeta Misra kcmd.cmd = ILB_ADD_SERVERS; 1252dbed73cbSSangeeta Misra kcmd.num_servers = 1; 1253dbed73cbSSangeeta Misra kcmd.servers[0].err = 0; 1254dbed73cbSSangeeta Misra kcmd.servers[0].addr = srv->sgs_addr; 1255dbed73cbSSangeeta Misra kcmd.servers[0].flags = i_flags_d2k(srv->sgs_flags); 1256dbed73cbSSangeeta Misra (void) strlcpy(kcmd.servers[0].name, srv->sgs_srvID, 1257dbed73cbSSangeeta Misra sizeof (kcmd.servers[0].name)); 1258dbed73cbSSangeeta Misra 1259dbed73cbSSangeeta Misra /* 1260dbed73cbSSangeeta Misra * a note about rollback: since we need to start rollback with the 1261dbed73cbSSangeeta Misra * current list element in some case, and with the previous one 1262dbed73cbSSangeeta Misra * in others, we must "go back" in this latter case before 1263dbed73cbSSangeeta Misra * we jump to the rollback code. 1264dbed73cbSSangeeta Misra */ 1265dbed73cbSSangeeta Misra for (rl = list_head(rlist); rl != NULL; rl = list_next(rlist, rl)) { 1266dbed73cbSSangeeta Misra (void) strlcpy(kcmd.name, rl->irl_name, sizeof (kcmd.name)); 1267dbed73cbSSangeeta Misra /* 1268dbed73cbSSangeeta Misra * sgs_minport == 0 means "no port specified"; this 1269dbed73cbSSangeeta Misra * indicates that the server matches anything the rule 1270dbed73cbSSangeeta Misra * provides. 1271dbed73cbSSangeeta Misra * NOTE: this can be different for different rules 1272dbed73cbSSangeeta Misra * using the same server group, therefore we don't modify 1273dbed73cbSSangeeta Misra * this information in the servergroup, but *only* in 1274dbed73cbSSangeeta Misra * the kernel's rule. 1275dbed73cbSSangeeta Misra */ 1276dbed73cbSSangeeta Misra if (srv->sgs_minport == 0) { 1277dbed73cbSSangeeta Misra kcmd.servers[0].min_port = rl->irl_minport; 1278dbed73cbSSangeeta Misra kcmd.servers[0].max_port = rl->irl_maxport; 1279dbed73cbSSangeeta Misra } else { 1280dbed73cbSSangeeta Misra kcmd.servers[0].min_port = srv->sgs_minport; 1281dbed73cbSSangeeta Misra kcmd.servers[0].max_port = srv->sgs_maxport; 1282dbed73cbSSangeeta Misra } 1283dbed73cbSSangeeta Misra rc = do_ioctl((void *)&kcmd, 0); 1284dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 1285dbed73cbSSangeeta Misra logdebug("i_add_srv2krules: do_ioctl call failed"); 1286dbed73cbSSangeeta Misra del_rl = list_prev(rlist, rl); 1287dbed73cbSSangeeta Misra goto rollback; 1288dbed73cbSSangeeta Misra } 1289dbed73cbSSangeeta Misra 1290dbed73cbSSangeeta Misra /* 1291dbed73cbSSangeeta Misra * if ioctl() returns != 0, it doesn't perform the copyout 1292dbed73cbSSangeeta Misra * necessary to indicate *which* server failed (we could be 1293dbed73cbSSangeeta Misra * adding more than one); therefore we must check this 1294dbed73cbSSangeeta Misra * 'err' field even if ioctl() returns 0. 1295dbed73cbSSangeeta Misra */ 1296dbed73cbSSangeeta Misra if (kcmd.servers[0].err != 0) { 1297dbed73cbSSangeeta Misra logerr("i_add_srv2krules: SIOCILB ioctl returned" 1298dbed73cbSSangeeta Misra " error %d", kcmd.servers[0].err); 1299dbed73cbSSangeeta Misra rc = ilb_map_errno2ilbstat(kcmd.servers[0].err); 1300dbed73cbSSangeeta Misra del_rl = list_prev(rlist, rl); 1301dbed73cbSSangeeta Misra goto rollback; 1302dbed73cbSSangeeta Misra } 1303dbed73cbSSangeeta Misra if (RULE_HAS_HC(rl)) { 1304dbed73cbSSangeeta Misra if ((rc = ilbd_hc_add_server(rl, srv, ev_port)) != 1305dbed73cbSSangeeta Misra ILB_STATUS_OK) { 1306dbed73cbSSangeeta Misra logerr("i_add_srv2krules: cannot start timer " 1307dbed73cbSSangeeta Misra " for rules %s server %s", rl->irl_name, 1308dbed73cbSSangeeta Misra srv->sgs_srvID); 1309dbed73cbSSangeeta Misra 1310dbed73cbSSangeeta Misra del_rl = rl; 1311dbed73cbSSangeeta Misra goto rollback; 1312dbed73cbSSangeeta Misra } 1313dbed73cbSSangeeta Misra } 1314dbed73cbSSangeeta Misra } 1315dbed73cbSSangeeta Misra 1316dbed73cbSSangeeta Misra return (rc); 1317dbed73cbSSangeeta Misra 1318dbed73cbSSangeeta Misra rollback: 1319dbed73cbSSangeeta Misra /* 1320dbed73cbSSangeeta Misra * this is almost, but not quite, the same as i_rem_srv_frm_krules() 1321dbed73cbSSangeeta Misra * therefore we keep it seperate. 1322dbed73cbSSangeeta Misra */ 1323dbed73cbSSangeeta Misra del_kcmd.cmd = ILB_DEL_SERVERS; 1324dbed73cbSSangeeta Misra del_kcmd.num_servers = 1; 1325dbed73cbSSangeeta Misra del_kcmd.servers[0].addr = srv->sgs_addr; 1326dbed73cbSSangeeta Misra while (del_rl != NULL) { 1327dbed73cbSSangeeta Misra if (RULE_HAS_HC(del_rl)) 1328dbed73cbSSangeeta Misra (void) ilbd_hc_del_server(del_rl, srv); 1329dbed73cbSSangeeta Misra (void) strlcpy(del_kcmd.name, del_rl->irl_name, 1330dbed73cbSSangeeta Misra sizeof (del_kcmd.name)); 1331dbed73cbSSangeeta Misra (void) do_ioctl((void *)&del_kcmd, 0); 1332dbed73cbSSangeeta Misra del_rl = list_prev(rlist, del_rl); 1333dbed73cbSSangeeta Misra } 1334dbed73cbSSangeeta Misra 1335dbed73cbSSangeeta Misra return (rc); 1336dbed73cbSSangeeta Misra } 1337dbed73cbSSangeeta Misra 1338dbed73cbSSangeeta Misra /* 1339dbed73cbSSangeeta Misra * ev_port is only used for rollback purposes in this function 1340dbed73cbSSangeeta Misra */ 1341dbed73cbSSangeeta Misra ilb_status_t 1342dbed73cbSSangeeta Misra i_rem_srv_frm_krules(list_t *rlist, ilb_sg_srv_t *srv, int ev_port) 1343dbed73cbSSangeeta Misra { 1344dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 1345dbed73cbSSangeeta Misra ilbd_rule_t *rl, *add_rl; 1346dbed73cbSSangeeta Misra ilb_servers_cmd_t kcmd; 1347dbed73cbSSangeeta Misra ilb_servers_info_cmd_t add_kcmd; 1348dbed73cbSSangeeta Misra 1349dbed73cbSSangeeta Misra kcmd.cmd = ILB_DEL_SERVERS; 1350dbed73cbSSangeeta Misra kcmd.num_servers = 1; 1351dbed73cbSSangeeta Misra kcmd.servers[0].err = 0; 1352dbed73cbSSangeeta Misra kcmd.servers[0].addr = srv->sgs_addr; 1353dbed73cbSSangeeta Misra 1354dbed73cbSSangeeta Misra for (rl = list_head(rlist); rl != NULL; rl = list_next(rlist, rl)) { 1355dbed73cbSSangeeta Misra (void) strlcpy(kcmd.name, rl->irl_name, sizeof (kcmd.name)); 1356dbed73cbSSangeeta Misra rc = do_ioctl((void *)&kcmd, 0); 1357dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 1358dbed73cbSSangeeta Misra logdebug("i_rem_srv_frm_krules: do_ioctl" 1359dbed73cbSSangeeta Misra "call failed"); 1360dbed73cbSSangeeta Misra add_rl = list_prev(rlist, rl); 1361dbed73cbSSangeeta Misra goto rollback; 1362dbed73cbSSangeeta Misra } 1363dbed73cbSSangeeta Misra /* 1364dbed73cbSSangeeta Misra * if ioctl() returns != 0, it doesn't perform the copyout 1365dbed73cbSSangeeta Misra * necessary to indicate *which* server failed (we could be 1366dbed73cbSSangeeta Misra * removing more than one); therefore we must check this 1367dbed73cbSSangeeta Misra * 'err' field even if ioctl() returns 0. 1368dbed73cbSSangeeta Misra */ 1369dbed73cbSSangeeta Misra if (kcmd.servers[0].err != 0) { 1370dbed73cbSSangeeta Misra logerr("i_rem_srv_frm_krules: SIOCILB ioctl" 1371dbed73cbSSangeeta Misra " returned error %s", 1372dbed73cbSSangeeta Misra strerror(kcmd.servers[0].err)); 1373dbed73cbSSangeeta Misra rc = ilb_map_errno2ilbstat(kcmd.servers[0].err); 1374dbed73cbSSangeeta Misra add_rl = list_prev(rlist, rl); 1375dbed73cbSSangeeta Misra goto rollback; 1376dbed73cbSSangeeta Misra } 1377dbed73cbSSangeeta Misra if (RULE_HAS_HC(rl) && 1378dbed73cbSSangeeta Misra (rc = ilbd_hc_del_server(rl, srv)) != ILB_STATUS_OK) { 1379dbed73cbSSangeeta Misra logerr("i_rem_srv_frm_krules: cannot delete " 1380dbed73cbSSangeeta Misra "timer for rules %s server %s", rl->irl_name, 1381dbed73cbSSangeeta Misra srv->sgs_srvID); 1382dbed73cbSSangeeta Misra add_rl = rl; 1383dbed73cbSSangeeta Misra goto rollback; 1384dbed73cbSSangeeta Misra } 1385dbed73cbSSangeeta Misra } 1386dbed73cbSSangeeta Misra 1387dbed73cbSSangeeta Misra return (rc); 1388dbed73cbSSangeeta Misra 1389dbed73cbSSangeeta Misra rollback: 1390dbed73cbSSangeeta Misra /* Don't do roll back if ev_port == -1. */ 1391dbed73cbSSangeeta Misra if (ev_port == -1) 1392dbed73cbSSangeeta Misra return (rc); 1393dbed73cbSSangeeta Misra 1394dbed73cbSSangeeta Misra add_kcmd.cmd = ILB_ADD_SERVERS; 1395dbed73cbSSangeeta Misra add_kcmd.num_servers = 1; 1396dbed73cbSSangeeta Misra add_kcmd.servers[0].err = 0; 1397dbed73cbSSangeeta Misra add_kcmd.servers[0].addr = srv->sgs_addr; 1398dbed73cbSSangeeta Misra add_kcmd.servers[0].flags = i_flags_d2k(srv->sgs_flags); 1399dbed73cbSSangeeta Misra (void) strlcpy(add_kcmd.servers[0].name, srv->sgs_srvID, 1400dbed73cbSSangeeta Misra sizeof (add_kcmd.servers[0].name)); 1401dbed73cbSSangeeta Misra while (add_rl != NULL) { 1402dbed73cbSSangeeta Misra if (srv->sgs_minport == 0) { 1403dbed73cbSSangeeta Misra add_kcmd.servers[0].min_port = add_rl->irl_minport; 1404dbed73cbSSangeeta Misra add_kcmd.servers[0].max_port = add_rl->irl_maxport; 1405dbed73cbSSangeeta Misra } else { 1406dbed73cbSSangeeta Misra add_kcmd.servers[0].min_port = srv->sgs_minport; 1407dbed73cbSSangeeta Misra add_kcmd.servers[0].max_port = srv->sgs_maxport; 1408dbed73cbSSangeeta Misra } 1409dbed73cbSSangeeta Misra if (RULE_HAS_HC(add_rl)) 1410dbed73cbSSangeeta Misra (void) ilbd_hc_add_server(add_rl, srv, ev_port); 1411dbed73cbSSangeeta Misra (void) strlcpy(add_kcmd.name, add_rl->irl_name, 1412dbed73cbSSangeeta Misra sizeof (add_kcmd.name)); 1413dbed73cbSSangeeta Misra (void) do_ioctl((void *)&add_kcmd, 0); 1414dbed73cbSSangeeta Misra add_rl = list_prev(rlist, add_rl); 1415dbed73cbSSangeeta Misra } 1416dbed73cbSSangeeta Misra 1417dbed73cbSSangeeta Misra return (rc); 1418dbed73cbSSangeeta Misra } 1419