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 <sys/types.h> 30dbed73cbSSangeeta Misra #include <sys/socket.h> 31dbed73cbSSangeeta Misra #include <sys/list.h> 32dbed73cbSSangeeta Misra #include <assert.h> 33dbed73cbSSangeeta Misra #include <errno.h> 34dbed73cbSSangeeta Misra #include <libilb.h> 35dbed73cbSSangeeta Misra #include <net/if.h> 36dbed73cbSSangeeta Misra #include <inet/ilb.h> 37dbed73cbSSangeeta Misra #include <netinet/in.h> 38dbed73cbSSangeeta Misra #include <arpa/inet.h> 39dbed73cbSSangeeta Misra #include "libilb_impl.h" 40dbed73cbSSangeeta Misra #include "ilbd.h" 41dbed73cbSSangeeta Misra 42dbed73cbSSangeeta Misra typedef enum { 43dbed73cbSSangeeta Misra not_searched, 44dbed73cbSSangeeta Misra stop_found, 45dbed73cbSSangeeta Misra cont_search, 46dbed73cbSSangeeta Misra fail_search 47dbed73cbSSangeeta Misra } srch_ind_t; 48dbed73cbSSangeeta Misra 49dbed73cbSSangeeta Misra static list_t ilbd_sg_hlist; 50dbed73cbSSangeeta Misra 51dbed73cbSSangeeta Misra static ilb_status_t i_delete_srv(ilbd_sg_t *, ilbd_srv_t *, int); 52dbed73cbSSangeeta Misra static void i_ilbd_free_srvID(ilbd_sg_t *, int32_t); 53dbed73cbSSangeeta Misra 54dbed73cbSSangeeta Misra /* Last parameter to pass to i_find_srv(), specifying the matching mode */ 55dbed73cbSSangeeta Misra #define MODE_ADDR 1 56dbed73cbSSangeeta Misra #define MODE_SRVID 2 57dbed73cbSSangeeta Misra 58dbed73cbSSangeeta Misra static ilbd_srv_t *i_find_srv(list_t *, ilb_sg_srv_t *, int); 59dbed73cbSSangeeta Misra 60dbed73cbSSangeeta Misra void 61dbed73cbSSangeeta Misra i_setup_sg_hlist(void) 62dbed73cbSSangeeta Misra { 63dbed73cbSSangeeta Misra list_create(&ilbd_sg_hlist, sizeof (ilbd_sg_t), 64dbed73cbSSangeeta Misra offsetof(ilbd_sg_t, isg_link)); 65dbed73cbSSangeeta Misra } 66dbed73cbSSangeeta Misra 67dbed73cbSSangeeta Misra /* 68dbed73cbSSangeeta Misra * allocate storage for a daemon-internal server group, init counters 69dbed73cbSSangeeta Misra */ 70dbed73cbSSangeeta Misra static ilbd_sg_t * 71dbed73cbSSangeeta Misra i_ilbd_alloc_sg(char *name) 72dbed73cbSSangeeta Misra { 73dbed73cbSSangeeta Misra ilbd_sg_t *d_sg; 74dbed73cbSSangeeta Misra 75dbed73cbSSangeeta Misra d_sg = calloc(sizeof (*d_sg), 1); 76dbed73cbSSangeeta Misra if (d_sg == NULL) 77dbed73cbSSangeeta Misra goto out; 78dbed73cbSSangeeta Misra 79dbed73cbSSangeeta Misra (void) strlcpy(d_sg->isg_name, name, sizeof (d_sg->isg_name)); 80dbed73cbSSangeeta Misra 81dbed73cbSSangeeta Misra list_create(&d_sg->isg_srvlist, sizeof (ilbd_srv_t), 82dbed73cbSSangeeta Misra offsetof(ilbd_srv_t, isv_srv_link)); 83dbed73cbSSangeeta Misra list_create(&d_sg->isg_rulelist, sizeof (ilbd_rule_t), 84dbed73cbSSangeeta Misra offsetof(ilbd_rule_t, irl_sglink)); 85dbed73cbSSangeeta Misra 86dbed73cbSSangeeta Misra list_insert_tail(&ilbd_sg_hlist, d_sg); 87dbed73cbSSangeeta Misra out: 88dbed73cbSSangeeta Misra return (d_sg); 89dbed73cbSSangeeta Misra } 90dbed73cbSSangeeta Misra 91dbed73cbSSangeeta Misra static ilb_status_t 92dbed73cbSSangeeta Misra i_ilbd_save_sg(ilbd_sg_t *d_sg, ilbd_scf_cmd_t scf_cmd, const char *prop_name, 93dbed73cbSSangeeta Misra char *valstr) 94dbed73cbSSangeeta Misra { 95dbed73cbSSangeeta Misra switch (scf_cmd) { 96dbed73cbSSangeeta Misra case ILBD_SCF_CREATE: 97dbed73cbSSangeeta Misra return (ilbd_create_pg(ILBD_SCF_SG, (void *)d_sg)); 98dbed73cbSSangeeta Misra case ILBD_SCF_DESTROY: 99dbed73cbSSangeeta Misra return (ilbd_destroy_pg(ILBD_SCF_SG, d_sg->isg_name)); 100dbed73cbSSangeeta Misra case ILBD_SCF_ENABLE_DISABLE: 101dbed73cbSSangeeta Misra if (prop_name == NULL) 102dbed73cbSSangeeta Misra return (ILB_STATUS_EINVAL); 103dbed73cbSSangeeta Misra return (ilbd_change_prop(ILBD_SCF_SG, d_sg->isg_name, 104dbed73cbSSangeeta Misra prop_name, valstr)); 105dbed73cbSSangeeta Misra default: 106dbed73cbSSangeeta Misra logdebug("i_ilbd_save_sg: invalid scf cmd %d", scf_cmd); 107dbed73cbSSangeeta Misra return (ILB_STATUS_EINVAL); 108dbed73cbSSangeeta Misra } 109dbed73cbSSangeeta Misra } 110dbed73cbSSangeeta Misra 111dbed73cbSSangeeta Misra ilb_status_t 112dbed73cbSSangeeta Misra i_attach_rule2sg(ilbd_sg_t *sg, ilbd_rule_t *irl) 113dbed73cbSSangeeta Misra { 114dbed73cbSSangeeta Misra /* assert: the same rule is attached to any sg only once */ 115dbed73cbSSangeeta Misra list_insert_tail(&sg->isg_rulelist, irl); 116dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 117dbed73cbSSangeeta Misra } 118dbed73cbSSangeeta Misra 119dbed73cbSSangeeta Misra static void 120dbed73cbSSangeeta Misra i_ilbd_free_sg(ilbd_sg_t *sg) 121dbed73cbSSangeeta Misra { 122dbed73cbSSangeeta Misra ilbd_srv_t *tmp_srv; 123dbed73cbSSangeeta Misra 124dbed73cbSSangeeta Misra if (sg == NULL) 125dbed73cbSSangeeta Misra return; 126dbed73cbSSangeeta Misra list_remove(&ilbd_sg_hlist, sg); 127dbed73cbSSangeeta Misra while ((tmp_srv = list_remove_tail(&sg->isg_srvlist)) != NULL) { 128dbed73cbSSangeeta Misra i_ilbd_free_srvID(sg, tmp_srv->isv_id); 129dbed73cbSSangeeta Misra free(tmp_srv); 130dbed73cbSSangeeta Misra sg->isg_srvcount--; 131dbed73cbSSangeeta Misra } 132dbed73cbSSangeeta Misra free(sg); 133dbed73cbSSangeeta Misra } 134dbed73cbSSangeeta Misra 135dbed73cbSSangeeta Misra ilbd_sg_t * 136dbed73cbSSangeeta Misra i_find_sg_byname(const char *name) 137dbed73cbSSangeeta Misra { 138dbed73cbSSangeeta Misra ilbd_sg_t *sg; 139dbed73cbSSangeeta Misra 140dbed73cbSSangeeta Misra /* find position of sg in list */ 141dbed73cbSSangeeta Misra for (sg = list_head(&ilbd_sg_hlist); sg != NULL; 142dbed73cbSSangeeta Misra sg = list_next(&ilbd_sg_hlist, sg)) { 143dbed73cbSSangeeta Misra if (strncmp(sg->isg_name, name, sizeof (sg->isg_name)) == 0) 144dbed73cbSSangeeta Misra return (sg); 145dbed73cbSSangeeta Misra } 146dbed73cbSSangeeta Misra return (sg); 147dbed73cbSSangeeta Misra } 148dbed73cbSSangeeta Misra 149dbed73cbSSangeeta Misra /* 150dbed73cbSSangeeta Misra * Generates an audit record for enable-server, disable-server, remove-server 151dbed73cbSSangeeta Misra * delete-servergroup, create-servergroup and add-server subcommands. 152dbed73cbSSangeeta Misra */ 153dbed73cbSSangeeta Misra static void 154dbed73cbSSangeeta Misra ilbd_audit_server_event(audit_sg_event_data_t *data, 155dbed73cbSSangeeta Misra ilbd_cmd_t cmd, ilb_status_t rc, ucred_t *ucredp) 156dbed73cbSSangeeta Misra { 157dbed73cbSSangeeta Misra adt_session_data_t *ah; 158dbed73cbSSangeeta Misra adt_event_data_t *event; 159dbed73cbSSangeeta Misra au_event_t flag; 160dbed73cbSSangeeta Misra int audit_error; 161dbed73cbSSangeeta Misra 162dbed73cbSSangeeta Misra if ((ucredp == NULL) && ((cmd == ILBD_ADD_SERVER_TO_GROUP) || 163dbed73cbSSangeeta Misra (cmd == ILBD_CREATE_SERVERGROUP))) { 164dbed73cbSSangeeta Misra /* 165dbed73cbSSangeeta Misra * We came here from the path where ilbd is 166dbed73cbSSangeeta Misra * incorporating the ILB configuration from 167dbed73cbSSangeeta Misra * SCF. In that case, we skip auditing 168dbed73cbSSangeeta Misra */ 169dbed73cbSSangeeta Misra return; 170dbed73cbSSangeeta Misra } 171dbed73cbSSangeeta Misra 172dbed73cbSSangeeta Misra if (adt_start_session(&ah, NULL, 0) != 0) { 173dbed73cbSSangeeta Misra logerr("ilbd_audit_server_event: adt_start_session failed"); 174dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 175dbed73cbSSangeeta Misra } 176dbed73cbSSangeeta Misra 177dbed73cbSSangeeta Misra if (adt_set_from_ucred(ah, ucredp, ADT_NEW) != 0) { 178dbed73cbSSangeeta Misra (void) adt_end_session(ah); 179dbed73cbSSangeeta Misra logerr("ilbd_audit_server_event: adt_set_from_ucred failed"); 180dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 181dbed73cbSSangeeta Misra } 182dbed73cbSSangeeta Misra 183dbed73cbSSangeeta Misra if (cmd == ILBD_ENABLE_SERVER) 184dbed73cbSSangeeta Misra flag = ADT_ilb_enable_server; 185dbed73cbSSangeeta Misra else if (cmd == ILBD_DISABLE_SERVER) 186dbed73cbSSangeeta Misra flag = ADT_ilb_disable_server; 187dbed73cbSSangeeta Misra else if (cmd == ILBD_REM_SERVER_FROM_GROUP) 188dbed73cbSSangeeta Misra flag = ADT_ilb_remove_server; 189dbed73cbSSangeeta Misra else if (cmd == ILBD_ADD_SERVER_TO_GROUP) 190dbed73cbSSangeeta Misra flag = ADT_ilb_add_server; 191dbed73cbSSangeeta Misra else if (cmd == ILBD_CREATE_SERVERGROUP) 192dbed73cbSSangeeta Misra flag = ADT_ilb_create_servergroup; 193dbed73cbSSangeeta Misra else if (cmd == ILBD_DESTROY_SERVERGROUP) 194dbed73cbSSangeeta Misra flag = ADT_ilb_delete_servergroup; 195dbed73cbSSangeeta Misra 196dbed73cbSSangeeta Misra if ((event = adt_alloc_event(ah, flag)) == NULL) { 197dbed73cbSSangeeta Misra logerr("ilbd_audit_server_event: adt_alloc_event failed"); 198dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 199dbed73cbSSangeeta Misra } 200dbed73cbSSangeeta Misra (void) memset((char *)event, 0, sizeof (adt_event_data_t)); 201dbed73cbSSangeeta Misra 202dbed73cbSSangeeta Misra switch (cmd) { 203dbed73cbSSangeeta Misra case ILBD_ENABLE_SERVER: 204dbed73cbSSangeeta Misra event->adt_ilb_enable_server.auth_used = 205dbed73cbSSangeeta Misra NET_ILB_ENABLE_AUTH; 206dbed73cbSSangeeta Misra event->adt_ilb_enable_server.server_id = 207dbed73cbSSangeeta Misra data->ed_serverid; 208*5df82708SSangeeta Misra event->adt_ilb_enable_server.server_ipaddress_type = 209*5df82708SSangeeta Misra data->ed_ipaddr_type; 210*5df82708SSangeeta Misra (void) memcpy(event->adt_ilb_enable_server.server_ipaddress, 211*5df82708SSangeeta Misra data->ed_server_address, 212*5df82708SSangeeta Misra (sizeof (data->ed_server_address))); 213dbed73cbSSangeeta Misra break; 214dbed73cbSSangeeta Misra case ILBD_DISABLE_SERVER: 215dbed73cbSSangeeta Misra event->adt_ilb_disable_server.auth_used = 216dbed73cbSSangeeta Misra NET_ILB_ENABLE_AUTH; 217dbed73cbSSangeeta Misra event->adt_ilb_disable_server.server_id = 218dbed73cbSSangeeta Misra data->ed_serverid; 219*5df82708SSangeeta Misra event->adt_ilb_disable_server.server_ipaddress_type = 220*5df82708SSangeeta Misra data->ed_ipaddr_type; 221*5df82708SSangeeta Misra (void) memcpy(event->adt_ilb_disable_server.server_ipaddress, 222*5df82708SSangeeta Misra data->ed_server_address, 223*5df82708SSangeeta Misra (sizeof (data->ed_server_address))); 224dbed73cbSSangeeta Misra break; 225dbed73cbSSangeeta Misra case ILBD_REM_SERVER_FROM_GROUP: 226dbed73cbSSangeeta Misra event->adt_ilb_remove_server.auth_used = 227dbed73cbSSangeeta Misra NET_ILB_CONFIG_AUTH; 228dbed73cbSSangeeta Misra event->adt_ilb_remove_server.server_id = 229dbed73cbSSangeeta Misra data->ed_serverid; 230dbed73cbSSangeeta Misra event->adt_ilb_remove_server.server_group = data->ed_sgroup; 231*5df82708SSangeeta Misra event->adt_ilb_remove_server.server_ipaddress_type = 232*5df82708SSangeeta Misra data->ed_ipaddr_type; 233*5df82708SSangeeta Misra (void) memcpy(event->adt_ilb_remove_server.server_ipaddress, 234*5df82708SSangeeta Misra data->ed_server_address, 235*5df82708SSangeeta Misra (sizeof (data->ed_server_address))); 236dbed73cbSSangeeta Misra break; 237dbed73cbSSangeeta Misra case ILBD_CREATE_SERVERGROUP: 238dbed73cbSSangeeta Misra event->adt_ilb_create_servergroup.auth_used = 239dbed73cbSSangeeta Misra NET_ILB_CONFIG_AUTH; 240dbed73cbSSangeeta Misra event->adt_ilb_create_servergroup.server_group = 241dbed73cbSSangeeta Misra data->ed_sgroup; 242dbed73cbSSangeeta Misra break; 243dbed73cbSSangeeta Misra case ILBD_ADD_SERVER_TO_GROUP: 244dbed73cbSSangeeta Misra event->adt_ilb_add_server.auth_used = 245dbed73cbSSangeeta Misra NET_ILB_CONFIG_AUTH; 246*5df82708SSangeeta Misra event->adt_ilb_add_server.server_ipaddress_type = 247*5df82708SSangeeta Misra data->ed_ipaddr_type; 248*5df82708SSangeeta Misra (void) memcpy(event->adt_ilb_add_server.server_ipaddress, 249*5df82708SSangeeta Misra data->ed_server_address, 250*5df82708SSangeeta Misra (sizeof (data->ed_server_address))); 251dbed73cbSSangeeta Misra event->adt_ilb_add_server.server_id = 252dbed73cbSSangeeta Misra data->ed_serverid; 253dbed73cbSSangeeta Misra event->adt_ilb_add_server.server_group = 254dbed73cbSSangeeta Misra data->ed_sgroup; 255dbed73cbSSangeeta Misra event->adt_ilb_add_server.server_minport = 256dbed73cbSSangeeta Misra ntohs(data->ed_minport); 257dbed73cbSSangeeta Misra event->adt_ilb_add_server.server_maxport = 258dbed73cbSSangeeta Misra ntohs(data->ed_maxport); 259dbed73cbSSangeeta Misra break; 260dbed73cbSSangeeta Misra case ILBD_DESTROY_SERVERGROUP: 261dbed73cbSSangeeta Misra event->adt_ilb_delete_servergroup.auth_used = 262dbed73cbSSangeeta Misra NET_ILB_CONFIG_AUTH; 263dbed73cbSSangeeta Misra event->adt_ilb_delete_servergroup.server_group = 264dbed73cbSSangeeta Misra data->ed_sgroup; 265dbed73cbSSangeeta Misra break; 266dbed73cbSSangeeta Misra } 267dbed73cbSSangeeta Misra 268dbed73cbSSangeeta Misra /* Fill in success/failure */ 269dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) { 270dbed73cbSSangeeta Misra if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) { 271dbed73cbSSangeeta Misra logerr("ilbd_audit_server_event:" 272dbed73cbSSangeeta Misra " adt_put_event failed"); 273dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 274dbed73cbSSangeeta Misra } 275dbed73cbSSangeeta Misra } else { 276dbed73cbSSangeeta Misra audit_error = ilberror2auditerror(rc); 277dbed73cbSSangeeta Misra if (adt_put_event(event, ADT_FAILURE, audit_error) != 0) { 278dbed73cbSSangeeta Misra logerr("ilbd_audit_server_event:" 279dbed73cbSSangeeta Misra " adt_put_event failed"); 280dbed73cbSSangeeta Misra exit(EXIT_FAILURE); 281dbed73cbSSangeeta Misra } 282dbed73cbSSangeeta Misra } 283dbed73cbSSangeeta Misra adt_free_event(event); 284dbed73cbSSangeeta Misra (void) adt_end_session(ah); 285dbed73cbSSangeeta Misra } 286dbed73cbSSangeeta Misra 287dbed73cbSSangeeta Misra ilb_status_t 288dbed73cbSSangeeta Misra ilbd_destroy_sg(const char *sg_name, const struct passwd *ps, 289dbed73cbSSangeeta Misra ucred_t *ucredp) 290dbed73cbSSangeeta Misra { 291dbed73cbSSangeeta Misra ilb_status_t rc; 292dbed73cbSSangeeta Misra ilbd_sg_t *tmp_sg; 293dbed73cbSSangeeta Misra audit_sg_event_data_t audit_sg_data; 294dbed73cbSSangeeta Misra 295dbed73cbSSangeeta Misra (void) memset(&audit_sg_data, 0, sizeof (audit_sg_event_data_t)); 296dbed73cbSSangeeta Misra audit_sg_data.ed_sgroup = (char *)sg_name; 297dbed73cbSSangeeta Misra 298dbed73cbSSangeeta Misra rc = ilbd_check_client_config_auth(ps); 299dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 300dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 301dbed73cbSSangeeta Misra ILBD_DESTROY_SERVERGROUP, rc, ucredp); 302dbed73cbSSangeeta Misra return (rc); 303dbed73cbSSangeeta Misra } 304dbed73cbSSangeeta Misra 305dbed73cbSSangeeta Misra tmp_sg = i_find_sg_byname(sg_name); 306dbed73cbSSangeeta Misra if (tmp_sg == NULL) { 307dbed73cbSSangeeta Misra logdebug("ilbd_destroy_sg: cannot find specified server" 308dbed73cbSSangeeta Misra " group %s", sg_name); 309dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 310dbed73cbSSangeeta Misra ILBD_DESTROY_SERVERGROUP, ILB_STATUS_SGUNAVAIL, ucredp); 311dbed73cbSSangeeta Misra return (ILB_STATUS_SGUNAVAIL); 312dbed73cbSSangeeta Misra } 313dbed73cbSSangeeta Misra 314dbed73cbSSangeeta Misra /* 315dbed73cbSSangeeta Misra * we only destroy SGs that don't have any rules associated with 316dbed73cbSSangeeta Misra * them anymore. 317dbed73cbSSangeeta Misra */ 318dbed73cbSSangeeta Misra if (list_head(&tmp_sg->isg_rulelist) != NULL) { 319dbed73cbSSangeeta Misra logdebug("ilbd_destroy_sg: server group %s has rules" 320dbed73cbSSangeeta Misra " associated with it and thus cannot be" 321dbed73cbSSangeeta Misra " removed", tmp_sg->isg_name); 322dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 323dbed73cbSSangeeta Misra ILBD_DESTROY_SERVERGROUP, ILB_STATUS_SGINUSE, ucredp); 324dbed73cbSSangeeta Misra return (ILB_STATUS_SGINUSE); 325dbed73cbSSangeeta Misra } 326dbed73cbSSangeeta Misra 327dbed73cbSSangeeta Misra if (ps != NULL) { 328dbed73cbSSangeeta Misra rc = i_ilbd_save_sg(tmp_sg, ILBD_SCF_DESTROY, NULL, NULL); 329dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 330dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 331dbed73cbSSangeeta Misra ILBD_DESTROY_SERVERGROUP, rc, ucredp); 332dbed73cbSSangeeta Misra return (rc); 333dbed73cbSSangeeta Misra } 334dbed73cbSSangeeta Misra } 335dbed73cbSSangeeta Misra i_ilbd_free_sg(tmp_sg); 336dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, ILBD_DESTROY_SERVERGROUP, 337dbed73cbSSangeeta Misra rc, ucredp); 338dbed73cbSSangeeta Misra return (rc); 339dbed73cbSSangeeta Misra } 340dbed73cbSSangeeta Misra 341dbed73cbSSangeeta Misra /* ARGSUSED */ 342dbed73cbSSangeeta Misra /* 343dbed73cbSSangeeta Misra * Parameter ev_port is not used but has to have for read persistent configure 344dbed73cbSSangeeta Misra * ilbd_create_sg(), ilbd_create_hc() and ilbd_create_rule() are callbacks 345dbed73cbSSangeeta Misra * for ilbd_scf_instance_walk_pg() which requires the same signature. 346dbed73cbSSangeeta Misra */ 347dbed73cbSSangeeta Misra ilb_status_t 348dbed73cbSSangeeta Misra ilbd_create_sg(ilb_sg_info_t *sg, int ev_port, const struct passwd *ps, 349dbed73cbSSangeeta Misra ucred_t *ucredp) 350dbed73cbSSangeeta Misra { 351dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 352dbed73cbSSangeeta Misra ilbd_sg_t *d_sg; 353dbed73cbSSangeeta Misra audit_sg_event_data_t audit_sg_data; 354dbed73cbSSangeeta Misra 355dbed73cbSSangeeta Misra (void) memset(&audit_sg_data, 0, sizeof (audit_sg_event_data_t)); 356dbed73cbSSangeeta Misra audit_sg_data.ed_sgroup = sg->sg_name; 357dbed73cbSSangeeta Misra 358dbed73cbSSangeeta Misra if (ps != NULL) { 359dbed73cbSSangeeta Misra rc = ilbd_check_client_config_auth(ps); 360dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 361dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 362dbed73cbSSangeeta Misra ILBD_CREATE_SERVERGROUP, rc, ucredp); 363dbed73cbSSangeeta Misra return (rc); 364dbed73cbSSangeeta Misra } 365dbed73cbSSangeeta Misra } 366dbed73cbSSangeeta Misra 367dbed73cbSSangeeta Misra if (i_find_sg_byname(sg->sg_name) != NULL) { 368dbed73cbSSangeeta Misra logdebug("ilbd_create_sg: server group %s already exists", 369dbed73cbSSangeeta Misra sg->sg_name); 370dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 371dbed73cbSSangeeta Misra ILBD_CREATE_SERVERGROUP, ILB_STATUS_SGEXISTS, ucredp); 372dbed73cbSSangeeta Misra return (ILB_STATUS_SGEXISTS); 373dbed73cbSSangeeta Misra } 374dbed73cbSSangeeta Misra 375dbed73cbSSangeeta Misra d_sg = i_ilbd_alloc_sg(sg->sg_name); 376dbed73cbSSangeeta Misra if (d_sg == NULL) { 377dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 378dbed73cbSSangeeta Misra ILBD_CREATE_SERVERGROUP, ILB_STATUS_ENOMEM, ucredp); 379dbed73cbSSangeeta Misra return (ILB_STATUS_ENOMEM); 380dbed73cbSSangeeta Misra } 381dbed73cbSSangeeta Misra 382dbed73cbSSangeeta Misra /* 383dbed73cbSSangeeta Misra * we've successfully created the sg in memory. Before we can 384dbed73cbSSangeeta Misra * return "success", we need to reflect this in persistent 385dbed73cbSSangeeta Misra * storage 386dbed73cbSSangeeta Misra */ 387dbed73cbSSangeeta Misra if (ps != NULL) { 388dbed73cbSSangeeta Misra rc = i_ilbd_save_sg(d_sg, ILBD_SCF_CREATE, NULL, NULL); 389dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 390dbed73cbSSangeeta Misra i_ilbd_free_sg(d_sg); 391dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 392dbed73cbSSangeeta Misra ILBD_CREATE_SERVERGROUP, rc, ucredp); 393dbed73cbSSangeeta Misra return (rc); 394dbed73cbSSangeeta Misra } 395dbed73cbSSangeeta Misra } 396dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 397dbed73cbSSangeeta Misra ILBD_CREATE_SERVERGROUP, rc, ucredp); 398dbed73cbSSangeeta Misra return (rc); 399dbed73cbSSangeeta Misra } 400dbed73cbSSangeeta Misra 401dbed73cbSSangeeta Misra /* 402dbed73cbSSangeeta Misra * This function checks whether tsrv should/can be inserted before lsrv 403dbed73cbSSangeeta Misra * and does so if possible. 404dbed73cbSSangeeta Misra * We keep the list in sorted order so we don't have to search it 405dbed73cbSSangeeta Misra * in its entirety for overlap every time we insert a new server. 406dbed73cbSSangeeta Misra * Return code: 407dbed73cbSSangeeta Misra * stop_found: don't continue searching because we found a place 408dbed73cbSSangeeta Misra * cont_search: continue with next element in the list 409dbed73cbSSangeeta Misra * fail_search: search failed (caller translates to ILB_STATUS_EEXIST) 410dbed73cbSSangeeta Misra */ 411dbed73cbSSangeeta Misra static srch_ind_t 412dbed73cbSSangeeta Misra i_test_and_insert(ilbd_srv_t *tsrv, ilbd_srv_t *lsrv, list_t *srvlist) 413dbed73cbSSangeeta Misra { 414dbed73cbSSangeeta Misra struct in6_addr *t1, *l1; 415dbed73cbSSangeeta Misra int fnd; 416dbed73cbSSangeeta Misra 417dbed73cbSSangeeta Misra t1 = &tsrv->isv_addr; 418dbed73cbSSangeeta Misra l1 = &lsrv->isv_addr; 419dbed73cbSSangeeta Misra 420dbed73cbSSangeeta Misra if ((fnd = ilb_cmp_in6_addr(t1, l1, NULL)) == 1) 421dbed73cbSSangeeta Misra return (cont_search); /* search can continue */ 422dbed73cbSSangeeta Misra 423dbed73cbSSangeeta Misra if (fnd == 0) { 424dbed73cbSSangeeta Misra logdebug("i_test_and_insert: specified server already exists"); 425dbed73cbSSangeeta Misra return (fail_search); 426dbed73cbSSangeeta Misra } 427dbed73cbSSangeeta Misra /* the list is kept in ascending order */ 428dbed73cbSSangeeta Misra list_insert_before(srvlist, lsrv, tsrv); 429dbed73cbSSangeeta Misra return (stop_found); 430dbed73cbSSangeeta Misra } 431dbed73cbSSangeeta Misra 432dbed73cbSSangeeta Misra 433dbed73cbSSangeeta Misra /* 434dbed73cbSSangeeta Misra * copy a server description [ip1,ip2,port1,port2,srvID,flags] 435dbed73cbSSangeeta Misra */ 436dbed73cbSSangeeta Misra #define COPY_SERVER(src, dest) \ 437dbed73cbSSangeeta Misra (dest)->sgs_addr = (src)->sgs_addr; \ 438dbed73cbSSangeeta Misra (dest)->sgs_minport = (src)->sgs_minport; \ 439dbed73cbSSangeeta Misra (dest)->sgs_maxport = (src)->sgs_maxport; \ 440dbed73cbSSangeeta Misra (dest)->sgs_id = (src)->sgs_id; \ 441dbed73cbSSangeeta Misra (void) strlcpy((dest)->sgs_srvID, (src)->sgs_srvID, \ 442dbed73cbSSangeeta Misra sizeof ((dest)->sgs_srvID)); \ 443dbed73cbSSangeeta Misra (dest)->sgs_flags = (src)->sgs_flags 444dbed73cbSSangeeta Misra 445dbed73cbSSangeeta Misra static ilb_status_t 446dbed73cbSSangeeta Misra i_add_srv2sg(ilbd_sg_t *dsg, ilb_sg_srv_t *srv, ilbd_srv_t **ret_srv) 447dbed73cbSSangeeta Misra { 448dbed73cbSSangeeta Misra ilb_sg_srv_t *n_sg_srv; 449dbed73cbSSangeeta Misra list_t *srvlist; 450dbed73cbSSangeeta Misra srch_ind_t search = not_searched; 451dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 452dbed73cbSSangeeta Misra ilbd_srv_t *nsrv, *lsrv; 453dbed73cbSSangeeta Misra in_port_t h_minport, h_maxport; 454dbed73cbSSangeeta Misra 455dbed73cbSSangeeta Misra nsrv = calloc(sizeof (*nsrv), 1); 456dbed73cbSSangeeta Misra if (nsrv == NULL) 457dbed73cbSSangeeta Misra return (ILB_STATUS_ENOMEM); 458dbed73cbSSangeeta Misra n_sg_srv = &nsrv->isv_srv; 459dbed73cbSSangeeta Misra COPY_SERVER(srv, n_sg_srv); 460dbed73cbSSangeeta Misra 461dbed73cbSSangeeta Misra /* 462dbed73cbSSangeeta Misra * port info is in network byte order - we need host byte order 463dbed73cbSSangeeta Misra * for comparisons purposes 464dbed73cbSSangeeta Misra */ 465dbed73cbSSangeeta Misra h_minport = ntohs(n_sg_srv->sgs_minport); 466dbed73cbSSangeeta Misra h_maxport = ntohs(n_sg_srv->sgs_maxport); 467dbed73cbSSangeeta Misra if (h_minport != 0 && h_minport > h_maxport) 468dbed73cbSSangeeta Misra n_sg_srv->sgs_maxport = n_sg_srv->sgs_minport; 469dbed73cbSSangeeta Misra 470dbed73cbSSangeeta Misra srvlist = &dsg->isg_srvlist; 471dbed73cbSSangeeta Misra 472dbed73cbSSangeeta Misra lsrv = list_head(srvlist); 473dbed73cbSSangeeta Misra if (lsrv == NULL) { 474dbed73cbSSangeeta Misra list_insert_head(srvlist, nsrv); 475dbed73cbSSangeeta Misra } else { 476dbed73cbSSangeeta Misra while (lsrv != NULL) { 477dbed73cbSSangeeta Misra search = i_test_and_insert(nsrv, lsrv, 478dbed73cbSSangeeta Misra srvlist); 479dbed73cbSSangeeta Misra 480dbed73cbSSangeeta Misra if (search != cont_search) 481dbed73cbSSangeeta Misra break; 482dbed73cbSSangeeta Misra lsrv = list_next(srvlist, lsrv); 483dbed73cbSSangeeta Misra 484dbed73cbSSangeeta Misra /* if reaches the end of list, insert to the tail */ 485dbed73cbSSangeeta Misra if (search == cont_search && lsrv == NULL) 486dbed73cbSSangeeta Misra list_insert_tail(srvlist, nsrv); 487dbed73cbSSangeeta Misra } 488dbed73cbSSangeeta Misra if (search == fail_search) 489dbed73cbSSangeeta Misra rc = ILB_STATUS_EEXIST; 490dbed73cbSSangeeta Misra } 491dbed73cbSSangeeta Misra 492dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) { 493dbed73cbSSangeeta Misra dsg->isg_srvcount++; 494dbed73cbSSangeeta Misra *ret_srv = nsrv; 495dbed73cbSSangeeta Misra } else { 496dbed73cbSSangeeta Misra free(nsrv); 497dbed73cbSSangeeta Misra } 498dbed73cbSSangeeta Misra 499dbed73cbSSangeeta Misra return (rc); 500dbed73cbSSangeeta Misra } 501dbed73cbSSangeeta Misra 502dbed73cbSSangeeta Misra /* 503dbed73cbSSangeeta Misra * Allocate a server ID. The algorithm is simple. Just check the ID array 504dbed73cbSSangeeta Misra * of the server group and find an unused ID. If *set_id is given, it 505dbed73cbSSangeeta Misra * means that the ID is already allocated and the ID array needs to be 506dbed73cbSSangeeta Misra * updated. This is the case when ilbd reads from the persistent 507dbed73cbSSangeeta Misra * configuration. 508dbed73cbSSangeeta Misra */ 509dbed73cbSSangeeta Misra static int32_t 510dbed73cbSSangeeta Misra i_ilbd_alloc_srvID(ilbd_sg_t *sg, int32_t *set_id) 511dbed73cbSSangeeta Misra { 512dbed73cbSSangeeta Misra int32_t id; 513dbed73cbSSangeeta Misra int32_t i; 514dbed73cbSSangeeta Misra 515dbed73cbSSangeeta Misra /* The server ID is already allocated, just update the ID array. */ 516dbed73cbSSangeeta Misra if (set_id != NULL) { 517dbed73cbSSangeeta Misra assert(sg->isg_id_arr[*set_id] == 0); 518dbed73cbSSangeeta Misra sg->isg_id_arr[*set_id] = 1; 519dbed73cbSSangeeta Misra return (*set_id); 520dbed73cbSSangeeta Misra } 521dbed73cbSSangeeta Misra 522dbed73cbSSangeeta Misra /* if we're "full up", give back something invalid */ 523dbed73cbSSangeeta Misra if (sg->isg_srvcount == MAX_SRVCOUNT) 524dbed73cbSSangeeta Misra return (BAD_SRVID); 525dbed73cbSSangeeta Misra 526dbed73cbSSangeeta Misra i = sg->isg_max_id; 527dbed73cbSSangeeta Misra for (id = 0; id < MAX_SRVCOUNT; id++) { 528dbed73cbSSangeeta Misra if (sg->isg_id_arr[(id + i) % MAX_SRVCOUNT] == 0) 529dbed73cbSSangeeta Misra break; 530dbed73cbSSangeeta Misra } 531dbed73cbSSangeeta Misra 532dbed73cbSSangeeta Misra sg->isg_max_id = (id + i) % MAX_SRVCOUNT; 533dbed73cbSSangeeta Misra sg->isg_id_arr[sg->isg_max_id] = 1; 534dbed73cbSSangeeta Misra return (sg->isg_max_id); 535dbed73cbSSangeeta Misra } 536dbed73cbSSangeeta Misra 537dbed73cbSSangeeta Misra /* 538dbed73cbSSangeeta Misra * Free a server ID by updating the server group's ID array. 539dbed73cbSSangeeta Misra */ 540dbed73cbSSangeeta Misra static void 541dbed73cbSSangeeta Misra i_ilbd_free_srvID(ilbd_sg_t *sg, int32_t id) 542dbed73cbSSangeeta Misra { 543dbed73cbSSangeeta Misra assert(sg->isg_id_arr[id] == 1); 544dbed73cbSSangeeta Misra sg->isg_id_arr[id] = 0; 545dbed73cbSSangeeta Misra } 546dbed73cbSSangeeta Misra 547dbed73cbSSangeeta Misra /* 548dbed73cbSSangeeta Misra * This function is called by ilbd_add_server_to_group() and 549dbed73cbSSangeeta Misra * ilb_remove_server_group() to create a audit record for a 550dbed73cbSSangeeta Misra * failed servicing of add-server/remove-server command 551dbed73cbSSangeeta Misra */ 552dbed73cbSSangeeta Misra static void 553dbed73cbSSangeeta Misra fill_audit_record(ilb_sg_info_t *sg, audit_sg_event_data_t *audit_sg_data, 554dbed73cbSSangeeta Misra ilbd_cmd_t cmd, ilb_status_t rc, ucred_t *ucredp) 555dbed73cbSSangeeta Misra { 556dbed73cbSSangeeta Misra ilb_sg_srv_t *tsrv; 557dbed73cbSSangeeta Misra int i; 558dbed73cbSSangeeta Misra 559dbed73cbSSangeeta Misra for (i = 0; i < sg->sg_srvcount; i++) { 560dbed73cbSSangeeta Misra tsrv = &sg->sg_servers[i]; 561dbed73cbSSangeeta Misra if (cmd == ILBD_ADD_SERVER_TO_GROUP) { 562dbed73cbSSangeeta Misra 563dbed73cbSSangeeta Misra audit_sg_data->ed_serverid = NULL; 564*5df82708SSangeeta Misra if (IN6_IS_ADDR_V4MAPPED(&tsrv->sgs_addr)) { 565*5df82708SSangeeta Misra audit_sg_data->ed_ipaddr_type = ADT_IPv4; 566*5df82708SSangeeta Misra cvt_addr(audit_sg_data->ed_server_address, 567*5df82708SSangeeta Misra ADT_IPv4, tsrv->sgs_addr); 568*5df82708SSangeeta Misra } else { 569*5df82708SSangeeta Misra audit_sg_data->ed_ipaddr_type = ADT_IPv6; 570*5df82708SSangeeta Misra cvt_addr(audit_sg_data->ed_server_address, 571*5df82708SSangeeta Misra ADT_IPv6, tsrv->sgs_addr); 572*5df82708SSangeeta Misra } 573dbed73cbSSangeeta Misra audit_sg_data->ed_minport = tsrv->sgs_minport; 574dbed73cbSSangeeta Misra audit_sg_data->ed_maxport = tsrv->sgs_maxport; 575dbed73cbSSangeeta Misra audit_sg_data->ed_sgroup = sg->sg_name; 576dbed73cbSSangeeta Misra } else if (cmd == ILBD_REM_SERVER_FROM_GROUP) { 577dbed73cbSSangeeta Misra audit_sg_data->ed_serverid = tsrv->sgs_srvID; 578dbed73cbSSangeeta Misra audit_sg_data->ed_sgroup = sg->sg_name; 579*5df82708SSangeeta Misra 580dbed73cbSSangeeta Misra audit_sg_data->ed_minport = 0; 581dbed73cbSSangeeta Misra audit_sg_data->ed_maxport = 0; 582dbed73cbSSangeeta Misra } 583dbed73cbSSangeeta Misra ilbd_audit_server_event(audit_sg_data, cmd, rc, ucredp); 584dbed73cbSSangeeta Misra } 585dbed73cbSSangeeta Misra } 586dbed73cbSSangeeta Misra 587dbed73cbSSangeeta Misra /* 588dbed73cbSSangeeta Misra * the name(s) of the server(s) are encoded in the sg. 589dbed73cbSSangeeta Misra */ 590dbed73cbSSangeeta Misra ilb_status_t 591dbed73cbSSangeeta Misra ilbd_add_server_to_group(ilb_sg_info_t *sg_info, int ev_port, 592dbed73cbSSangeeta Misra const struct passwd *ps, ucred_t *ucredp) 593dbed73cbSSangeeta Misra { 594dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 595dbed73cbSSangeeta Misra ilbd_sg_t *tmp_sg; 596dbed73cbSSangeeta Misra int i, j; 597dbed73cbSSangeeta Misra int32_t new_id = BAD_SRVID; 598dbed73cbSSangeeta Misra int32_t af = AF_UNSPEC; 599dbed73cbSSangeeta Misra ilbd_srv_t *nsrv; 600dbed73cbSSangeeta Misra ilb_sg_srv_t *srv; 601dbed73cbSSangeeta Misra audit_sg_event_data_t audit_sg_data; 602dbed73cbSSangeeta Misra 603dbed73cbSSangeeta Misra if (ps != NULL) { 604dbed73cbSSangeeta Misra rc = ilbd_check_client_config_auth(ps); 605dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 606dbed73cbSSangeeta Misra fill_audit_record(sg_info, &audit_sg_data, 607dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, rc, ucredp); 608dbed73cbSSangeeta Misra return (rc); 609dbed73cbSSangeeta Misra } 610dbed73cbSSangeeta Misra } 611dbed73cbSSangeeta Misra 612dbed73cbSSangeeta Misra tmp_sg = i_find_sg_byname(sg_info->sg_name); 613dbed73cbSSangeeta Misra if (tmp_sg == NULL) { 614dbed73cbSSangeeta Misra logdebug("ilbd_add_server_to_group: server" 615dbed73cbSSangeeta Misra " group %s does not exist", sg_info->sg_name); 616dbed73cbSSangeeta Misra fill_audit_record(sg_info, &audit_sg_data, 617dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, ILB_STATUS_ENOENT, ucredp); 618dbed73cbSSangeeta Misra return (ILB_STATUS_ENOENT); 619dbed73cbSSangeeta Misra } 620dbed73cbSSangeeta Misra 621dbed73cbSSangeeta Misra /* 622dbed73cbSSangeeta Misra * we do the dance with address family below to make sure only 623dbed73cbSSangeeta Misra * IP addresses in the same AF get into an SG; the first one to get 624dbed73cbSSangeeta Misra * in sets the "tone" 625dbed73cbSSangeeta Misra * if this is the first server to join a group, check whether 626dbed73cbSSangeeta Misra * there's no mismatch with any *rules* already attached 627dbed73cbSSangeeta Misra */ 628dbed73cbSSangeeta Misra if (tmp_sg->isg_srvcount > 0) { 629dbed73cbSSangeeta Misra ilbd_srv_t *tsrv = list_head(&tmp_sg->isg_srvlist); 630dbed73cbSSangeeta Misra 631dbed73cbSSangeeta Misra af = GET_AF(&tsrv->isv_addr); 632dbed73cbSSangeeta Misra } else { 633dbed73cbSSangeeta Misra ilbd_rule_t *irl = list_head(&tmp_sg->isg_rulelist); 634dbed73cbSSangeeta Misra 635dbed73cbSSangeeta Misra if (irl != NULL) 636dbed73cbSSangeeta Misra af = GET_AF(&irl->irl_vip); 637dbed73cbSSangeeta Misra } 638dbed73cbSSangeeta Misra 639dbed73cbSSangeeta Misra for (i = 0; i < sg_info->sg_srvcount; i++) { 640dbed73cbSSangeeta Misra srv = &sg_info->sg_servers[i]; 641dbed73cbSSangeeta Misra 642dbed73cbSSangeeta Misra (void) memset(&audit_sg_data, 0, sizeof (audit_sg_data)); 643*5df82708SSangeeta Misra if (IN6_IS_ADDR_V4MAPPED(&srv->sgs_addr)) { 644*5df82708SSangeeta Misra audit_sg_data.ed_ipaddr_type = ADT_IPv4; 645*5df82708SSangeeta Misra cvt_addr(audit_sg_data.ed_server_address, ADT_IPv4, 646*5df82708SSangeeta Misra srv->sgs_addr); 647*5df82708SSangeeta Misra } else { 648*5df82708SSangeeta Misra audit_sg_data.ed_ipaddr_type = ADT_IPv6; 649*5df82708SSangeeta Misra cvt_addr(audit_sg_data.ed_server_address, ADT_IPv6, 650*5df82708SSangeeta Misra srv->sgs_addr); 651*5df82708SSangeeta Misra } 652dbed73cbSSangeeta Misra audit_sg_data.ed_minport = srv->sgs_minport; 653dbed73cbSSangeeta Misra audit_sg_data.ed_maxport = srv->sgs_maxport; 654dbed73cbSSangeeta Misra audit_sg_data.ed_sgroup = sg_info->sg_name; 655dbed73cbSSangeeta Misra 656dbed73cbSSangeeta Misra /* only test if we have sth to test against */ 657dbed73cbSSangeeta Misra if (af != AF_UNSPEC) { 658dbed73cbSSangeeta Misra int32_t sgs_af = GET_AF(&srv->sgs_addr); 659dbed73cbSSangeeta Misra 660dbed73cbSSangeeta Misra if (af != sgs_af) { 661dbed73cbSSangeeta Misra logdebug("address family mismatch with previous" 662dbed73cbSSangeeta Misra " hosts in servergroup or with rule"); 663dbed73cbSSangeeta Misra rc = ILB_STATUS_MISMATCHH; 664dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 665dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, rc, ucredp); 666dbed73cbSSangeeta Misra goto rollback; 667dbed73cbSSangeeta Misra } 668dbed73cbSSangeeta Misra } 669dbed73cbSSangeeta Misra 670dbed73cbSSangeeta Misra /* 671dbed73cbSSangeeta Misra * PS: NULL means daemon is loading configure from scf. 672dbed73cbSSangeeta Misra * ServerID is already assigned, just update the ID array. 673dbed73cbSSangeeta Misra */ 674dbed73cbSSangeeta Misra if (ps != NULL) { 675dbed73cbSSangeeta Misra new_id = i_ilbd_alloc_srvID(tmp_sg, NULL); 676dbed73cbSSangeeta Misra if (new_id == BAD_SRVID) { 677dbed73cbSSangeeta Misra logdebug("ilbd_add_server_to_group: server" 678dbed73cbSSangeeta Misra "group %s is full, no more servers" 679dbed73cbSSangeeta Misra " can be added", sg_info->sg_name); 680dbed73cbSSangeeta Misra rc = ILB_STATUS_SGFULL; 681dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 682dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, rc, ucredp); 683dbed73cbSSangeeta Misra goto rollback; 684dbed73cbSSangeeta Misra } 685dbed73cbSSangeeta Misra srv->sgs_id = new_id; 686dbed73cbSSangeeta Misra } else { 687dbed73cbSSangeeta Misra new_id = i_ilbd_alloc_srvID(tmp_sg, &srv->sgs_id); 688dbed73cbSSangeeta Misra } 689dbed73cbSSangeeta Misra 690dbed73cbSSangeeta Misra /* 691dbed73cbSSangeeta Misra * here we implement the requirement that server IDs start 692dbed73cbSSangeeta Misra * with a character that is not legal in hostnames - in our 693dbed73cbSSangeeta Misra * case, a "_" (underscore). 694dbed73cbSSangeeta Misra */ 695dbed73cbSSangeeta Misra (void) snprintf(srv->sgs_srvID, 696dbed73cbSSangeeta Misra sizeof (srv->sgs_srvID), "%c%s.%d", ILB_SRVID_PREFIX, 697dbed73cbSSangeeta Misra tmp_sg->isg_name, srv->sgs_id); 698dbed73cbSSangeeta Misra audit_sg_data.ed_serverid = srv->sgs_srvID; 699dbed73cbSSangeeta Misra 700dbed73cbSSangeeta Misra /* 701dbed73cbSSangeeta Misra * Before we update the kernel rules by adding the server, 702dbed73cbSSangeeta Misra * we need to make checks and fail if any of the 703dbed73cbSSangeeta Misra * following is true: 704dbed73cbSSangeeta Misra * 705dbed73cbSSangeeta Misra * o if the server has single port and the servergroup 706dbed73cbSSangeeta Misra * is associated to a DSR rule with a port range 707dbed73cbSSangeeta Misra * o if the server has a port range and the servergroup 708dbed73cbSSangeeta Misra * is associated to a DSR rule with a port range and 709dbed73cbSSangeeta Misra * the rule's min and max port does not exactly 710dbed73cbSSangeeta Misra * match that of the server's. 711dbed73cbSSangeeta Misra * o if the the server has a port range and the servergroup 712dbed73cbSSangeeta Misra * is associated to a NAT/Half-NAT rule with a port range 713dbed73cbSSangeeta Misra * and the rule's port range size does not match that 714dbed73cbSSangeeta Misra * of the server's. 715dbed73cbSSangeeta Misra * o if the rule has a fixed hc port, check that this port 716dbed73cbSSangeeta Misra * is valid in the server's port specification. 717dbed73cbSSangeeta Misra */ 718dbed73cbSSangeeta Misra rc = i_check_srv2rules(&tmp_sg->isg_rulelist, srv); 719dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 720dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 721dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, rc, ucredp); 722dbed73cbSSangeeta Misra goto rollback; 723dbed73cbSSangeeta Misra } 724dbed73cbSSangeeta Misra 725dbed73cbSSangeeta Misra if ((rc = i_add_srv2sg(tmp_sg, srv, &nsrv)) != ILB_STATUS_OK) { 726dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 727dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, rc, ucredp); 728dbed73cbSSangeeta Misra goto rollback; 729dbed73cbSSangeeta Misra } 730dbed73cbSSangeeta Misra 731dbed73cbSSangeeta Misra rc = i_add_srv2krules(&tmp_sg->isg_rulelist, &nsrv->isv_srv, 732dbed73cbSSangeeta Misra ev_port); 733dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 734dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 735dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, rc, ucredp); 736dbed73cbSSangeeta Misra /* 737dbed73cbSSangeeta Misra * The failure may be due to the serverid being on 738dbed73cbSSangeeta Misra * hold in kernel for connection draining. But ilbd 739dbed73cbSSangeeta Misra * has no way of knowing that. So we are freeing up 740dbed73cbSSangeeta Misra * the serverid, and may run into the risk of 741dbed73cbSSangeeta Misra * having this failure again, if we choose this 742dbed73cbSSangeeta Misra * serverid when processing the next add-server 743dbed73cbSSangeeta Misra * command for this servergroup, while connection 744dbed73cbSSangeeta Misra * draining is underway. We assume that the user 745dbed73cbSSangeeta Misra * will read the man page after he/she encounters 746dbed73cbSSangeeta Misra * this failure, and learn to not add any server 747dbed73cbSSangeeta Misra * to the servergroup until connection draining of 748dbed73cbSSangeeta Misra * all servers in the servergroup is complete. 749dbed73cbSSangeeta Misra * XXX Need to revisit this when connection draining 750dbed73cbSSangeeta Misra * is reworked 751dbed73cbSSangeeta Misra */ 752dbed73cbSSangeeta Misra list_remove(&tmp_sg->isg_srvlist, nsrv); 753dbed73cbSSangeeta Misra i_ilbd_free_srvID(tmp_sg, nsrv->isv_id); 754dbed73cbSSangeeta Misra free(nsrv); 755dbed73cbSSangeeta Misra tmp_sg->isg_srvcount--; 756dbed73cbSSangeeta Misra goto rollback; 757dbed73cbSSangeeta Misra } 758dbed73cbSSangeeta Misra if (ps != NULL) { 759dbed73cbSSangeeta Misra rc = ilbd_scf_add_srv(tmp_sg, nsrv); 760dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 761dbed73cbSSangeeta Misra /* 762dbed73cbSSangeeta Misra * The following should not fail since the 763dbed73cbSSangeeta Misra * server is just added. Just in case, we 764dbed73cbSSangeeta Misra * pass in -1 as the event port to avoid 765dbed73cbSSangeeta Misra * roll back in i_rem_srv_frm_krules() called 766dbed73cbSSangeeta Misra * by i_delete_srv(). 767dbed73cbSSangeeta Misra */ 768dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 769dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, rc, ucredp); 770dbed73cbSSangeeta Misra (void) i_delete_srv(tmp_sg, nsrv, -1); 771dbed73cbSSangeeta Misra break; 772dbed73cbSSangeeta Misra } 773dbed73cbSSangeeta Misra } 774dbed73cbSSangeeta Misra } 775dbed73cbSSangeeta Misra 776dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) { 777dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 778dbed73cbSSangeeta Misra ILBD_ADD_SERVER_TO_GROUP, rc, ucredp); 779dbed73cbSSangeeta Misra return (rc); 780dbed73cbSSangeeta Misra } 781dbed73cbSSangeeta Misra 782dbed73cbSSangeeta Misra rollback: 783dbed73cbSSangeeta Misra /* 784dbed73cbSSangeeta Misra * If ilbd is initializing based on the SCF data and something fails, 785dbed73cbSSangeeta Misra * the only choice is to transition the service to maintanence mode... 786dbed73cbSSangeeta Misra */ 787dbed73cbSSangeeta Misra if (ps == NULL) { 788dbed73cbSSangeeta Misra logerr("%s: failure during initialization -" 789dbed73cbSSangeeta Misra " entering maintenance mode", __func__); 790dbed73cbSSangeeta Misra (void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE); 791dbed73cbSSangeeta Misra return (rc); 792dbed73cbSSangeeta Misra } 793dbed73cbSSangeeta Misra 794dbed73cbSSangeeta Misra /* 795dbed73cbSSangeeta Misra * we need to roll back all servers previous to the one 796dbed73cbSSangeeta Misra * that just caused the failure 797dbed73cbSSangeeta Misra */ 798dbed73cbSSangeeta Misra for (j = i-1; j >= 0; j--) { 799dbed73cbSSangeeta Misra srv = &sg_info->sg_servers[j]; 800dbed73cbSSangeeta Misra 801dbed73cbSSangeeta Misra /* We should be able to find those servers just added. */ 802dbed73cbSSangeeta Misra nsrv = i_find_srv(&tmp_sg->isg_srvlist, srv, MODE_SRVID); 803dbed73cbSSangeeta Misra assert(nsrv != NULL); 804dbed73cbSSangeeta Misra (void) i_delete_srv(tmp_sg, nsrv, -1); 805dbed73cbSSangeeta Misra } 806dbed73cbSSangeeta Misra return (rc); 807dbed73cbSSangeeta Misra } 808dbed73cbSSangeeta Misra 809dbed73cbSSangeeta Misra static srch_ind_t 810dbed73cbSSangeeta Misra i_match_srvID(ilb_sg_srv_t *sg_srv, ilbd_srv_t *lsrv) 811dbed73cbSSangeeta Misra { 812dbed73cbSSangeeta Misra if (strncmp(sg_srv->sgs_srvID, lsrv->isv_srvID, 813dbed73cbSSangeeta Misra sizeof (sg_srv->sgs_srvID)) == 0) { 814dbed73cbSSangeeta Misra return (stop_found); 815dbed73cbSSangeeta Misra } 816dbed73cbSSangeeta Misra return (cont_search); 817dbed73cbSSangeeta Misra } 818dbed73cbSSangeeta Misra 819dbed73cbSSangeeta Misra /* 820dbed73cbSSangeeta Misra * Sanity check on a rule's port specification against all the servers' 821dbed73cbSSangeeta Misra * specification in its associated server group. 822dbed73cbSSangeeta Misra * 823dbed73cbSSangeeta Misra * 1. If the health check's probe port (hcport) is specified. 824dbed73cbSSangeeta Misra * - if server port range is specified, check if hcport is inside 825dbed73cbSSangeeta Misra * the range 826dbed73cbSSangeeta Misra * - if no server port is specified (meaning the port range is the same as 827dbed73cbSSangeeta Misra * the rule's port range), check if hcport is inside the rule's range. 828dbed73cbSSangeeta Misra * 829dbed73cbSSangeeta Misra * 2. If a server has no port specification, there is no conflict. 830dbed73cbSSangeeta Misra * 831dbed73cbSSangeeta Misra * 3. If the rule's load balance mode is DSR, a server port specification must 832dbed73cbSSangeeta Misra * be exactly the same as the rule's. 833dbed73cbSSangeeta Misra * 834dbed73cbSSangeeta Misra * 4. In other modes (NAT and half-NAT), the server's port range must be 835dbed73cbSSangeeta Misra * the same as the rule's, unless it is doing port collapsing (the server's 836dbed73cbSSangeeta Misra * port range is only 1). 837dbed73cbSSangeeta Misra */ 838dbed73cbSSangeeta Misra ilb_status_t 839dbed73cbSSangeeta Misra ilbd_sg_check_rule_port(ilbd_sg_t *sg, ilb_rule_info_t *rl) 840dbed73cbSSangeeta Misra { 841dbed73cbSSangeeta Misra ilbd_srv_t *srv; 842dbed73cbSSangeeta Misra in_port_t r_minport, r_maxport; 843dbed73cbSSangeeta Misra 844dbed73cbSSangeeta Misra /* Don't allow adding a rule to a sg with no server, for now... */ 845dbed73cbSSangeeta Misra if (sg->isg_srvcount == 0) 846dbed73cbSSangeeta Misra return (ILB_STATUS_SGEMPTY); 847dbed73cbSSangeeta Misra 848dbed73cbSSangeeta Misra r_minport = ntohs(rl->rl_minport); 849dbed73cbSSangeeta Misra r_maxport = ntohs(rl->rl_maxport); 850dbed73cbSSangeeta Misra 851dbed73cbSSangeeta Misra for (srv = list_head(&sg->isg_srvlist); srv != NULL; 852dbed73cbSSangeeta Misra srv = list_next(&sg->isg_srvlist, srv)) { 853dbed73cbSSangeeta Misra in_port_t srv_minport, srv_maxport; 854dbed73cbSSangeeta Misra int range; 855dbed73cbSSangeeta Misra 856dbed73cbSSangeeta Misra srv_minport = ntohs(srv->isv_minport); 857dbed73cbSSangeeta Misra srv_maxport = ntohs(srv->isv_maxport); 858dbed73cbSSangeeta Misra range = srv_maxport - srv_minport; 859dbed73cbSSangeeta Misra 860dbed73cbSSangeeta Misra /* 861dbed73cbSSangeeta Misra * If the rule has a specific probe port, check if that port is 862dbed73cbSSangeeta Misra * valid in all the servers' port specification. 863dbed73cbSSangeeta Misra */ 864dbed73cbSSangeeta Misra if (rl->rl_hcpflag == ILB_HCI_PROBE_FIX) { 865dbed73cbSSangeeta Misra in_port_t hcport = ntohs(rl->rl_hcport); 866dbed73cbSSangeeta Misra 867dbed73cbSSangeeta Misra /* No server port specified. */ 868dbed73cbSSangeeta Misra if (srv_minport == 0) { 869dbed73cbSSangeeta Misra if (hcport > r_maxport || hcport < r_minport) { 870dbed73cbSSangeeta Misra return (ILB_STATUS_BADSG); 871dbed73cbSSangeeta Misra } 872dbed73cbSSangeeta Misra } else { 873dbed73cbSSangeeta Misra if (hcport > srv_maxport || 874dbed73cbSSangeeta Misra hcport < srv_minport) { 875dbed73cbSSangeeta Misra return (ILB_STATUS_BADSG); 876dbed73cbSSangeeta Misra } 877dbed73cbSSangeeta Misra } 878dbed73cbSSangeeta Misra } 879dbed73cbSSangeeta Misra 880dbed73cbSSangeeta Misra /* 881dbed73cbSSangeeta Misra * There is no server port specification, so there cannot be 882dbed73cbSSangeeta Misra * any conflict. 883dbed73cbSSangeeta Misra */ 884dbed73cbSSangeeta Misra if (srv_minport == 0) 885dbed73cbSSangeeta Misra continue; 886dbed73cbSSangeeta Misra 887dbed73cbSSangeeta Misra if (rl->rl_topo == ILB_TOPO_DSR) { 888dbed73cbSSangeeta Misra if (r_minport != srv_minport || 889dbed73cbSSangeeta Misra r_maxport != srv_maxport) { 890dbed73cbSSangeeta Misra return (ILB_STATUS_BADSG); 891dbed73cbSSangeeta Misra } 892dbed73cbSSangeeta Misra } else { 893dbed73cbSSangeeta Misra if ((range != r_maxport - r_minport) && range != 0) 894dbed73cbSSangeeta Misra return (ILB_STATUS_BADSG); 895dbed73cbSSangeeta Misra } 896dbed73cbSSangeeta Misra } 897dbed73cbSSangeeta Misra 898dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 899dbed73cbSSangeeta Misra } 900dbed73cbSSangeeta Misra 901dbed73cbSSangeeta Misra static srch_ind_t 902dbed73cbSSangeeta Misra i_match_srvIP(ilb_sg_srv_t *sg_srv, ilbd_srv_t *lsrv) 903dbed73cbSSangeeta Misra { 904dbed73cbSSangeeta Misra if (IN6_ARE_ADDR_EQUAL(&sg_srv->sgs_addr, &lsrv->isv_addr)) 905dbed73cbSSangeeta Misra return (stop_found); 906dbed73cbSSangeeta Misra return (cont_search); 907dbed73cbSSangeeta Misra } 908dbed73cbSSangeeta Misra 909dbed73cbSSangeeta Misra static ilbd_srv_t * 910dbed73cbSSangeeta Misra i_find_srv(list_t *srvlist, ilb_sg_srv_t *sg_srv, int cmpmode) 911dbed73cbSSangeeta Misra { 912dbed73cbSSangeeta Misra ilbd_srv_t *tmp_srv; 913dbed73cbSSangeeta Misra srch_ind_t srch_res = cont_search; 914dbed73cbSSangeeta Misra 915dbed73cbSSangeeta Misra for (tmp_srv = list_head(srvlist); tmp_srv != NULL; 916dbed73cbSSangeeta Misra tmp_srv = list_next(srvlist, tmp_srv)) { 917dbed73cbSSangeeta Misra switch (cmpmode) { 918dbed73cbSSangeeta Misra case MODE_ADDR: 919dbed73cbSSangeeta Misra srch_res = i_match_srvIP(sg_srv, tmp_srv); 920dbed73cbSSangeeta Misra break; 921dbed73cbSSangeeta Misra case MODE_SRVID: 922dbed73cbSSangeeta Misra srch_res = i_match_srvID(sg_srv, tmp_srv); 923dbed73cbSSangeeta Misra break; 924dbed73cbSSangeeta Misra } 925dbed73cbSSangeeta Misra if (srch_res == stop_found) 926dbed73cbSSangeeta Misra break; 927dbed73cbSSangeeta Misra } 928dbed73cbSSangeeta Misra 929dbed73cbSSangeeta Misra if (srch_res == stop_found) 930dbed73cbSSangeeta Misra return (tmp_srv); 931dbed73cbSSangeeta Misra return (NULL); 932dbed73cbSSangeeta Misra } 933dbed73cbSSangeeta Misra 934dbed73cbSSangeeta Misra static ilb_status_t 935dbed73cbSSangeeta Misra i_delete_srv(ilbd_sg_t *sg, ilbd_srv_t *srv, int ev_port) 936dbed73cbSSangeeta Misra { 937dbed73cbSSangeeta Misra ilb_status_t rc; 938dbed73cbSSangeeta Misra 939dbed73cbSSangeeta Misra rc = i_rem_srv_frm_krules(&sg->isg_rulelist, &srv->isv_srv, ev_port); 940dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 941dbed73cbSSangeeta Misra return (rc); 942dbed73cbSSangeeta Misra list_remove(&sg->isg_srvlist, srv); 943dbed73cbSSangeeta Misra i_ilbd_free_srvID(sg, srv->isv_id); 944dbed73cbSSangeeta Misra free(srv); 945dbed73cbSSangeeta Misra sg->isg_srvcount--; 946dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 947dbed73cbSSangeeta Misra } 948dbed73cbSSangeeta Misra 949dbed73cbSSangeeta Misra /* 950dbed73cbSSangeeta Misra * some people argue that returning anything here is 951dbed73cbSSangeeta Misra * useless - what *do* you do if you can't remove/destroy 952dbed73cbSSangeeta Misra * something anyway? 953dbed73cbSSangeeta Misra */ 954dbed73cbSSangeeta Misra ilb_status_t 955dbed73cbSSangeeta Misra ilbd_rem_server_from_group(ilb_sg_info_t *sg_info, int ev_port, 956dbed73cbSSangeeta Misra const struct passwd *ps, ucred_t *ucredp) 957dbed73cbSSangeeta Misra { 958dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 959dbed73cbSSangeeta Misra ilbd_sg_t *tmp_sg; 960dbed73cbSSangeeta Misra ilbd_srv_t *srv, tmp_srv; 961dbed73cbSSangeeta Misra ilb_sg_srv_t *tsrv; 962dbed73cbSSangeeta Misra audit_sg_event_data_t audit_sg_data; 963dbed73cbSSangeeta Misra 964dbed73cbSSangeeta Misra rc = ilbd_check_client_config_auth(ps); 965dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 966dbed73cbSSangeeta Misra fill_audit_record(sg_info, &audit_sg_data, 967dbed73cbSSangeeta Misra ILBD_REM_SERVER_FROM_GROUP, rc, ucredp); 968dbed73cbSSangeeta Misra return (rc); 969dbed73cbSSangeeta Misra } 970dbed73cbSSangeeta Misra 971dbed73cbSSangeeta Misra tmp_sg = i_find_sg_byname(sg_info->sg_name); 972dbed73cbSSangeeta Misra if (tmp_sg == NULL) { 973dbed73cbSSangeeta Misra logdebug("%s: server group %s\n does not exist", __func__, 974dbed73cbSSangeeta Misra sg_info->sg_name); 975dbed73cbSSangeeta Misra fill_audit_record(sg_info, &audit_sg_data, 976dbed73cbSSangeeta Misra ILBD_REM_SERVER_FROM_GROUP, ILB_STATUS_SGUNAVAIL, ucredp); 977dbed73cbSSangeeta Misra return (ILB_STATUS_SGUNAVAIL); 978dbed73cbSSangeeta Misra } 979dbed73cbSSangeeta Misra tsrv = &sg_info->sg_servers[0]; 980dbed73cbSSangeeta Misra audit_sg_data.ed_serverid = tsrv->sgs_srvID; 981dbed73cbSSangeeta Misra audit_sg_data.ed_sgroup = sg_info->sg_name; 982dbed73cbSSangeeta Misra 983dbed73cbSSangeeta Misra assert(sg_info->sg_srvcount == 1); 984dbed73cbSSangeeta Misra srv = i_find_srv(&tmp_sg->isg_srvlist, &sg_info->sg_servers[0], 985dbed73cbSSangeeta Misra MODE_SRVID); 986dbed73cbSSangeeta Misra if (srv == NULL) { 987dbed73cbSSangeeta Misra logdebug("%s: cannot find server in server group %s", __func__, 988dbed73cbSSangeeta Misra sg_info->sg_name); 989dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 990dbed73cbSSangeeta Misra ILBD_REM_SERVER_FROM_GROUP, ILB_STATUS_SRVUNAVAIL, ucredp); 991dbed73cbSSangeeta Misra return (ILB_STATUS_SRVUNAVAIL); 992dbed73cbSSangeeta Misra } 993dbed73cbSSangeeta Misra tsrv = &srv->isv_srv; 994*5df82708SSangeeta Misra if (IN6_IS_ADDR_V4MAPPED(&tsrv->sgs_addr)) { 995*5df82708SSangeeta Misra audit_sg_data.ed_ipaddr_type = ADT_IPv4; 996*5df82708SSangeeta Misra cvt_addr(audit_sg_data.ed_server_address, ADT_IPv4, 997*5df82708SSangeeta Misra tsrv->sgs_addr); 998*5df82708SSangeeta Misra } else { 999*5df82708SSangeeta Misra audit_sg_data.ed_ipaddr_type = ADT_IPv6; 1000*5df82708SSangeeta Misra cvt_addr(audit_sg_data.ed_server_address, ADT_IPv6, 1001*5df82708SSangeeta Misra tsrv->sgs_addr); 1002*5df82708SSangeeta Misra } 1003dbed73cbSSangeeta Misra /* 1004dbed73cbSSangeeta Misra * i_delete_srv frees srv, therefore we need to save 1005dbed73cbSSangeeta Misra * this information for ilbd_scf_del_srv 1006dbed73cbSSangeeta Misra */ 1007dbed73cbSSangeeta Misra (void) memcpy(&tmp_srv, srv, sizeof (tmp_srv)); 1008dbed73cbSSangeeta Misra 1009dbed73cbSSangeeta Misra rc = i_delete_srv(tmp_sg, srv, ev_port); 1010dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 1011dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1012dbed73cbSSangeeta Misra ILBD_REM_SERVER_FROM_GROUP, rc, ucredp); 1013dbed73cbSSangeeta Misra return (rc); 1014dbed73cbSSangeeta Misra } 1015dbed73cbSSangeeta Misra 1016dbed73cbSSangeeta Misra if (ps != NULL) { 1017dbed73cbSSangeeta Misra if ((rc = ilbd_scf_del_srv(tmp_sg, &tmp_srv)) != 1018dbed73cbSSangeeta Misra ILB_STATUS_OK) { 1019dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1020dbed73cbSSangeeta Misra ILBD_REM_SERVER_FROM_GROUP, rc, ucredp); 1021dbed73cbSSangeeta Misra logerr("%s: SCF update failed - entering maintenance" 1022dbed73cbSSangeeta Misra " mode", __func__); 1023dbed73cbSSangeeta Misra (void) smf_maintain_instance(ILB_FMRI, SMF_IMMEDIATE); 1024dbed73cbSSangeeta Misra } 1025dbed73cbSSangeeta Misra } 1026dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1027dbed73cbSSangeeta Misra ILBD_REM_SERVER_FROM_GROUP, rc, ucredp); 1028dbed73cbSSangeeta Misra return (rc); 1029dbed73cbSSangeeta Misra } 1030dbed73cbSSangeeta Misra 1031dbed73cbSSangeeta Misra ilb_status_t 1032dbed73cbSSangeeta Misra ilbd_retrieve_names(ilbd_cmd_t cmd, uint32_t *rbuf, size_t *rbufsz) 1033dbed73cbSSangeeta Misra { 1034dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 1035dbed73cbSSangeeta Misra ilbd_namelist_t *nlist; 1036dbed73cbSSangeeta Misra size_t tmp_rbufsz; 1037dbed73cbSSangeeta Misra 1038dbed73cbSSangeeta Misra tmp_rbufsz = *rbufsz; 1039dbed73cbSSangeeta Misra /* Set up the reply buffer. rbufsz will be set to the new size. */ 1040dbed73cbSSangeeta Misra ilbd_reply_ok(rbuf, rbufsz); 1041dbed73cbSSangeeta Misra 1042dbed73cbSSangeeta Misra /* Calculate how much space is left for holding name info. */ 1043dbed73cbSSangeeta Misra *rbufsz += sizeof (ilbd_namelist_t); 1044dbed73cbSSangeeta Misra tmp_rbufsz -= *rbufsz; 1045dbed73cbSSangeeta Misra 1046dbed73cbSSangeeta Misra nlist = (ilbd_namelist_t *)&((ilb_comm_t *)rbuf)->ic_data; 1047dbed73cbSSangeeta Misra nlist->ilbl_count = 0; 1048dbed73cbSSangeeta Misra 1049dbed73cbSSangeeta Misra switch (cmd) { 1050dbed73cbSSangeeta Misra case ILBD_RETRIEVE_SG_NAMES: { 1051dbed73cbSSangeeta Misra ilbd_sg_t *sg; 1052dbed73cbSSangeeta Misra 1053dbed73cbSSangeeta Misra for (sg = list_head(&ilbd_sg_hlist); 1054dbed73cbSSangeeta Misra sg != NULL && tmp_rbufsz >= sizeof (ilbd_name_t); 1055dbed73cbSSangeeta Misra sg = list_next(&ilbd_sg_hlist, sg), 1056dbed73cbSSangeeta Misra tmp_rbufsz -= sizeof (ilbd_name_t)) { 1057dbed73cbSSangeeta Misra (void) strlcpy(nlist->ilbl_name[nlist->ilbl_count++], 1058dbed73cbSSangeeta Misra sg->isg_name, sizeof (ilbd_name_t)); 1059dbed73cbSSangeeta Misra } 1060dbed73cbSSangeeta Misra break; 1061dbed73cbSSangeeta Misra } 1062dbed73cbSSangeeta Misra case ILBD_RETRIEVE_RULE_NAMES: { 1063dbed73cbSSangeeta Misra ilbd_rule_t *irl; 1064dbed73cbSSangeeta Misra extern list_t ilbd_rule_hlist; 1065dbed73cbSSangeeta Misra 1066dbed73cbSSangeeta Misra for (irl = list_head(&ilbd_rule_hlist); 1067dbed73cbSSangeeta Misra irl != NULL && tmp_rbufsz >= sizeof (ilbd_name_t); 1068dbed73cbSSangeeta Misra irl = list_next(&ilbd_rule_hlist, irl), 1069dbed73cbSSangeeta Misra tmp_rbufsz -= sizeof (ilbd_name_t)) { 1070dbed73cbSSangeeta Misra (void) strlcpy(nlist->ilbl_name[nlist->ilbl_count++], 1071dbed73cbSSangeeta Misra irl->irl_name, sizeof (ilbd_name_t)); 1072dbed73cbSSangeeta Misra } 1073dbed73cbSSangeeta Misra break; 1074dbed73cbSSangeeta Misra } 1075dbed73cbSSangeeta Misra case ILBD_RETRIEVE_HC_NAMES: { 1076dbed73cbSSangeeta Misra extern list_t ilbd_hc_list; 1077dbed73cbSSangeeta Misra ilbd_hc_t *hc; 1078dbed73cbSSangeeta Misra 1079dbed73cbSSangeeta Misra for (hc = list_head(&ilbd_hc_list); 1080dbed73cbSSangeeta Misra hc != NULL && tmp_rbufsz >= sizeof (ilbd_name_t); 1081dbed73cbSSangeeta Misra hc = list_next(&ilbd_hc_list, hc)) { 1082dbed73cbSSangeeta Misra (void) strlcpy(nlist->ilbl_name[nlist->ilbl_count++], 1083dbed73cbSSangeeta Misra hc->ihc_name, sizeof (ilbd_name_t)); 1084dbed73cbSSangeeta Misra } 1085dbed73cbSSangeeta Misra break; 1086dbed73cbSSangeeta Misra } 1087dbed73cbSSangeeta Misra default: 1088dbed73cbSSangeeta Misra logdebug("ilbd_retrieve_names: unknown command"); 1089dbed73cbSSangeeta Misra return (ILB_STATUS_INVAL_CMD); 1090dbed73cbSSangeeta Misra } 1091dbed73cbSSangeeta Misra 1092dbed73cbSSangeeta Misra *rbufsz += nlist->ilbl_count * sizeof (ilbd_name_t); 1093dbed73cbSSangeeta Misra return (rc); 1094dbed73cbSSangeeta Misra } 1095dbed73cbSSangeeta Misra 1096dbed73cbSSangeeta Misra ilb_status_t 1097dbed73cbSSangeeta Misra ilbd_retrieve_sg_hosts(const char *sg_name, uint32_t *rbuf, size_t *rbufsz) 1098dbed73cbSSangeeta Misra { 1099dbed73cbSSangeeta Misra ilbd_sg_t *dsg; 1100dbed73cbSSangeeta Misra ilbd_srv_t *dsrv; 1101dbed73cbSSangeeta Misra list_t *srvlist; 1102dbed73cbSSangeeta Misra ilb_sg_info_t *sg_info; 1103dbed73cbSSangeeta Misra size_t tmp_rbufsz; 1104dbed73cbSSangeeta Misra 1105dbed73cbSSangeeta Misra dsg = i_find_sg_byname(sg_name); 1106dbed73cbSSangeeta Misra if (dsg == NULL) { 1107dbed73cbSSangeeta Misra logdebug("ilbd_retrieve_sg_hosts: server group" 1108dbed73cbSSangeeta Misra " %s not found", sg_name); 1109dbed73cbSSangeeta Misra return (ILB_STATUS_SGUNAVAIL); 1110dbed73cbSSangeeta Misra } 1111dbed73cbSSangeeta Misra 1112dbed73cbSSangeeta Misra srvlist = &dsg->isg_srvlist; 1113dbed73cbSSangeeta Misra dsrv = list_head(srvlist); 1114dbed73cbSSangeeta Misra 1115dbed73cbSSangeeta Misra tmp_rbufsz = *rbufsz; 1116dbed73cbSSangeeta Misra ilbd_reply_ok(rbuf, rbufsz); 1117dbed73cbSSangeeta Misra 1118dbed73cbSSangeeta Misra /* Calculate the size to hold all the hosts info. */ 1119dbed73cbSSangeeta Misra *rbufsz += sizeof (ilb_sg_info_t); 1120dbed73cbSSangeeta Misra tmp_rbufsz -= *rbufsz; 1121dbed73cbSSangeeta Misra 1122dbed73cbSSangeeta Misra sg_info = (ilb_sg_info_t *)&((ilb_comm_t *)rbuf)->ic_data; 1123dbed73cbSSangeeta Misra (void) strlcpy(sg_info->sg_name, sg_name, sizeof (sg_info->sg_name)); 1124dbed73cbSSangeeta Misra sg_info->sg_srvcount = 0; 1125dbed73cbSSangeeta Misra 1126dbed73cbSSangeeta Misra while (dsrv != NULL && tmp_rbufsz >= sizeof (ilb_sg_srv_t)) { 1127dbed73cbSSangeeta Misra sg_info->sg_servers[sg_info->sg_srvcount++] = dsrv->isv_srv; 1128dbed73cbSSangeeta Misra dsrv = list_next(srvlist, dsrv); 1129dbed73cbSSangeeta Misra tmp_rbufsz -= sizeof (ilb_sg_srv_t); 1130dbed73cbSSangeeta Misra } 1131dbed73cbSSangeeta Misra *rbufsz += sg_info->sg_srvcount * sizeof (ilb_sg_srv_t); 1132dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1133dbed73cbSSangeeta Misra } 1134dbed73cbSSangeeta Misra 1135dbed73cbSSangeeta Misra /* 1136dbed73cbSSangeeta Misra * this mapping function works on the assumption that HC only is 1137dbed73cbSSangeeta Misra * active when a server is enabled. 1138dbed73cbSSangeeta Misra */ 1139dbed73cbSSangeeta Misra static ilb_cmd_t 1140dbed73cbSSangeeta Misra i_srvcmd_d2k(ilbd_srv_status_ind_t dcmd) 1141dbed73cbSSangeeta Misra { 1142dbed73cbSSangeeta Misra ilb_cmd_t cmd; 1143dbed73cbSSangeeta Misra 1144dbed73cbSSangeeta Misra switch (dcmd) { 1145dbed73cbSSangeeta Misra case stat_enable_server: 1146dbed73cbSSangeeta Misra case stat_declare_srv_alive: 1147dbed73cbSSangeeta Misra cmd = ILB_ENABLE_SERVERS; 1148dbed73cbSSangeeta Misra break; 1149dbed73cbSSangeeta Misra case stat_disable_server: 1150dbed73cbSSangeeta Misra case stat_declare_srv_dead: 1151dbed73cbSSangeeta Misra cmd = ILB_DISABLE_SERVERS; 1152dbed73cbSSangeeta Misra break; 1153dbed73cbSSangeeta Misra } 1154dbed73cbSSangeeta Misra 1155dbed73cbSSangeeta Misra return (cmd); 1156dbed73cbSSangeeta Misra } 1157dbed73cbSSangeeta Misra 1158dbed73cbSSangeeta Misra ilb_status_t 1159dbed73cbSSangeeta Misra ilbd_k_Xable_server(const struct in6_addr *addr, const char *rlname, 1160dbed73cbSSangeeta Misra ilbd_srv_status_ind_t cmd) 1161dbed73cbSSangeeta Misra { 1162dbed73cbSSangeeta Misra ilb_status_t rc; 1163dbed73cbSSangeeta Misra ilb_servers_cmd_t kcmd; 1164dbed73cbSSangeeta Misra int e; 1165dbed73cbSSangeeta Misra 1166dbed73cbSSangeeta Misra kcmd.cmd = i_srvcmd_d2k(cmd); 1167dbed73cbSSangeeta Misra (void) strlcpy(kcmd.name, rlname, sizeof (kcmd.name)); 1168dbed73cbSSangeeta Misra kcmd.num_servers = 1; 1169dbed73cbSSangeeta Misra 1170dbed73cbSSangeeta Misra kcmd.servers[0].addr = *addr; 1171dbed73cbSSangeeta Misra kcmd.servers[0].err = 0; 1172dbed73cbSSangeeta Misra 1173dbed73cbSSangeeta Misra rc = do_ioctl(&kcmd, 0); 1174dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) 1175dbed73cbSSangeeta Misra return (rc); 1176dbed73cbSSangeeta Misra 1177dbed73cbSSangeeta Misra if ((e = kcmd.servers[0].err) != 0) { 1178dbed73cbSSangeeta Misra logdebug("ilbd_k_Xable_server: error %s occurred", 1179dbed73cbSSangeeta Misra strerror(e)); 1180dbed73cbSSangeeta Misra return (ilb_map_errno2ilbstat(e)); 1181dbed73cbSSangeeta Misra } 1182dbed73cbSSangeeta Misra 1183dbed73cbSSangeeta Misra return (rc); 1184dbed73cbSSangeeta Misra } 1185dbed73cbSSangeeta Misra 1186dbed73cbSSangeeta Misra #define IS_SRV_ENABLED(s) ILB_IS_SRV_ENABLED((s)->sgs_flags) 1187dbed73cbSSangeeta Misra #define IS_SRV_DISABLED(s) (!(IS_SRV_ENABLED(s))) 1188dbed73cbSSangeeta Misra 1189dbed73cbSSangeeta Misra #define SET_SRV_ENABLED(s) ILB_SET_ENABLED((s)->sgs_flags) 1190dbed73cbSSangeeta Misra #define SET_SRV_DISABLED(s) ILB_SET_DISABLED((s)->sgs_flags) 1191dbed73cbSSangeeta Misra 1192dbed73cbSSangeeta Misra static ilb_status_t 1193dbed73cbSSangeeta Misra ilbd_Xable_server(ilb_sg_info_t *sg, const struct passwd *ps, 1194dbed73cbSSangeeta Misra ilbd_srv_status_ind_t cmd, ucred_t *ucredp) 1195dbed73cbSSangeeta Misra { 1196dbed73cbSSangeeta Misra ilb_status_t rc = ILB_STATUS_OK; 1197dbed73cbSSangeeta Misra ilbd_sg_t *isg; 1198dbed73cbSSangeeta Misra ilbd_srv_t *tmp_srv; 1199dbed73cbSSangeeta Misra ilb_sg_srv_t *srv; 1200dbed73cbSSangeeta Misra ilbd_rule_t *irl; 1201dbed73cbSSangeeta Misra char *dot; 1202dbed73cbSSangeeta Misra int scf_name_len = ILBD_MAX_NAME_LEN; 1203dbed73cbSSangeeta Misra int scf_val_len = ILBD_MAX_VALUE_LEN; 12043ae6a67dSSangeeta Misra char *prop_name = NULL; 1205dbed73cbSSangeeta Misra ilb_ip_addr_t ipaddr; 1206dbed73cbSSangeeta Misra void *addrptr; 12073ae6a67dSSangeeta Misra char ipstr[INET6_ADDRSTRLEN], *valstr = NULL; 1208dbed73cbSSangeeta Misra int ipver, vallen; 1209dbed73cbSSangeeta Misra char sgname[ILB_NAMESZ]; 1210dbed73cbSSangeeta Misra uint32_t nflags; 1211dbed73cbSSangeeta Misra ilbd_srv_status_ind_t u_cmd; 1212dbed73cbSSangeeta Misra audit_sg_event_data_t audit_sg_data; 1213dbed73cbSSangeeta Misra 1214dbed73cbSSangeeta Misra (void) memset(&audit_sg_data, 0, sizeof (audit_sg_data)); 1215dbed73cbSSangeeta Misra 1216dbed73cbSSangeeta Misra /* we currently only implement a "list" of one */ 1217dbed73cbSSangeeta Misra assert(sg->sg_srvcount == 1); 1218dbed73cbSSangeeta Misra 1219dbed73cbSSangeeta Misra srv = &sg->sg_servers[0]; 1220dbed73cbSSangeeta Misra audit_sg_data.ed_serverid = srv->sgs_srvID; 1221dbed73cbSSangeeta Misra 1222dbed73cbSSangeeta Misra rc = ilbd_check_client_enable_auth(ps); 1223dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 1224dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1225dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, rc, ucredp); 1226dbed73cbSSangeeta Misra return (rc); 1227dbed73cbSSangeeta Misra } 1228dbed73cbSSangeeta Misra 1229dbed73cbSSangeeta Misra if (srv->sgs_srvID[0] != ILB_SRVID_PREFIX) { 1230dbed73cbSSangeeta Misra switch (cmd) { 1231dbed73cbSSangeeta Misra case stat_disable_server: 1232dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1233dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, 1234dbed73cbSSangeeta Misra ILB_STATUS_EINVAL, ucredp); 1235dbed73cbSSangeeta Misra break; 1236dbed73cbSSangeeta Misra case stat_enable_server: 1237dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1238dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, 1239dbed73cbSSangeeta Misra ILB_STATUS_EINVAL, ucredp); 1240dbed73cbSSangeeta Misra break; 1241dbed73cbSSangeeta Misra } 1242dbed73cbSSangeeta Misra return (ILB_STATUS_EINVAL); 1243dbed73cbSSangeeta Misra } 1244dbed73cbSSangeeta Misra 1245dbed73cbSSangeeta Misra /* 1246dbed73cbSSangeeta Misra * the following asserts that serverIDs are constructed 1247dbed73cbSSangeeta Misra * along the pattern "_"<SG name>"."<number> 1248dbed73cbSSangeeta Misra * so we look for the final "." to recreate the SG name. 1249dbed73cbSSangeeta Misra */ 1250dbed73cbSSangeeta Misra (void) strlcpy(sgname, srv->sgs_srvID + 1, sizeof (sgname)); 1251dbed73cbSSangeeta Misra dot = strrchr(sgname, (int)'.'); 1252dbed73cbSSangeeta Misra if (dot == NULL) { 1253dbed73cbSSangeeta Misra switch (cmd) { 1254dbed73cbSSangeeta Misra case stat_disable_server: 1255dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1256dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, 1257dbed73cbSSangeeta Misra ILB_STATUS_EINVAL, ucredp); 1258dbed73cbSSangeeta Misra break; 1259dbed73cbSSangeeta Misra case stat_enable_server: 1260dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1261dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, 1262dbed73cbSSangeeta Misra ILB_STATUS_EINVAL, ucredp); 1263dbed73cbSSangeeta Misra break; 1264dbed73cbSSangeeta Misra } 1265dbed73cbSSangeeta Misra return (ILB_STATUS_EINVAL); 1266dbed73cbSSangeeta Misra } 1267dbed73cbSSangeeta Misra 1268dbed73cbSSangeeta Misra /* make the non-sg_name part "invisible" */ 1269dbed73cbSSangeeta Misra *dot = '\0'; 1270dbed73cbSSangeeta Misra isg = i_find_sg_byname(sgname); 1271dbed73cbSSangeeta Misra if (isg == NULL) { 1272dbed73cbSSangeeta Misra switch (cmd) { 1273dbed73cbSSangeeta Misra case stat_disable_server: 1274dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1275dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, 1276dbed73cbSSangeeta Misra ILB_STATUS_ENOENT, ucredp); 1277dbed73cbSSangeeta Misra break; 1278dbed73cbSSangeeta Misra case stat_enable_server: 1279dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1280dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, 1281dbed73cbSSangeeta Misra ILB_STATUS_ENOENT, ucredp); 1282dbed73cbSSangeeta Misra break; 1283dbed73cbSSangeeta Misra } 1284dbed73cbSSangeeta Misra return (ILB_STATUS_ENOENT); 1285dbed73cbSSangeeta Misra } 1286dbed73cbSSangeeta Misra 1287dbed73cbSSangeeta Misra tmp_srv = i_find_srv(&isg->isg_srvlist, srv, MODE_SRVID); 1288dbed73cbSSangeeta Misra if (tmp_srv == NULL) { 1289dbed73cbSSangeeta Misra switch (cmd) { 1290dbed73cbSSangeeta Misra case stat_disable_server: 1291dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1292dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, 1293dbed73cbSSangeeta Misra ILB_STATUS_ENOENT, ucredp); 1294dbed73cbSSangeeta Misra break; 1295dbed73cbSSangeeta Misra case stat_enable_server: 1296dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1297dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, 1298dbed73cbSSangeeta Misra ILB_STATUS_ENOENT, ucredp); 1299dbed73cbSSangeeta Misra break; 1300dbed73cbSSangeeta Misra } 1301dbed73cbSSangeeta Misra return (ILB_STATUS_ENOENT); 1302dbed73cbSSangeeta Misra } 1303dbed73cbSSangeeta Misra 1304dbed73cbSSangeeta Misra /* 1305dbed73cbSSangeeta Misra * if server's servergroup is not associated with 1306dbed73cbSSangeeta Misra * a rule, do not enable it. 1307dbed73cbSSangeeta Misra */ 1308dbed73cbSSangeeta Misra irl = list_head(&isg->isg_rulelist); 1309dbed73cbSSangeeta Misra if (irl == NULL) { 1310dbed73cbSSangeeta Misra switch (cmd) { 1311dbed73cbSSangeeta Misra case stat_disable_server: 1312dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1313dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, 1314dbed73cbSSangeeta Misra ILB_STATUS_INVAL_ENBSRVR, ucredp); 1315dbed73cbSSangeeta Misra break; 1316dbed73cbSSangeeta Misra case stat_enable_server: 1317dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1318dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, 1319dbed73cbSSangeeta Misra ILB_STATUS_INVAL_ENBSRVR, ucredp); 1320dbed73cbSSangeeta Misra break; 1321dbed73cbSSangeeta Misra } 1322dbed73cbSSangeeta Misra return (ILB_STATUS_INVAL_ENBSRVR); 1323dbed73cbSSangeeta Misra } 1324dbed73cbSSangeeta Misra /* Fill in the server IP address for audit record */ 1325*5df82708SSangeeta Misra if (IN6_IS_ADDR_V4MAPPED(&tmp_srv->isv_addr)) { 1326*5df82708SSangeeta Misra audit_sg_data.ed_ipaddr_type = ADT_IPv4; 1327*5df82708SSangeeta Misra cvt_addr(audit_sg_data.ed_server_address, ADT_IPv4, 1328*5df82708SSangeeta Misra tmp_srv->isv_addr); 1329*5df82708SSangeeta Misra } else { 1330*5df82708SSangeeta Misra audit_sg_data.ed_ipaddr_type = ADT_IPv6; 1331*5df82708SSangeeta Misra cvt_addr(audit_sg_data.ed_server_address, ADT_IPv6, 1332*5df82708SSangeeta Misra tmp_srv->isv_addr); 1333*5df82708SSangeeta Misra } 1334dbed73cbSSangeeta Misra 1335dbed73cbSSangeeta Misra /* 1336dbed73cbSSangeeta Misra * We have found the server in memory, perform the following 1337dbed73cbSSangeeta Misra * tasks. 1338dbed73cbSSangeeta Misra * 1339dbed73cbSSangeeta Misra * 1. For every rule associated with this SG, 1340dbed73cbSSangeeta Misra * - tell the kernel 1341dbed73cbSSangeeta Misra * - tell the hc 1342dbed73cbSSangeeta Misra * 2. Update our internal state and persistent configuration 1343dbed73cbSSangeeta Misra * if the new state is not the same as the old one. 1344dbed73cbSSangeeta Misra */ 1345dbed73cbSSangeeta Misra /* 1. */ 1346dbed73cbSSangeeta Misra for (; irl != NULL; irl = list_next(&isg->isg_rulelist, irl)) { 1347dbed73cbSSangeeta Misra rc = ilbd_k_Xable_server(&tmp_srv->isv_addr, 1348dbed73cbSSangeeta Misra irl->irl_name, cmd); 1349dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 1350dbed73cbSSangeeta Misra switch (cmd) { 1351dbed73cbSSangeeta Misra case stat_disable_server: 1352dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1353dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, rc, ucredp); 1354dbed73cbSSangeeta Misra break; 1355dbed73cbSSangeeta Misra case stat_enable_server: 1356dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1357dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, rc, ucredp); 1358dbed73cbSSangeeta Misra break; 1359dbed73cbSSangeeta Misra } 1360dbed73cbSSangeeta Misra goto rollback_rules; 1361dbed73cbSSangeeta Misra } 1362dbed73cbSSangeeta Misra if (!RULE_HAS_HC(irl)) 1363dbed73cbSSangeeta Misra continue; 1364dbed73cbSSangeeta Misra 1365dbed73cbSSangeeta Misra if (cmd == stat_disable_server) { 1366dbed73cbSSangeeta Misra rc = ilbd_hc_disable_server(irl, 1367dbed73cbSSangeeta Misra &tmp_srv->isv_srv); 1368dbed73cbSSangeeta Misra } else { 1369dbed73cbSSangeeta Misra assert(cmd == stat_enable_server); 1370dbed73cbSSangeeta Misra rc = ilbd_hc_enable_server(irl, 1371dbed73cbSSangeeta Misra &tmp_srv->isv_srv); 1372dbed73cbSSangeeta Misra } 1373dbed73cbSSangeeta Misra if (rc != ILB_STATUS_OK) { 1374dbed73cbSSangeeta Misra logdebug("ilbd_Xable_server: cannot toggle srv " 1375dbed73cbSSangeeta Misra "timer, rc =%d, srv =%s%d\n", rc, 1376dbed73cbSSangeeta Misra tmp_srv->isv_srvID, 1377dbed73cbSSangeeta Misra tmp_srv->isv_id); 1378dbed73cbSSangeeta Misra } 1379dbed73cbSSangeeta Misra } 1380dbed73cbSSangeeta Misra 1381dbed73cbSSangeeta Misra /* 2. */ 1382dbed73cbSSangeeta Misra if ((cmd == stat_disable_server && 1383dbed73cbSSangeeta Misra IS_SRV_DISABLED(&tmp_srv->isv_srv)) || 1384dbed73cbSSangeeta Misra (cmd == stat_enable_server && 1385dbed73cbSSangeeta Misra IS_SRV_ENABLED(&tmp_srv->isv_srv))) { 1386dbed73cbSSangeeta Misra switch (cmd) { 1387dbed73cbSSangeeta Misra case stat_disable_server: 1388dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1389dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, ILB_STATUS_OK, ucredp); 1390dbed73cbSSangeeta Misra break; 1391dbed73cbSSangeeta Misra case stat_enable_server: 1392dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1393dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, ILB_STATUS_OK, ucredp); 1394dbed73cbSSangeeta Misra break; 1395dbed73cbSSangeeta Misra } 1396dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1397dbed73cbSSangeeta Misra } 1398dbed73cbSSangeeta Misra 1399dbed73cbSSangeeta Misra nflags = tmp_srv->isv_flags; 1400dbed73cbSSangeeta Misra if (cmd == stat_enable_server) 1401dbed73cbSSangeeta Misra ILB_SET_ENABLED(nflags); 1402dbed73cbSSangeeta Misra else 1403dbed73cbSSangeeta Misra ILB_SET_DISABLED(nflags); 1404dbed73cbSSangeeta Misra 1405dbed73cbSSangeeta Misra IP_COPY_IMPL_2_CLI(&tmp_srv->isv_addr, &ipaddr); 1406dbed73cbSSangeeta Misra ipver = GET_AF(&tmp_srv->isv_addr); 1407dbed73cbSSangeeta Misra vallen = (ipver == AF_INET) ? INET_ADDRSTRLEN : 1408dbed73cbSSangeeta Misra INET6_ADDRSTRLEN; 1409dbed73cbSSangeeta Misra addrptr = (ipver == AF_INET) ? (void *)&ipaddr.ia_v4 : 1410dbed73cbSSangeeta Misra (void *)&ipaddr.ia_v6; 1411dbed73cbSSangeeta Misra if (inet_ntop(ipver, addrptr, ipstr, vallen) == NULL) { 1412dbed73cbSSangeeta Misra logerr("ilbd_Xable_server: failed transfer ip addr to" 1413dbed73cbSSangeeta Misra " str"); 1414dbed73cbSSangeeta Misra if (errno == ENOSPC) 1415dbed73cbSSangeeta Misra rc = ILB_STATUS_ENOMEM; 1416dbed73cbSSangeeta Misra else 1417dbed73cbSSangeeta Misra rc = ILB_STATUS_GENERIC; 1418dbed73cbSSangeeta Misra switch (cmd) { 1419dbed73cbSSangeeta Misra case stat_disable_server: 1420dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1421dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, rc, ucredp); 1422dbed73cbSSangeeta Misra break; 1423dbed73cbSSangeeta Misra case stat_enable_server: 1424dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1425dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, rc, ucredp); 1426dbed73cbSSangeeta Misra break; 1427dbed73cbSSangeeta Misra } 1428dbed73cbSSangeeta Misra goto rollback_rules; 1429dbed73cbSSangeeta Misra } 1430dbed73cbSSangeeta Misra 14313ae6a67dSSangeeta Misra if ((prop_name = malloc(scf_name_len)) == NULL) 14323ae6a67dSSangeeta Misra return (ILB_STATUS_ENOMEM); 14333ae6a67dSSangeeta Misra if ((valstr = malloc(scf_val_len)) == NULL) { 14343ae6a67dSSangeeta Misra free(prop_name); 14353ae6a67dSSangeeta Misra return (ILB_STATUS_ENOMEM); 14363ae6a67dSSangeeta Misra } 14373ae6a67dSSangeeta Misra 14383ae6a67dSSangeeta Misra (void) snprintf(valstr, scf_val_len, "%s;%d;%d-%d;%d", 1439dbed73cbSSangeeta Misra ipstr, ipver, 1440dbed73cbSSangeeta Misra ntohs(tmp_srv->isv_minport), 1441dbed73cbSSangeeta Misra ntohs(tmp_srv->isv_maxport), nflags); 14423ae6a67dSSangeeta Misra (void) snprintf(prop_name, scf_name_len, "server%d", 1443dbed73cbSSangeeta Misra tmp_srv->isv_id); 1444dbed73cbSSangeeta Misra 1445dbed73cbSSangeeta Misra switch (cmd) { 1446dbed73cbSSangeeta Misra case stat_disable_server: 1447dbed73cbSSangeeta Misra rc = i_ilbd_save_sg(isg, ILBD_SCF_ENABLE_DISABLE, 1448dbed73cbSSangeeta Misra prop_name, valstr); 1449dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) 1450dbed73cbSSangeeta Misra SET_SRV_DISABLED(&tmp_srv->isv_srv); 1451dbed73cbSSangeeta Misra break; 1452dbed73cbSSangeeta Misra case stat_enable_server: 1453dbed73cbSSangeeta Misra rc = i_ilbd_save_sg(isg, ILBD_SCF_ENABLE_DISABLE, 1454dbed73cbSSangeeta Misra prop_name, valstr); 1455dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) 1456dbed73cbSSangeeta Misra SET_SRV_ENABLED(&tmp_srv->isv_srv); 1457dbed73cbSSangeeta Misra break; 1458dbed73cbSSangeeta Misra } 14593ae6a67dSSangeeta Misra free(prop_name); 14603ae6a67dSSangeeta Misra free(valstr); 1461dbed73cbSSangeeta Misra if (rc == ILB_STATUS_OK) { 1462dbed73cbSSangeeta Misra switch (cmd) { 1463dbed73cbSSangeeta Misra case stat_disable_server: 1464dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1465dbed73cbSSangeeta Misra ILBD_DISABLE_SERVER, ILB_STATUS_OK, ucredp); 1466dbed73cbSSangeeta Misra break; 1467dbed73cbSSangeeta Misra case stat_enable_server: 1468dbed73cbSSangeeta Misra ilbd_audit_server_event(&audit_sg_data, 1469dbed73cbSSangeeta Misra ILBD_ENABLE_SERVER, ILB_STATUS_OK, ucredp); 1470dbed73cbSSangeeta Misra break; 1471dbed73cbSSangeeta Misra } 1472dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1473dbed73cbSSangeeta Misra } 1474dbed73cbSSangeeta Misra 1475dbed73cbSSangeeta Misra rollback_rules: 1476dbed73cbSSangeeta Misra if (cmd == stat_disable_server) 1477dbed73cbSSangeeta Misra u_cmd = stat_enable_server; 1478dbed73cbSSangeeta Misra else 1479dbed73cbSSangeeta Misra u_cmd = stat_disable_server; 1480dbed73cbSSangeeta Misra 1481dbed73cbSSangeeta Misra if (irl == NULL) 1482dbed73cbSSangeeta Misra irl = list_tail(&isg->isg_rulelist); 1483dbed73cbSSangeeta Misra else 1484dbed73cbSSangeeta Misra irl = list_prev(&isg->isg_rulelist, irl); 1485dbed73cbSSangeeta Misra 1486dbed73cbSSangeeta Misra for (; irl != NULL; irl = list_prev(&isg->isg_rulelist, irl)) { 1487dbed73cbSSangeeta Misra (void) ilbd_k_Xable_server(&tmp_srv->isv_addr, 1488dbed73cbSSangeeta Misra irl->irl_name, u_cmd); 1489dbed73cbSSangeeta Misra if (!RULE_HAS_HC(irl)) 1490dbed73cbSSangeeta Misra continue; 1491dbed73cbSSangeeta Misra 1492dbed73cbSSangeeta Misra if (u_cmd == stat_disable_server) 1493dbed73cbSSangeeta Misra (void) ilbd_hc_disable_server(irl, &tmp_srv->isv_srv); 1494dbed73cbSSangeeta Misra else 1495dbed73cbSSangeeta Misra (void) ilbd_hc_enable_server(irl, &tmp_srv->isv_srv); 1496dbed73cbSSangeeta Misra } 1497dbed73cbSSangeeta Misra 1498dbed73cbSSangeeta Misra return (rc); 1499dbed73cbSSangeeta Misra } 1500dbed73cbSSangeeta Misra 1501dbed73cbSSangeeta Misra ilb_status_t 1502dbed73cbSSangeeta Misra ilbd_disable_server(ilb_sg_info_t *sg, const struct passwd *ps, 1503dbed73cbSSangeeta Misra ucred_t *ucredp) 1504dbed73cbSSangeeta Misra { 1505dbed73cbSSangeeta Misra return (ilbd_Xable_server(sg, ps, stat_disable_server, ucredp)); 1506dbed73cbSSangeeta Misra } 1507dbed73cbSSangeeta Misra 1508dbed73cbSSangeeta Misra ilb_status_t 1509dbed73cbSSangeeta Misra ilbd_enable_server(ilb_sg_info_t *sg, const struct passwd *ps, 1510dbed73cbSSangeeta Misra ucred_t *ucredp) 1511dbed73cbSSangeeta Misra { 1512dbed73cbSSangeeta Misra return (ilbd_Xable_server(sg, ps, stat_enable_server, ucredp)); 1513dbed73cbSSangeeta Misra } 1514dbed73cbSSangeeta Misra 1515dbed73cbSSangeeta Misra /* 1516dbed73cbSSangeeta Misra * fill in the srvID for the given IP address in the 0th server 1517dbed73cbSSangeeta Misra */ 1518dbed73cbSSangeeta Misra ilb_status_t 1519dbed73cbSSangeeta Misra ilbd_address_to_srvID(ilb_sg_info_t *sg, uint32_t *rbuf, size_t *rbufsz) 1520dbed73cbSSangeeta Misra { 1521dbed73cbSSangeeta Misra ilbd_srv_t *tmp_srv; 1522dbed73cbSSangeeta Misra ilb_sg_srv_t *tsrv; 1523dbed73cbSSangeeta Misra ilbd_sg_t *tmp_sg; 1524dbed73cbSSangeeta Misra 1525dbed73cbSSangeeta Misra ilbd_reply_ok(rbuf, rbufsz); 1526dbed73cbSSangeeta Misra tsrv = (ilb_sg_srv_t *)&((ilb_comm_t *)rbuf)->ic_data; 1527dbed73cbSSangeeta Misra *rbufsz += sizeof (ilb_sg_srv_t); 1528dbed73cbSSangeeta Misra 1529dbed73cbSSangeeta Misra tmp_sg = i_find_sg_byname(sg->sg_name); 1530dbed73cbSSangeeta Misra if (tmp_sg == NULL) 1531dbed73cbSSangeeta Misra return (ILB_STATUS_SGUNAVAIL); 1532dbed73cbSSangeeta Misra tsrv->sgs_addr = sg->sg_servers[0].sgs_addr; 1533dbed73cbSSangeeta Misra 1534dbed73cbSSangeeta Misra tmp_srv = i_find_srv(&tmp_sg->isg_srvlist, tsrv, MODE_ADDR); 1535dbed73cbSSangeeta Misra if (tmp_srv == NULL) 1536dbed73cbSSangeeta Misra return (ILB_STATUS_ENOENT); 1537dbed73cbSSangeeta Misra 1538dbed73cbSSangeeta Misra (void) strlcpy(tsrv->sgs_srvID, tmp_srv->isv_srvID, 1539dbed73cbSSangeeta Misra sizeof (tsrv->sgs_srvID)); 1540dbed73cbSSangeeta Misra 1541dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1542dbed73cbSSangeeta Misra } 1543dbed73cbSSangeeta Misra 1544dbed73cbSSangeeta Misra /* 1545dbed73cbSSangeeta Misra * fill in the address for the given serverID in the 0th server 1546dbed73cbSSangeeta Misra */ 1547dbed73cbSSangeeta Misra ilb_status_t 1548dbed73cbSSangeeta Misra ilbd_srvID_to_address(ilb_sg_info_t *sg, uint32_t *rbuf, size_t *rbufsz) 1549dbed73cbSSangeeta Misra { 1550dbed73cbSSangeeta Misra ilbd_srv_t *tmp_srv; 1551dbed73cbSSangeeta Misra ilb_sg_srv_t *tsrv; 1552dbed73cbSSangeeta Misra ilbd_sg_t *tmp_sg; 1553dbed73cbSSangeeta Misra 1554dbed73cbSSangeeta Misra ilbd_reply_ok(rbuf, rbufsz); 1555dbed73cbSSangeeta Misra tsrv = (ilb_sg_srv_t *)&((ilb_comm_t *)rbuf)->ic_data; 1556dbed73cbSSangeeta Misra 1557dbed73cbSSangeeta Misra tmp_sg = i_find_sg_byname(sg->sg_name); 1558dbed73cbSSangeeta Misra if (tmp_sg == NULL) 1559dbed73cbSSangeeta Misra return (ILB_STATUS_SGUNAVAIL); 1560dbed73cbSSangeeta Misra (void) strlcpy(tsrv->sgs_srvID, sg->sg_servers[0].sgs_srvID, 1561dbed73cbSSangeeta Misra sizeof (tsrv->sgs_srvID)); 1562dbed73cbSSangeeta Misra 1563dbed73cbSSangeeta Misra tmp_srv = i_find_srv(&tmp_sg->isg_srvlist, tsrv, MODE_SRVID); 1564dbed73cbSSangeeta Misra if (tmp_srv == NULL) 1565dbed73cbSSangeeta Misra return (ILB_STATUS_ENOENT); 1566dbed73cbSSangeeta Misra 1567dbed73cbSSangeeta Misra tsrv->sgs_addr = tmp_srv->isv_addr; 1568dbed73cbSSangeeta Misra *rbufsz += sizeof (ilb_sg_srv_t); 1569dbed73cbSSangeeta Misra 1570dbed73cbSSangeeta Misra return (ILB_STATUS_OK); 1571dbed73cbSSangeeta Misra } 1572dbed73cbSSangeeta Misra 1573dbed73cbSSangeeta Misra /* 1574dbed73cbSSangeeta Misra * Map ilb_status errors to similar errno values from errno.h or 1575dbed73cbSSangeeta Misra * adt_event.h to be used for audit record 1576dbed73cbSSangeeta Misra */ 1577dbed73cbSSangeeta Misra int 1578dbed73cbSSangeeta Misra ilberror2auditerror(ilb_status_t rc) 1579dbed73cbSSangeeta Misra { 1580dbed73cbSSangeeta Misra int audit_error; 1581dbed73cbSSangeeta Misra 1582dbed73cbSSangeeta Misra switch (rc) { 1583dbed73cbSSangeeta Misra case ILB_STATUS_CFGAUTH: 1584dbed73cbSSangeeta Misra audit_error = ADT_FAIL_VALUE_AUTH; 1585dbed73cbSSangeeta Misra break; 1586dbed73cbSSangeeta Misra case ILB_STATUS_ENOMEM: 1587dbed73cbSSangeeta Misra audit_error = ENOMEM; 1588dbed73cbSSangeeta Misra break; 1589dbed73cbSSangeeta Misra case ILB_STATUS_ENOENT: 1590dbed73cbSSangeeta Misra case ILB_STATUS_ENOHCINFO: 1591dbed73cbSSangeeta Misra case ILB_STATUS_INVAL_HCTESTTYPE: 1592dbed73cbSSangeeta Misra case ILB_STATUS_INVAL_CMD: 1593dbed73cbSSangeeta Misra case ILB_STATUS_DUP_RULE: 1594dbed73cbSSangeeta Misra case ILB_STATUS_ENORULE: 1595dbed73cbSSangeeta Misra case ILB_STATUS_SGUNAVAIL: 1596dbed73cbSSangeeta Misra audit_error = ENOENT; 1597dbed73cbSSangeeta Misra break; 1598dbed73cbSSangeeta Misra case ILB_STATUS_EINVAL: 1599dbed73cbSSangeeta Misra case ILB_STATUS_MISMATCHSG: 1600dbed73cbSSangeeta Misra case ILB_STATUS_MISMATCHH: 1601dbed73cbSSangeeta Misra case ILB_STATUS_BADSG: 1602dbed73cbSSangeeta Misra case ILB_STATUS_INVAL_SRVR: 1603dbed73cbSSangeeta Misra case ILB_STATUS_INVAL_ENBSRVR: 1604dbed73cbSSangeeta Misra case ILB_STATUS_BADPORT: 1605dbed73cbSSangeeta Misra audit_error = EINVAL; 1606dbed73cbSSangeeta Misra break; 1607dbed73cbSSangeeta Misra case ILB_STATUS_EEXIST: 1608dbed73cbSSangeeta Misra case ILB_STATUS_SGEXISTS: 1609dbed73cbSSangeeta Misra audit_error = EEXIST; 1610dbed73cbSSangeeta Misra break; 1611dbed73cbSSangeeta Misra case ILB_STATUS_EWOULDBLOCK: 1612dbed73cbSSangeeta Misra audit_error = EWOULDBLOCK; 1613dbed73cbSSangeeta Misra break; 1614dbed73cbSSangeeta Misra case ILB_STATUS_INPROGRESS: 1615dbed73cbSSangeeta Misra audit_error = EINPROGRESS; 1616dbed73cbSSangeeta Misra break; 1617dbed73cbSSangeeta Misra case ILB_STATUS_INTERNAL: 1618dbed73cbSSangeeta Misra case ILB_STATUS_CALLBACK: 1619dbed73cbSSangeeta Misra case ILB_STATUS_PERMIT: 1620dbed73cbSSangeeta Misra case ILB_STATUS_RULE_NO_HC: 1621dbed73cbSSangeeta Misra audit_error = ADT_FAIL_VALUE_PROGRAM; 1622dbed73cbSSangeeta Misra break; 1623dbed73cbSSangeeta Misra case ILB_STATUS_SOCKET: 1624dbed73cbSSangeeta Misra audit_error = ENOTSOCK; 1625dbed73cbSSangeeta Misra break; 1626dbed73cbSSangeeta Misra case ILB_STATUS_READ: 1627dbed73cbSSangeeta Misra case ILB_STATUS_WRITE: 1628dbed73cbSSangeeta Misra audit_error = ENOTCONN; 1629dbed73cbSSangeeta Misra break; 1630dbed73cbSSangeeta Misra case ILB_STATUS_SGINUSE: 1631dbed73cbSSangeeta Misra audit_error = EADDRINUSE; 1632dbed73cbSSangeeta Misra break; 1633dbed73cbSSangeeta Misra case ILB_STATUS_SEND: 1634dbed73cbSSangeeta Misra audit_error = ECOMM; 1635dbed73cbSSangeeta Misra break; 1636dbed73cbSSangeeta Misra case ILB_STATUS_SGFULL: 1637dbed73cbSSangeeta Misra audit_error = EOVERFLOW; 1638dbed73cbSSangeeta Misra break; 1639dbed73cbSSangeeta Misra case ILB_STATUS_NAMETOOLONG: 1640dbed73cbSSangeeta Misra audit_error = ENAMETOOLONG; 1641dbed73cbSSangeeta Misra break; 1642dbed73cbSSangeeta Misra case ILB_STATUS_SRVUNAVAIL: 1643dbed73cbSSangeeta Misra audit_error = EHOSTUNREACH; 1644dbed73cbSSangeeta Misra break; 1645dbed73cbSSangeeta Misra default: 1646dbed73cbSSangeeta Misra audit_error = ADT_FAIL_VALUE_UNKNOWN; 1647dbed73cbSSangeeta Misra break; 1648dbed73cbSSangeeta Misra } 1649dbed73cbSSangeeta Misra return (audit_error); 1650dbed73cbSSangeeta Misra } 1651