1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright (c) 2000-2001 by Sun Microsystems, Inc. 24*0Sstevel@tonic-gate * All rights reserved. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * This is the main file for the Domain Configuration Server (DCS). 31*0Sstevel@tonic-gate * 32*0Sstevel@tonic-gate * The DCS is a server that runs on a domain and communicates with 33*0Sstevel@tonic-gate * a Domain Configuration Agent (DCA) running on a remote host. The 34*0Sstevel@tonic-gate * DCA initiates DR requests that the DCS performs by calling the 35*0Sstevel@tonic-gate * appropriate libcfgadm(3LIB) function. 36*0Sstevel@tonic-gate * 37*0Sstevel@tonic-gate * This file contains functions that receive and process the messages 38*0Sstevel@tonic-gate * received from the DCA. It also handles the initialization of the 39*0Sstevel@tonic-gate * server and is responsible for starting a concurrent session to 40*0Sstevel@tonic-gate * handle each DR request. 41*0Sstevel@tonic-gate */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #include <stdlib.h> 44*0Sstevel@tonic-gate #include <stdio.h> 45*0Sstevel@tonic-gate #include <unistd.h> 46*0Sstevel@tonic-gate #include <string.h> 47*0Sstevel@tonic-gate #include <fcntl.h> 48*0Sstevel@tonic-gate #include <errno.h> 49*0Sstevel@tonic-gate #include <syslog.h> 50*0Sstevel@tonic-gate #include <assert.h> 51*0Sstevel@tonic-gate #include <signal.h> 52*0Sstevel@tonic-gate #include <netdb.h> 53*0Sstevel@tonic-gate #include <config_admin.h> 54*0Sstevel@tonic-gate #include <sys/param.h> 55*0Sstevel@tonic-gate #include <sys/time.h> 56*0Sstevel@tonic-gate #include <sys/stat.h> 57*0Sstevel@tonic-gate #include <sys/socket.h> 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include "dcs.h" 60*0Sstevel@tonic-gate #include "remote_cfg.h" 61*0Sstevel@tonic-gate #include "rdr_param_types.h" 62*0Sstevel@tonic-gate #include "rdr_messages.h" 63*0Sstevel@tonic-gate #include "rsrc_info.h" 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate typedef struct { 67*0Sstevel@tonic-gate ushort_t major; 68*0Sstevel@tonic-gate ushort_t minor; 69*0Sstevel@tonic-gate } dcs_ver_t; 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate /* initialization functions */ 73*0Sstevel@tonic-gate static int init_server(struct pollfd *pfd); 74*0Sstevel@tonic-gate static void init_signals(void); 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate /* message processing functions */ 77*0Sstevel@tonic-gate static int invalid_msg(rdr_msg_hdr_t *hdr); 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate /* message handling functions */ 80*0Sstevel@tonic-gate static int dcs_ses_req(rdr_msg_hdr_t *hdr, cfga_params_t *param); 81*0Sstevel@tonic-gate static int dcs_ses_estbl(rdr_msg_hdr_t *hdr, cfga_params_t *param); 82*0Sstevel@tonic-gate static int dcs_ses_end(rdr_msg_hdr_t *hdr, cfga_params_t *param); 83*0Sstevel@tonic-gate static int dcs_change_state(rdr_msg_hdr_t *hdr, cfga_params_t *param); 84*0Sstevel@tonic-gate static int dcs_private_func(rdr_msg_hdr_t *hdr, cfga_params_t *param); 85*0Sstevel@tonic-gate static int dcs_test(rdr_msg_hdr_t *hdr, cfga_params_t *param); 86*0Sstevel@tonic-gate static int dcs_list_ext(rdr_msg_hdr_t *hdr, cfga_params_t *param); 87*0Sstevel@tonic-gate static int dcs_help(rdr_msg_hdr_t *hdr, cfga_params_t *param); 88*0Sstevel@tonic-gate static int dcs_ap_id_cmp(rdr_msg_hdr_t *hdr, cfga_params_t *param); 89*0Sstevel@tonic-gate static int dcs_abort_cmd(rdr_msg_hdr_t *hdr, cfga_params_t *param); 90*0Sstevel@tonic-gate static int dcs_rsrc_info(rdr_msg_hdr_t *hdr, cfga_params_t *param); 91*0Sstevel@tonic-gate static int dcs_unknown_op(rdr_msg_hdr_t *hdr, cfga_params_t *param); 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate /* local callback functions */ 94*0Sstevel@tonic-gate static int dcs_confirm_callback(void *appdata_ptr, const char *message); 95*0Sstevel@tonic-gate static int dcs_message_callback(void *appdata_ptr, const char *message); 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* utility functions */ 98*0Sstevel@tonic-gate static dcs_ver_t resolve_version(ushort_t req_major, ushort_t req_minor); 99*0Sstevel@tonic-gate static void filter_list_data(int perm, int *nlistp, cfga_list_data_t *linfo); 100*0Sstevel@tonic-gate static rdr_list_t *generate_sort_order(cfga_list_data_t *listp, int nlist); 101*0Sstevel@tonic-gate static int ldata_compare(const void *ap1, const void *ap2); 102*0Sstevel@tonic-gate static int invalid_msg(rdr_msg_hdr_t *hdr); 103*0Sstevel@tonic-gate static char *basename(char *path); 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate /* 107*0Sstevel@tonic-gate * Lookup table for handling different message types. This 108*0Sstevel@tonic-gate * assumes the ordering of rdr_msg_opcode_t in remote_cfg.h. 109*0Sstevel@tonic-gate * If this enum changes, the lookup table must be updated. 110*0Sstevel@tonic-gate * 111*0Sstevel@tonic-gate * The lookup table handles all _known_ opcodes >= 0. Unsupported 112*0Sstevel@tonic-gate * opcodes, or opcodes that should not be received by the 113*0Sstevel@tonic-gate * dispatcher are handled by the dcs_unknown_op() function. 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate int (*dcs_cmd[])(rdr_msg_hdr_t *, cfga_params_t *) = { 116*0Sstevel@tonic-gate dcs_unknown_op, /* 0 is an invalid opcode */ 117*0Sstevel@tonic-gate dcs_ses_req, /* RDR_SES_REQ */ 118*0Sstevel@tonic-gate dcs_ses_estbl, /* RDR_SES_ESTBL */ 119*0Sstevel@tonic-gate dcs_ses_end, /* RDR_SES_END */ 120*0Sstevel@tonic-gate dcs_change_state, /* RDR_CONF_CHANGE_STATE */ 121*0Sstevel@tonic-gate dcs_private_func, /* RDR_CONF_PRIVATE_FUNC */ 122*0Sstevel@tonic-gate dcs_test, /* RDR_CONF_TEST */ 123*0Sstevel@tonic-gate dcs_list_ext, /* RDR_CONF_LIST_EXT */ 124*0Sstevel@tonic-gate dcs_help, /* RDR_CONF_HELP */ 125*0Sstevel@tonic-gate dcs_ap_id_cmp, /* RDR_CONF_AP_ID_CMP */ 126*0Sstevel@tonic-gate dcs_abort_cmd, /* RDR_CONF_ABORT_CMD */ 127*0Sstevel@tonic-gate dcs_unknown_op, /* RDR_CONF_CONFIRM_CALLBACK */ 128*0Sstevel@tonic-gate dcs_unknown_op, /* RDR_CONF_MSG_CALLBACK */ 129*0Sstevel@tonic-gate dcs_rsrc_info /* RDR_RSRC_INFO */ 130*0Sstevel@tonic-gate }; 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate /* 134*0Sstevel@tonic-gate * ver_supp[] is an array of the supported versions for the network 135*0Sstevel@tonic-gate * transport protocol used by the DCA and DCS. Each item in the array 136*0Sstevel@tonic-gate * is a pair: { major_version, minor_version }. 137*0Sstevel@tonic-gate * 138*0Sstevel@tonic-gate * The order of the array is significant. The first element should be 139*0Sstevel@tonic-gate * the highest supported version and all successive elements should be 140*0Sstevel@tonic-gate * strictly decreasing. 141*0Sstevel@tonic-gate */ 142*0Sstevel@tonic-gate dcs_ver_t ver_supp[] = { 143*0Sstevel@tonic-gate { 1, 0 } 144*0Sstevel@tonic-gate }; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate #define DCS_CURR_VER ver_supp[0] 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate /* 150*0Sstevel@tonic-gate * Global Data 151*0Sstevel@tonic-gate */ 152*0Sstevel@tonic-gate char *cmdname = NULL; /* the name of the executable */ 153*0Sstevel@tonic-gate ulong_t dcs_debug = 0; /* control the amount of debugging */ 154*0Sstevel@tonic-gate int standalone = 0; /* control standalone mode */ 155*0Sstevel@tonic-gate ulong_t max_sessions = DCS_MAX_SESSIONS; /* control maximum active sessions */ 156*0Sstevel@tonic-gate int dcsfd = STDIN_FILENO; /* fd for the DCS reserved port */ 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate /* 160*0Sstevel@tonic-gate * main: 161*0Sstevel@tonic-gate * 162*0Sstevel@tonic-gate * Initialize the DCS and then enter an infinite loop. This loop waits 163*0Sstevel@tonic-gate * for connection requests to come and then establishes a connection. 164*0Sstevel@tonic-gate * It dispatches the connection to be handled in a concurrent session. 165*0Sstevel@tonic-gate */ 166*0Sstevel@tonic-gate int 167*0Sstevel@tonic-gate main(int argc, char **argv) 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate int opt; 170*0Sstevel@tonic-gate struct timeval tv; 171*0Sstevel@tonic-gate struct pollfd dcs_rcv; 172*0Sstevel@tonic-gate int newfd; 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate /* initialize globals */ 176*0Sstevel@tonic-gate dcs_debug = DBG_NONE; 177*0Sstevel@tonic-gate cmdname = basename(argv[0]); 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate /* open log file with unique prefix */ 180*0Sstevel@tonic-gate openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON); 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* 183*0Sstevel@tonic-gate * Process command line args 184*0Sstevel@tonic-gate */ 185*0Sstevel@tonic-gate opterr = 0; /* disable getopt error messages */ 186*0Sstevel@tonic-gate while ((opt = getopt(argc, argv, OPT_STR)) != EOF) { 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate switch (opt) { 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate case 'd': { 191*0Sstevel@tonic-gate int usr_debug; 192*0Sstevel@tonic-gate char *err_str; 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate usr_debug = strtol(optarg, &err_str, 0); 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate /* 197*0Sstevel@tonic-gate * The err_str parameter will be an 198*0Sstevel@tonic-gate * empty string if successful. 199*0Sstevel@tonic-gate */ 200*0Sstevel@tonic-gate if (*err_str != '\0') { 201*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_BAD_OPT_ARG, optopt, 202*0Sstevel@tonic-gate optarg, "exiting"); 203*0Sstevel@tonic-gate (void) rdr_reject(dcsfd); 204*0Sstevel@tonic-gate exit(1); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate dcs_debug = usr_debug; 208*0Sstevel@tonic-gate break; 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate case 'S': 212*0Sstevel@tonic-gate standalone++; 213*0Sstevel@tonic-gate break; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate case 's': { 216*0Sstevel@tonic-gate int usr_ses; 217*0Sstevel@tonic-gate char *err_str; 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate usr_ses = strtol(optarg, &err_str, 0); 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate if (usr_ses >= 1) { 222*0Sstevel@tonic-gate max_sessions = usr_ses; 223*0Sstevel@tonic-gate } else { 224*0Sstevel@tonic-gate char behavior_str[MAX_MSG_LEN]; 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate snprintf(behavior_str, MAX_MSG_LEN, 227*0Sstevel@tonic-gate "using default value (%d)", max_sessions); 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_OPT_ARG, optopt, 230*0Sstevel@tonic-gate optarg, behavior_str); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate break; 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate default: 237*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_BAD_OPT, optopt); 238*0Sstevel@tonic-gate (void) rdr_reject(dcsfd); 239*0Sstevel@tonic-gate exit(1); 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate /* NOTREACHED */ 242*0Sstevel@tonic-gate break; 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate DCS_DBG(DBG_ALL, "initializing %s...", cmdname); 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate init_signals(); 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate /* must be root */ 251*0Sstevel@tonic-gate if (geteuid() != 0) { 252*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_PRIV); 253*0Sstevel@tonic-gate (void) rdr_reject(dcsfd); 254*0Sstevel@tonic-gate exit(1); 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate /* 258*0Sstevel@tonic-gate * Seed the random number generator for 259*0Sstevel@tonic-gate * generating random session identifiers. 260*0Sstevel@tonic-gate */ 261*0Sstevel@tonic-gate gettimeofday(&tv, NULL); 262*0Sstevel@tonic-gate srand48(tv.tv_usec); 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate /* initialize our transport endpoint */ 265*0Sstevel@tonic-gate if (init_server(&dcs_rcv) == -1) { 266*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_INIT_ERR); 267*0Sstevel@tonic-gate (void) rdr_reject(dcsfd); 268*0Sstevel@tonic-gate exit(1); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate DCS_DBG(DBG_ALL, "%s initialized, debug level = 0x%X, " 273*0Sstevel@tonic-gate "max sessions = %d", cmdname, dcs_debug, max_sessions); 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate /* 276*0Sstevel@tonic-gate * Main service loop 277*0Sstevel@tonic-gate */ 278*0Sstevel@tonic-gate for (;;) { 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate /* wait for a connection request */ 281*0Sstevel@tonic-gate if (ses_poll(&dcs_rcv, 1, BLOCKFOREVER) == -1) { 282*0Sstevel@tonic-gate if (errno != EINTR) { 283*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_INT_ERR, "poll", 284*0Sstevel@tonic-gate strerror(errno)); 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate continue; 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate /* attempt to connect */ 290*0Sstevel@tonic-gate newfd = rdr_connect_srv(dcs_rcv.fd); 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate if ((newfd == RDR_ERROR) || (newfd == RDR_NET_ERR)) { 293*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CONNECT_ERR); 294*0Sstevel@tonic-gate continue; 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate /* process the session concurrently */ 299*0Sstevel@tonic-gate if (ses_start(newfd) == -1) { 300*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_HAND_ERR); 301*0Sstevel@tonic-gate (void) rdr_close(newfd); 302*0Sstevel@tonic-gate break; 303*0Sstevel@tonic-gate } 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate close(dcs_rcv.fd); 307*0Sstevel@tonic-gate return (1); 308*0Sstevel@tonic-gate } 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate /* 312*0Sstevel@tonic-gate * init_server: 313*0Sstevel@tonic-gate * 314*0Sstevel@tonic-gate * Perform all the operations that are required to initialize the 315*0Sstevel@tonic-gate * transport endpoint used by the DCS. After this routine succeeds, 316*0Sstevel@tonic-gate * the DCS is ready to accept session requests on its well known 317*0Sstevel@tonic-gate * port. 318*0Sstevel@tonic-gate */ 319*0Sstevel@tonic-gate static int 320*0Sstevel@tonic-gate init_server(struct pollfd *pfd) 321*0Sstevel@tonic-gate { 322*0Sstevel@tonic-gate struct servent *se; 323*0Sstevel@tonic-gate struct sockaddr_storage ss; 324*0Sstevel@tonic-gate struct sockaddr_in *sin; 325*0Sstevel@tonic-gate struct sockaddr_in6 *sin6; 326*0Sstevel@tonic-gate int req_port; 327*0Sstevel@tonic-gate int act_port; 328*0Sstevel@tonic-gate int init_status; 329*0Sstevel@tonic-gate int num_sock_opts; 330*0Sstevel@tonic-gate int sock_opts[] = { SO_REUSEADDR }; 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate assert(pfd); 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* 336*0Sstevel@tonic-gate * In standalone mode, we have to initialize the transport 337*0Sstevel@tonic-gate * endpoint for our reserved port. In daemon mode, inetd 338*0Sstevel@tonic-gate * starts the DCS and hands off STDIN_FILENO connected to 339*0Sstevel@tonic-gate * our reserved port. 340*0Sstevel@tonic-gate */ 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate if (standalone) { 343*0Sstevel@tonic-gate /* in standalone mode, init fd for reserved port */ 344*0Sstevel@tonic-gate if ((dcsfd = rdr_open(AF_INET6)) == -1) { 345*0Sstevel@tonic-gate DCS_DBG(DBG_ALL, "rdr_open failed"); 346*0Sstevel@tonic-gate } 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate pfd->fd = dcsfd; 350*0Sstevel@tonic-gate pfd->events = POLLIN | POLLPRI; 351*0Sstevel@tonic-gate pfd->revents = 0; 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate /* 354*0Sstevel@tonic-gate * Look up our service to get the reserved port number 355*0Sstevel@tonic-gate */ 356*0Sstevel@tonic-gate if ((se = getservbyname(DCS_SERVICE, "tcp")) == NULL) { 357*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_NO_SERV, DCS_SERVICE); 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gate /* use the known port if service wasn't found */ 360*0Sstevel@tonic-gate req_port = SUN_DR_PORT; 361*0Sstevel@tonic-gate } else { 362*0Sstevel@tonic-gate req_port = se->s_port; 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate /* initialize our local address */ 366*0Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)&ss; 367*0Sstevel@tonic-gate (void) memset(sin6, 0, sizeof (*sin6)); 368*0Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 369*0Sstevel@tonic-gate sin6->sin6_port = htons(req_port); 370*0Sstevel@tonic-gate sin6->sin6_addr = in6addr_any; 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate num_sock_opts = sizeof (sock_opts) / sizeof (*sock_opts); 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate init_status = rdr_init(pfd->fd, (struct sockaddr *)sin6, 375*0Sstevel@tonic-gate sock_opts, num_sock_opts, DCS_BACKLOG); 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate if (init_status != RDR_OK) { 378*0Sstevel@tonic-gate return (-1); 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate switch (ss.ss_family) { 382*0Sstevel@tonic-gate case AF_INET: 383*0Sstevel@tonic-gate DCS_DBG(DBG_ALL, "using AF_INET socket"); 384*0Sstevel@tonic-gate sin = (struct sockaddr_in *)&ss; 385*0Sstevel@tonic-gate act_port = ntohs(sin->sin_port); 386*0Sstevel@tonic-gate break; 387*0Sstevel@tonic-gate case AF_INET6: 388*0Sstevel@tonic-gate DCS_DBG(DBG_ALL, "using AF_INET6 socket"); 389*0Sstevel@tonic-gate /* sin6 already set correctly */ 390*0Sstevel@tonic-gate act_port = ntohs(sin6->sin6_port); 391*0Sstevel@tonic-gate break; 392*0Sstevel@tonic-gate default: 393*0Sstevel@tonic-gate DCS_DBG(DBG_ALL, "unknown socket type"); 394*0Sstevel@tonic-gate return (-1); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate /* check that we got the requested port */ 398*0Sstevel@tonic-gate if (req_port != act_port) { 399*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_PORT, req_port); 400*0Sstevel@tonic-gate return (-1); 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate return (0); 404*0Sstevel@tonic-gate } 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate /* 408*0Sstevel@tonic-gate * init_signals: 409*0Sstevel@tonic-gate * 410*0Sstevel@tonic-gate * Initialize signals for the current session. All signals will be 411*0Sstevel@tonic-gate * blocked with two possible exceptions. SIGINT is not blocked in 412*0Sstevel@tonic-gate * standalone mode, and ses_init_signals() is called to selectively 413*0Sstevel@tonic-gate * unblock any signals required to handle concurrent sessions. 414*0Sstevel@tonic-gate */ 415*0Sstevel@tonic-gate static void 416*0Sstevel@tonic-gate init_signals(void) 417*0Sstevel@tonic-gate { 418*0Sstevel@tonic-gate sigset_t mask; 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate /* block all signals */ 422*0Sstevel@tonic-gate sigfillset(&mask); 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate /* in standalone, allow user to abort */ 425*0Sstevel@tonic-gate if (standalone) { 426*0Sstevel@tonic-gate sigdelset(&mask, SIGINT); 427*0Sstevel@tonic-gate } 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate ses_init_signals(&mask); 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &mask, NULL); 432*0Sstevel@tonic-gate } 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate /* 436*0Sstevel@tonic-gate * dcs_dispatch_message: 437*0Sstevel@tonic-gate * 438*0Sstevel@tonic-gate * This function dispatches a message to the correct function. The 439*0Sstevel@tonic-gate * correct handler is determined by the opcode field of the message 440*0Sstevel@tonic-gate * header. 441*0Sstevel@tonic-gate */ 442*0Sstevel@tonic-gate int 443*0Sstevel@tonic-gate dcs_dispatch_message(rdr_msg_hdr_t *hdr, cfga_params_t *params) 444*0Sstevel@tonic-gate { 445*0Sstevel@tonic-gate session_t *sp; 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate assert(hdr); 449*0Sstevel@tonic-gate assert(params); 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate /* get the current session information */ 452*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 453*0Sstevel@tonic-gate ses_close(DCS_ERROR); 454*0Sstevel@tonic-gate return (-1); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate /* check the message */ 458*0Sstevel@tonic-gate if (invalid_msg(hdr)) { 459*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 460*0Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 461*0Sstevel@tonic-gate return (-1); 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate /* save the current message */ 465*0Sstevel@tonic-gate sp->curr_msg.hdr = hdr; 466*0Sstevel@tonic-gate sp->curr_msg.params = params; 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate /* 469*0Sstevel@tonic-gate * hdr->message_opcode is unsigned so don't need 470*0Sstevel@tonic-gate * to check for values less than zero 471*0Sstevel@tonic-gate */ 472*0Sstevel@tonic-gate if (hdr->message_opcode >= RDR_NUM_OPS) { 473*0Sstevel@tonic-gate dcs_unknown_op(hdr, params); 474*0Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 475*0Sstevel@tonic-gate return (-1); 476*0Sstevel@tonic-gate } 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_RECEIVE, hdr); 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* dispatch the message */ 481*0Sstevel@tonic-gate if ((*dcs_cmd[hdr->message_opcode])(hdr, params) == -1) { 482*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_FAILED); 483*0Sstevel@tonic-gate ses_close(DCS_ERROR); 484*0Sstevel@tonic-gate return (-1); 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate return (0); 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate /* 492*0Sstevel@tonic-gate * init_msg: 493*0Sstevel@tonic-gate * 494*0Sstevel@tonic-gate * Initialize the message header with information from the current 495*0Sstevel@tonic-gate * session. Fields not set directly are initialized to zero. 496*0Sstevel@tonic-gate */ 497*0Sstevel@tonic-gate void 498*0Sstevel@tonic-gate init_msg(rdr_msg_hdr_t *hdr) 499*0Sstevel@tonic-gate { 500*0Sstevel@tonic-gate session_t *sp; 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate assert(hdr); 504*0Sstevel@tonic-gate 505*0Sstevel@tonic-gate /* get the current session information */ 506*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 507*0Sstevel@tonic-gate ses_close(DCS_ERROR); 508*0Sstevel@tonic-gate return; 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate (void) memset(hdr, 0, sizeof (rdr_msg_hdr_t)); 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate /* set the session information */ 514*0Sstevel@tonic-gate hdr->random_req = sp->random_req; 515*0Sstevel@tonic-gate hdr->random_resp = sp->random_resp; 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* set the version being used */ 518*0Sstevel@tonic-gate hdr->major_version = sp->major_version; 519*0Sstevel@tonic-gate hdr->minor_version = sp->minor_version; 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate /* 524*0Sstevel@tonic-gate * invalid_msg: 525*0Sstevel@tonic-gate * 526*0Sstevel@tonic-gate * Check if the message is valid for the current session. This 527*0Sstevel@tonic-gate * is accomplished by checking various information in the header 528*0Sstevel@tonic-gate * against the information for the current session. 529*0Sstevel@tonic-gate */ 530*0Sstevel@tonic-gate static int 531*0Sstevel@tonic-gate invalid_msg(rdr_msg_hdr_t *hdr) 532*0Sstevel@tonic-gate { 533*0Sstevel@tonic-gate session_t *sp; 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate assert(hdr); 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate /* get the current session information */ 539*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 540*0Sstevel@tonic-gate ses_close(DCS_ERROR); 541*0Sstevel@tonic-gate return (-1); 542*0Sstevel@tonic-gate } 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate /* 545*0Sstevel@tonic-gate * Only perform the following checks if the message 546*0Sstevel@tonic-gate * is not a session request. The information to check 547*0Sstevel@tonic-gate * will not be set at the time a session request is 548*0Sstevel@tonic-gate * received. 549*0Sstevel@tonic-gate */ 550*0Sstevel@tonic-gate if (hdr->message_opcode != RDR_SES_REQ) { 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate /* check major and minor version */ 553*0Sstevel@tonic-gate if ((sp->major_version != hdr->major_version) || 554*0Sstevel@tonic-gate (sp->minor_version != hdr->minor_version)) { 555*0Sstevel@tonic-gate DCS_DBG(DBG_MSG, "unsupported version %d.%d", 556*0Sstevel@tonic-gate hdr->major_version, hdr->minor_version); 557*0Sstevel@tonic-gate return (-1); 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate /* check session identifiers */ 561*0Sstevel@tonic-gate if ((sp->random_req != hdr->random_req) || 562*0Sstevel@tonic-gate (sp->random_resp != hdr->random_resp)) { 563*0Sstevel@tonic-gate DCS_DBG(DBG_MSG, "invalid session identifiers: " 564*0Sstevel@tonic-gate "<%d, %d>", hdr->random_req, hdr->random_resp); 565*0Sstevel@tonic-gate return (-1); 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate return (0); 570*0Sstevel@tonic-gate } 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate 573*0Sstevel@tonic-gate /* 574*0Sstevel@tonic-gate * dcs_ses_req: 575*0Sstevel@tonic-gate * 576*0Sstevel@tonic-gate * Handle a session request message (RDR_SES_REQ). 577*0Sstevel@tonic-gate */ 578*0Sstevel@tonic-gate static int 579*0Sstevel@tonic-gate dcs_ses_req(rdr_msg_hdr_t *hdr, cfga_params_t *param) 580*0Sstevel@tonic-gate { 581*0Sstevel@tonic-gate session_t *sp; 582*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 583*0Sstevel@tonic-gate cfga_params_t reply_param; 584*0Sstevel@tonic-gate dcs_ver_t act_ver; 585*0Sstevel@tonic-gate int snd_status; 586*0Sstevel@tonic-gate static char *op_name = "session request"; 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate assert(hdr); 590*0Sstevel@tonic-gate assert(param); 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate /* get the current session information */ 593*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 594*0Sstevel@tonic-gate ses_close(DCS_ERROR); 595*0Sstevel@tonic-gate return (-1); 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate /* make sure that a session hasn't been requested yet */ 599*0Sstevel@tonic-gate if (sp->state != DCS_CONNECTED) { 600*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_SEQ_INVAL); 601*0Sstevel@tonic-gate ses_close(DCS_SES_SEQ_INVAL); 602*0Sstevel@tonic-gate return (-1); 603*0Sstevel@tonic-gate } 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate ses_setlocale(param->req.locale_str); 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate /* get the best matching version supported */ 608*0Sstevel@tonic-gate act_ver = resolve_version(hdr->major_version, hdr->minor_version); 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate /* initialize session information */ 611*0Sstevel@tonic-gate sp->random_req = hdr->random_req; 612*0Sstevel@tonic-gate sp->major_version = act_ver.major; 613*0Sstevel@tonic-gate sp->minor_version = act_ver.minor; 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate /* prepare header information */ 616*0Sstevel@tonic-gate init_msg(&reply_hdr); 617*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_SES_REQ; 618*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 619*0Sstevel@tonic-gate reply_hdr.status = DCS_OK; 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate /* prepare session request specific data */ 622*0Sstevel@tonic-gate (void) memset(&reply_param, 0, sizeof (cfga_params_t)); 623*0Sstevel@tonic-gate reply_param.req.session_id = sp->id; 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate /* send the message */ 628*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, &reply_param, 629*0Sstevel@tonic-gate DCS_SND_TIMEOUT); 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 632*0Sstevel@tonic-gate abort_handler(); 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 636*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 637*0Sstevel@tonic-gate return (-1); 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate sp->state = DCS_SES_REQ; 641*0Sstevel@tonic-gate return (0); 642*0Sstevel@tonic-gate } 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate /* 646*0Sstevel@tonic-gate * dcs_ses_estbl: 647*0Sstevel@tonic-gate * 648*0Sstevel@tonic-gate * Handle a session establishment message (RDR_SES_ESTBL). 649*0Sstevel@tonic-gate */ 650*0Sstevel@tonic-gate /* ARGSUSED */ 651*0Sstevel@tonic-gate static int 652*0Sstevel@tonic-gate dcs_ses_estbl(rdr_msg_hdr_t *hdr, cfga_params_t *param) 653*0Sstevel@tonic-gate { 654*0Sstevel@tonic-gate session_t *sp; 655*0Sstevel@tonic-gate dcs_ver_t act_ver; 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate assert(hdr); 659*0Sstevel@tonic-gate assert(param); 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate /* get the current session information */ 662*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 663*0Sstevel@tonic-gate ses_close(DCS_ERROR); 664*0Sstevel@tonic-gate return (-1); 665*0Sstevel@tonic-gate } 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate /* 668*0Sstevel@tonic-gate * Make sure that a session has not been 669*0Sstevel@tonic-gate * established yet, and that a session 670*0Sstevel@tonic-gate * request has already been processed. 671*0Sstevel@tonic-gate */ 672*0Sstevel@tonic-gate if (sp->state != DCS_SES_REQ) { 673*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_SEQ_INVAL); 674*0Sstevel@tonic-gate ses_close(DCS_SES_SEQ_INVAL); 675*0Sstevel@tonic-gate return (-1); 676*0Sstevel@tonic-gate } 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate /* get the best matching version supported */ 679*0Sstevel@tonic-gate act_ver = resolve_version(hdr->major_version, hdr->minor_version); 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate if ((act_ver.major != hdr->major_version) || 682*0Sstevel@tonic-gate (act_ver.minor != hdr->minor_version)) { 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate /* end the session because protocol not supported */ 685*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_VER_INVAL, hdr->major_version, 686*0Sstevel@tonic-gate hdr->minor_version); 687*0Sstevel@tonic-gate ses_close(DCS_VER_INVAL); 688*0Sstevel@tonic-gate return (-1); 689*0Sstevel@tonic-gate } 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate DCS_DBG(DBG_SES, "Session Established"); 692*0Sstevel@tonic-gate sp->state = DCS_SES_ESTBL; 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate return (0); 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate /* 699*0Sstevel@tonic-gate * dcs_ses_end: 700*0Sstevel@tonic-gate * 701*0Sstevel@tonic-gate * Handle a session end message (RDR_SES_END). 702*0Sstevel@tonic-gate */ 703*0Sstevel@tonic-gate static int 704*0Sstevel@tonic-gate dcs_ses_end(rdr_msg_hdr_t *hdr, cfga_params_t *param) 705*0Sstevel@tonic-gate { 706*0Sstevel@tonic-gate session_t *sp; 707*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 708*0Sstevel@tonic-gate cfga_params_t reply_param; 709*0Sstevel@tonic-gate int snd_status; 710*0Sstevel@tonic-gate static char *op_name = "session end"; 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate assert(hdr); 714*0Sstevel@tonic-gate assert(param); 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate /* get the current session information */ 717*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 718*0Sstevel@tonic-gate ses_close(DCS_ERROR); 719*0Sstevel@tonic-gate return (-1); 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate /* 723*0Sstevel@tonic-gate * Session end is valid from any state. However, only 724*0Sstevel@tonic-gate * send back a reply if the error code is zero. A non-zero 725*0Sstevel@tonic-gate * error code indicates that the session is being terminated 726*0Sstevel@tonic-gate * under an error condition, and no acknowledgement is 727*0Sstevel@tonic-gate * required. 728*0Sstevel@tonic-gate */ 729*0Sstevel@tonic-gate if (param->end.error_code == 0) { 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate /* prepare header information */ 732*0Sstevel@tonic-gate init_msg(&reply_hdr); 733*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_SES_END; 734*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 735*0Sstevel@tonic-gate reply_hdr.status = DCS_OK; 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate /* return empty data - no information needed in reply */ 738*0Sstevel@tonic-gate (void) memset(&reply_param, 0, sizeof (cfga_params_t)); 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, &reply_param, 743*0Sstevel@tonic-gate DCS_SND_TIMEOUT); 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 746*0Sstevel@tonic-gate abort_handler(); 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 750*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate sp->state = DCS_SES_END; 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 757*0Sstevel@tonic-gate } 758*0Sstevel@tonic-gate 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate /* 761*0Sstevel@tonic-gate * dcs_change_state: 762*0Sstevel@tonic-gate * 763*0Sstevel@tonic-gate * Handle a change state request message (RDR_CONF_CHANGE_STATE). 764*0Sstevel@tonic-gate */ 765*0Sstevel@tonic-gate static int 766*0Sstevel@tonic-gate dcs_change_state(rdr_msg_hdr_t *hdr, cfga_params_t *param) 767*0Sstevel@tonic-gate { 768*0Sstevel@tonic-gate session_t *sp; 769*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 770*0Sstevel@tonic-gate change_state_params_t *op_data; 771*0Sstevel@tonic-gate struct cfga_confirm local_conf_cb; 772*0Sstevel@tonic-gate struct cfga_msg local_msg_cb; 773*0Sstevel@tonic-gate int cfga_status = 0; 774*0Sstevel@tonic-gate int snd_status; 775*0Sstevel@tonic-gate char *err_str; 776*0Sstevel@tonic-gate unsigned int curr_attempt; 777*0Sstevel@tonic-gate unsigned int num_attempts; 778*0Sstevel@tonic-gate char retry_msg[MAX_MSG_LEN]; 779*0Sstevel@tonic-gate static char *op_name = "config_change_state"; 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate assert(hdr); 783*0Sstevel@tonic-gate assert(param); 784*0Sstevel@tonic-gate 785*0Sstevel@tonic-gate /* get the current session information */ 786*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 787*0Sstevel@tonic-gate ses_close(DCS_ERROR); 788*0Sstevel@tonic-gate return (-1); 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate op_data = ¶m->change; 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate /* make sure we have a session established */ 794*0Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 795*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 796*0Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 797*0Sstevel@tonic-gate return (-1); 798*0Sstevel@tonic-gate } 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate /* initialize local confirm callback */ 801*0Sstevel@tonic-gate local_conf_cb.confirm = dcs_confirm_callback; 802*0Sstevel@tonic-gate local_conf_cb.appdata_ptr = (void *)op_data->confp; 803*0Sstevel@tonic-gate 804*0Sstevel@tonic-gate /* initialize local message callback */ 805*0Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 806*0Sstevel@tonic-gate local_msg_cb.appdata_ptr = (void *)op_data->msgp; 807*0Sstevel@tonic-gate 808*0Sstevel@tonic-gate /* verify retry value */ 809*0Sstevel@tonic-gate if (op_data->retries < 0) { 810*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_RETRY_VAL, op_data->retries); 811*0Sstevel@tonic-gate op_data->retries = 0; 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate /* verify timeout value */ 815*0Sstevel@tonic-gate if (op_data->timeval < 0) { 816*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_TIME_VAL, op_data->timeval); 817*0Sstevel@tonic-gate op_data->timeval = 0; 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate num_attempts = 1 + op_data->retries; 821*0Sstevel@tonic-gate curr_attempt = 0; 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate while (curr_attempt < num_attempts) { 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate /* don't sleep the first time around */ 826*0Sstevel@tonic-gate if (curr_attempt != 0) { 827*0Sstevel@tonic-gate 828*0Sstevel@tonic-gate /* log the error message and alert the user */ 829*0Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 830*0Sstevel@tonic-gate if (err_str) { 831*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, 832*0Sstevel@tonic-gate err_str); 833*0Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, 834*0Sstevel@tonic-gate err_str); 835*0Sstevel@tonic-gate free((void *)err_str); 836*0Sstevel@tonic-gate } else { 837*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_UNKNOWN); 838*0Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, 839*0Sstevel@tonic-gate dcs_strerror(DCS_CFGA_UNKNOWN)); 840*0Sstevel@tonic-gate } 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 843*0Sstevel@tonic-gate free((void *)*op_data->errstring); 844*0Sstevel@tonic-gate *op_data->errstring = NULL; 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate /* sleep with abort enabled */ 848*0Sstevel@tonic-gate ses_sleep(op_data->timeval); 849*0Sstevel@tonic-gate 850*0Sstevel@tonic-gate /* log the retry attempt and alert the user */ 851*0Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_RETRY, curr_attempt); 852*0Sstevel@tonic-gate snprintf(retry_msg, MAX_MSG_LEN, 853*0Sstevel@tonic-gate dcs_strerror(DCS_RETRY), curr_attempt); 854*0Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, retry_msg); 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate /* 860*0Sstevel@tonic-gate * Call into libcfgadm 861*0Sstevel@tonic-gate */ 862*0Sstevel@tonic-gate ses_abort_enable(); 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate cfga_status = config_change_state(op_data->state_change, 865*0Sstevel@tonic-gate op_data->num_ap_ids, op_data->ap_ids, op_data->options, 866*0Sstevel@tonic-gate &local_conf_cb, &local_msg_cb, op_data->errstring, 867*0Sstevel@tonic-gate op_data->flags); 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate ses_abort_disable(); 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate /* 872*0Sstevel@tonic-gate * Retry only the operations that have a chance to 873*0Sstevel@tonic-gate * succeed if retried. All libcfgadm errors not 874*0Sstevel@tonic-gate * included below will always fail, regardless of 875*0Sstevel@tonic-gate * a retry. 876*0Sstevel@tonic-gate */ 877*0Sstevel@tonic-gate if ((cfga_status != CFGA_BUSY) && 878*0Sstevel@tonic-gate (cfga_status != CFGA_SYSTEM_BUSY) && 879*0Sstevel@tonic-gate (cfga_status != CFGA_ERROR)) { 880*0Sstevel@tonic-gate break; 881*0Sstevel@tonic-gate } 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate /* prepare for another attempt */ 884*0Sstevel@tonic-gate ++curr_attempt; 885*0Sstevel@tonic-gate } 886*0Sstevel@tonic-gate 887*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 888*0Sstevel@tonic-gate 889*0Sstevel@tonic-gate /* log any libcfgadm errors */ 890*0Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 891*0Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 892*0Sstevel@tonic-gate if (err_str) { 893*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 894*0Sstevel@tonic-gate free((void *)err_str); 895*0Sstevel@tonic-gate } 896*0Sstevel@tonic-gate } 897*0Sstevel@tonic-gate 898*0Sstevel@tonic-gate /* prepare header information */ 899*0Sstevel@tonic-gate init_msg(&reply_hdr); 900*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_CHANGE_STATE; 901*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 902*0Sstevel@tonic-gate reply_hdr.status = cfga_status; 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 905*0Sstevel@tonic-gate 906*0Sstevel@tonic-gate /* send the message */ 907*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 908*0Sstevel@tonic-gate 909*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 910*0Sstevel@tonic-gate abort_handler(); 911*0Sstevel@tonic-gate } 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 914*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 915*0Sstevel@tonic-gate } 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate /* clean up */ 918*0Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 919*0Sstevel@tonic-gate free((void *)*op_data->errstring); 920*0Sstevel@tonic-gate *op_data->errstring = NULL; 921*0Sstevel@tonic-gate } 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 924*0Sstevel@tonic-gate } 925*0Sstevel@tonic-gate 926*0Sstevel@tonic-gate 927*0Sstevel@tonic-gate /* 928*0Sstevel@tonic-gate * dcs_private_func: 929*0Sstevel@tonic-gate * 930*0Sstevel@tonic-gate * Handle a private function request message (RDR_CONF_PRIVATE_FUNC). 931*0Sstevel@tonic-gate */ 932*0Sstevel@tonic-gate static int 933*0Sstevel@tonic-gate dcs_private_func(rdr_msg_hdr_t *hdr, cfga_params_t *param) 934*0Sstevel@tonic-gate { 935*0Sstevel@tonic-gate session_t *sp; 936*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 937*0Sstevel@tonic-gate private_func_params_t *op_data; 938*0Sstevel@tonic-gate struct cfga_confirm local_conf_cb; 939*0Sstevel@tonic-gate struct cfga_msg local_msg_cb; 940*0Sstevel@tonic-gate int cfga_status; 941*0Sstevel@tonic-gate int snd_status; 942*0Sstevel@tonic-gate char *err_str; 943*0Sstevel@tonic-gate static char *op_name = "config_private_func"; 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate 946*0Sstevel@tonic-gate assert(hdr); 947*0Sstevel@tonic-gate assert(param); 948*0Sstevel@tonic-gate 949*0Sstevel@tonic-gate /* get the current session information */ 950*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 951*0Sstevel@tonic-gate ses_close(DCS_ERROR); 952*0Sstevel@tonic-gate return (-1); 953*0Sstevel@tonic-gate } 954*0Sstevel@tonic-gate 955*0Sstevel@tonic-gate op_data = ¶m->priv; 956*0Sstevel@tonic-gate 957*0Sstevel@tonic-gate /* make sure we have a session established */ 958*0Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 959*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 960*0Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 961*0Sstevel@tonic-gate return (-1); 962*0Sstevel@tonic-gate } 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate /* initialize local confirm callback */ 965*0Sstevel@tonic-gate local_conf_cb.confirm = dcs_confirm_callback; 966*0Sstevel@tonic-gate local_conf_cb.appdata_ptr = (void *)op_data->confp; 967*0Sstevel@tonic-gate 968*0Sstevel@tonic-gate /* initialize local message callback */ 969*0Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 970*0Sstevel@tonic-gate local_msg_cb.appdata_ptr = (void *)op_data->msgp; 971*0Sstevel@tonic-gate 972*0Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 973*0Sstevel@tonic-gate 974*0Sstevel@tonic-gate /* 975*0Sstevel@tonic-gate * Call into libcfgadm 976*0Sstevel@tonic-gate */ 977*0Sstevel@tonic-gate ses_abort_enable(); 978*0Sstevel@tonic-gate 979*0Sstevel@tonic-gate cfga_status = config_private_func(op_data->function, 980*0Sstevel@tonic-gate op_data->num_ap_ids, op_data->ap_ids, op_data->options, 981*0Sstevel@tonic-gate &local_conf_cb, &local_msg_cb, op_data->errstring, op_data->flags); 982*0Sstevel@tonic-gate 983*0Sstevel@tonic-gate ses_abort_disable(); 984*0Sstevel@tonic-gate 985*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 986*0Sstevel@tonic-gate 987*0Sstevel@tonic-gate /* log any libcfgadm errors */ 988*0Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 989*0Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 990*0Sstevel@tonic-gate if (err_str) { 991*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 992*0Sstevel@tonic-gate free((void *)err_str); 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate } 995*0Sstevel@tonic-gate 996*0Sstevel@tonic-gate /* prepare header information */ 997*0Sstevel@tonic-gate init_msg(&reply_hdr); 998*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_PRIVATE_FUNC; 999*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 1000*0Sstevel@tonic-gate reply_hdr.status = cfga_status; 1001*0Sstevel@tonic-gate 1002*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 1003*0Sstevel@tonic-gate 1004*0Sstevel@tonic-gate /* send the message */ 1005*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 1006*0Sstevel@tonic-gate 1007*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1008*0Sstevel@tonic-gate abort_handler(); 1009*0Sstevel@tonic-gate } 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1012*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1013*0Sstevel@tonic-gate } 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 1016*0Sstevel@tonic-gate free((void *)*op_data->errstring); 1017*0Sstevel@tonic-gate *op_data->errstring = NULL; 1018*0Sstevel@tonic-gate } 1019*0Sstevel@tonic-gate 1020*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 1021*0Sstevel@tonic-gate } 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate /* 1025*0Sstevel@tonic-gate * dcs_test: 1026*0Sstevel@tonic-gate * 1027*0Sstevel@tonic-gate * Handle a test request message (RDR_CONF_TEST). 1028*0Sstevel@tonic-gate */ 1029*0Sstevel@tonic-gate static int 1030*0Sstevel@tonic-gate dcs_test(rdr_msg_hdr_t *hdr, cfga_params_t *param) 1031*0Sstevel@tonic-gate { 1032*0Sstevel@tonic-gate session_t *sp; 1033*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 1034*0Sstevel@tonic-gate test_params_t *op_data; 1035*0Sstevel@tonic-gate struct cfga_msg local_msg_cb; 1036*0Sstevel@tonic-gate int cfga_status; 1037*0Sstevel@tonic-gate int snd_status; 1038*0Sstevel@tonic-gate char *err_str; 1039*0Sstevel@tonic-gate static char *op_name = "config_test"; 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate assert(hdr); 1043*0Sstevel@tonic-gate assert(param); 1044*0Sstevel@tonic-gate 1045*0Sstevel@tonic-gate /* get the current session information */ 1046*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1047*0Sstevel@tonic-gate ses_close(DCS_ERROR); 1048*0Sstevel@tonic-gate return (-1); 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate op_data = ¶m->test; 1052*0Sstevel@tonic-gate 1053*0Sstevel@tonic-gate /* make sure we have a session established */ 1054*0Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 1055*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 1056*0Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 1057*0Sstevel@tonic-gate return (-1); 1058*0Sstevel@tonic-gate } 1059*0Sstevel@tonic-gate 1060*0Sstevel@tonic-gate /* initialize local message callback */ 1061*0Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 1062*0Sstevel@tonic-gate local_msg_cb.appdata_ptr = op_data->msgp; 1063*0Sstevel@tonic-gate 1064*0Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 1065*0Sstevel@tonic-gate 1066*0Sstevel@tonic-gate /* 1067*0Sstevel@tonic-gate * Call into libcfgadm 1068*0Sstevel@tonic-gate */ 1069*0Sstevel@tonic-gate ses_abort_enable(); 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate cfga_status = config_test(op_data->num_ap_ids, op_data->ap_ids, 1072*0Sstevel@tonic-gate op_data->options, &local_msg_cb, op_data->errstring, 1073*0Sstevel@tonic-gate op_data->flags); 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate ses_abort_disable(); 1076*0Sstevel@tonic-gate 1077*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 1078*0Sstevel@tonic-gate 1079*0Sstevel@tonic-gate /* log any libcfgadm errors */ 1080*0Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 1081*0Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 1082*0Sstevel@tonic-gate if (err_str) { 1083*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 1084*0Sstevel@tonic-gate free((void *)err_str); 1085*0Sstevel@tonic-gate } 1086*0Sstevel@tonic-gate } 1087*0Sstevel@tonic-gate 1088*0Sstevel@tonic-gate /* prepare header information */ 1089*0Sstevel@tonic-gate init_msg(&reply_hdr); 1090*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_TEST; 1091*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 1092*0Sstevel@tonic-gate reply_hdr.status = cfga_status; 1093*0Sstevel@tonic-gate 1094*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 1095*0Sstevel@tonic-gate 1096*0Sstevel@tonic-gate /* send the message */ 1097*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1100*0Sstevel@tonic-gate abort_handler(); 1101*0Sstevel@tonic-gate } 1102*0Sstevel@tonic-gate 1103*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1104*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1105*0Sstevel@tonic-gate } 1106*0Sstevel@tonic-gate 1107*0Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 1108*0Sstevel@tonic-gate free((void *)*op_data->errstring); 1109*0Sstevel@tonic-gate *op_data->errstring = NULL; 1110*0Sstevel@tonic-gate } 1111*0Sstevel@tonic-gate 1112*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 1113*0Sstevel@tonic-gate } 1114*0Sstevel@tonic-gate 1115*0Sstevel@tonic-gate 1116*0Sstevel@tonic-gate /* 1117*0Sstevel@tonic-gate * dcs_list_ext: 1118*0Sstevel@tonic-gate * 1119*0Sstevel@tonic-gate * Handle a list request message (RDR_CONF_LIST_EXT). 1120*0Sstevel@tonic-gate */ 1121*0Sstevel@tonic-gate static int 1122*0Sstevel@tonic-gate dcs_list_ext(rdr_msg_hdr_t *hdr, cfga_params_t *param) 1123*0Sstevel@tonic-gate { 1124*0Sstevel@tonic-gate session_t *sp; 1125*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 1126*0Sstevel@tonic-gate list_ext_params_t *op_data; 1127*0Sstevel@tonic-gate int cfga_status; 1128*0Sstevel@tonic-gate int snd_status; 1129*0Sstevel@tonic-gate char *err_str; 1130*0Sstevel@tonic-gate static char *op_name = "config_list_ext"; 1131*0Sstevel@tonic-gate cfga_list_data_t *ap_ids; 1132*0Sstevel@tonic-gate 1133*0Sstevel@tonic-gate 1134*0Sstevel@tonic-gate assert(hdr); 1135*0Sstevel@tonic-gate assert(param); 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate /* get the current session information */ 1138*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1139*0Sstevel@tonic-gate ses_close(DCS_ERROR); 1140*0Sstevel@tonic-gate return (-1); 1141*0Sstevel@tonic-gate } 1142*0Sstevel@tonic-gate 1143*0Sstevel@tonic-gate op_data = ¶m->list_ext; 1144*0Sstevel@tonic-gate 1145*0Sstevel@tonic-gate /* make sure we have a session established */ 1146*0Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 1147*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 1148*0Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 1149*0Sstevel@tonic-gate return (-1); 1150*0Sstevel@tonic-gate } 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate /* 1153*0Sstevel@tonic-gate * Make sure that we can retrieve the data 1154*0Sstevel@tonic-gate * from libcfgadm. If not, report the error. 1155*0Sstevel@tonic-gate */ 1156*0Sstevel@tonic-gate if (op_data->ap_id_list == NULL) { 1157*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 1158*0Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 1159*0Sstevel@tonic-gate return (-1); 1160*0Sstevel@tonic-gate } 1161*0Sstevel@tonic-gate 1162*0Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate /* 1165*0Sstevel@tonic-gate * Call into libcfgadm 1166*0Sstevel@tonic-gate */ 1167*0Sstevel@tonic-gate ses_abort_enable(); 1168*0Sstevel@tonic-gate 1169*0Sstevel@tonic-gate cfga_status = config_list_ext(op_data->num_ap_ids, op_data->ap_ids, 1170*0Sstevel@tonic-gate &ap_ids, op_data->nlist, op_data->options, op_data->listopts, 1171*0Sstevel@tonic-gate op_data->errstring, op_data->flags); 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate ses_abort_disable(); 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 1176*0Sstevel@tonic-gate 1177*0Sstevel@tonic-gate /* 1178*0Sstevel@tonic-gate * Log any libcfgadm errors at a low priority level. 1179*0Sstevel@tonic-gate * Since a status request does not modify the system 1180*0Sstevel@tonic-gate * in any way, we do not need to worry about these 1181*0Sstevel@tonic-gate * errors here on the host. 1182*0Sstevel@tonic-gate */ 1183*0Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 1184*0Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 1185*0Sstevel@tonic-gate if (err_str) { 1186*0Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_CFGA_ERR, op_name, err_str); 1187*0Sstevel@tonic-gate free((void *)err_str); 1188*0Sstevel@tonic-gate } 1189*0Sstevel@tonic-gate } 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate /* 1192*0Sstevel@tonic-gate * Filter ap ids to return only appropriate information 1193*0Sstevel@tonic-gate */ 1194*0Sstevel@tonic-gate filter_list_data(op_data->permissions, op_data->nlist, ap_ids); 1195*0Sstevel@tonic-gate 1196*0Sstevel@tonic-gate /* if all aps were filtered out, return an error */ 1197*0Sstevel@tonic-gate if ((cfga_status == CFGA_OK) && (*op_data->nlist == 0)) { 1198*0Sstevel@tonic-gate cfga_status = CFGA_APID_NOEXIST; 1199*0Sstevel@tonic-gate } 1200*0Sstevel@tonic-gate 1201*0Sstevel@tonic-gate /* calculate the sort order */ 1202*0Sstevel@tonic-gate if (cfga_status == CFGA_OK) { 1203*0Sstevel@tonic-gate 1204*0Sstevel@tonic-gate *op_data->ap_id_list = generate_sort_order(ap_ids, 1205*0Sstevel@tonic-gate *op_data->nlist); 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gate if (*op_data->ap_id_list == NULL) { 1208*0Sstevel@tonic-gate cfga_status = CFGA_LIB_ERROR; 1209*0Sstevel@tonic-gate } 1210*0Sstevel@tonic-gate } 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gate /* ensure that nlist is 0 for errors */ 1213*0Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 1214*0Sstevel@tonic-gate *op_data->nlist = 0; 1215*0Sstevel@tonic-gate } 1216*0Sstevel@tonic-gate 1217*0Sstevel@tonic-gate /* prepare header information */ 1218*0Sstevel@tonic-gate init_msg(&reply_hdr); 1219*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_LIST_EXT; 1220*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 1221*0Sstevel@tonic-gate reply_hdr.status = cfga_status; 1222*0Sstevel@tonic-gate 1223*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 1224*0Sstevel@tonic-gate 1225*0Sstevel@tonic-gate /* send the message */ 1226*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 1227*0Sstevel@tonic-gate 1228*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1229*0Sstevel@tonic-gate abort_handler(); 1230*0Sstevel@tonic-gate } 1231*0Sstevel@tonic-gate 1232*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1233*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1234*0Sstevel@tonic-gate } 1235*0Sstevel@tonic-gate 1236*0Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 1237*0Sstevel@tonic-gate free((void *)*op_data->errstring); 1238*0Sstevel@tonic-gate *op_data->errstring = NULL; 1239*0Sstevel@tonic-gate } 1240*0Sstevel@tonic-gate 1241*0Sstevel@tonic-gate if (ap_ids != NULL) { 1242*0Sstevel@tonic-gate free((void *)ap_ids); 1243*0Sstevel@tonic-gate } 1244*0Sstevel@tonic-gate 1245*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 1246*0Sstevel@tonic-gate } 1247*0Sstevel@tonic-gate 1248*0Sstevel@tonic-gate 1249*0Sstevel@tonic-gate /* 1250*0Sstevel@tonic-gate * dcs_help: 1251*0Sstevel@tonic-gate * 1252*0Sstevel@tonic-gate * Handle a help request message (RDR_CONF_HELP). 1253*0Sstevel@tonic-gate */ 1254*0Sstevel@tonic-gate static int 1255*0Sstevel@tonic-gate dcs_help(rdr_msg_hdr_t *hdr, cfga_params_t *param) 1256*0Sstevel@tonic-gate { 1257*0Sstevel@tonic-gate session_t *sp; 1258*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 1259*0Sstevel@tonic-gate help_params_t *op_data; 1260*0Sstevel@tonic-gate struct cfga_msg local_msg_cb; 1261*0Sstevel@tonic-gate int cfga_status; 1262*0Sstevel@tonic-gate int snd_status; 1263*0Sstevel@tonic-gate char *err_str; 1264*0Sstevel@tonic-gate static char *op_name = "config_help"; 1265*0Sstevel@tonic-gate 1266*0Sstevel@tonic-gate 1267*0Sstevel@tonic-gate assert(hdr); 1268*0Sstevel@tonic-gate assert(param); 1269*0Sstevel@tonic-gate 1270*0Sstevel@tonic-gate /* get the current session information */ 1271*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1272*0Sstevel@tonic-gate ses_close(DCS_ERROR); 1273*0Sstevel@tonic-gate return (-1); 1274*0Sstevel@tonic-gate } 1275*0Sstevel@tonic-gate 1276*0Sstevel@tonic-gate op_data = ¶m->help; 1277*0Sstevel@tonic-gate 1278*0Sstevel@tonic-gate /* make sure we have a session established */ 1279*0Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 1280*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 1281*0Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 1282*0Sstevel@tonic-gate return (-1); 1283*0Sstevel@tonic-gate } 1284*0Sstevel@tonic-gate 1285*0Sstevel@tonic-gate /* initialize local message callback */ 1286*0Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 1287*0Sstevel@tonic-gate local_msg_cb.appdata_ptr = op_data->msgp; 1288*0Sstevel@tonic-gate 1289*0Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 1290*0Sstevel@tonic-gate 1291*0Sstevel@tonic-gate /* 1292*0Sstevel@tonic-gate * Call into libcfgadm 1293*0Sstevel@tonic-gate */ 1294*0Sstevel@tonic-gate ses_abort_enable(); 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate cfga_status = config_help(op_data->num_ap_ids, op_data->ap_ids, 1297*0Sstevel@tonic-gate &local_msg_cb, op_data->options, op_data->flags); 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate ses_abort_disable(); 1300*0Sstevel@tonic-gate 1301*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 1302*0Sstevel@tonic-gate 1303*0Sstevel@tonic-gate /* 1304*0Sstevel@tonic-gate * Log any libcfgadm errors at a low priority level. 1305*0Sstevel@tonic-gate * Since a help request does not modify the system 1306*0Sstevel@tonic-gate * in any way, we do not need to worry about these 1307*0Sstevel@tonic-gate * errors here on the host. 1308*0Sstevel@tonic-gate */ 1309*0Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 1310*0Sstevel@tonic-gate err_str = dcs_cfga_str(NULL, cfga_status); 1311*0Sstevel@tonic-gate if (err_str) { 1312*0Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_CFGA_ERR, op_name, err_str); 1313*0Sstevel@tonic-gate free((void *)err_str); 1314*0Sstevel@tonic-gate } 1315*0Sstevel@tonic-gate } 1316*0Sstevel@tonic-gate 1317*0Sstevel@tonic-gate /* prepare header information */ 1318*0Sstevel@tonic-gate init_msg(&reply_hdr); 1319*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_HELP; 1320*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 1321*0Sstevel@tonic-gate reply_hdr.status = cfga_status; 1322*0Sstevel@tonic-gate 1323*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 1324*0Sstevel@tonic-gate 1325*0Sstevel@tonic-gate /* send the message */ 1326*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 1327*0Sstevel@tonic-gate 1328*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1329*0Sstevel@tonic-gate abort_handler(); 1330*0Sstevel@tonic-gate } 1331*0Sstevel@tonic-gate 1332*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1333*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1334*0Sstevel@tonic-gate } 1335*0Sstevel@tonic-gate 1336*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 1337*0Sstevel@tonic-gate } 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate 1340*0Sstevel@tonic-gate /* 1341*0Sstevel@tonic-gate * dcs_ap_id_cmp: 1342*0Sstevel@tonic-gate * 1343*0Sstevel@tonic-gate * Handle an attachment point comparison request message (RDR_AP_ID_CMP). 1344*0Sstevel@tonic-gate */ 1345*0Sstevel@tonic-gate static int 1346*0Sstevel@tonic-gate dcs_ap_id_cmp(rdr_msg_hdr_t *hdr, cfga_params_t *param) 1347*0Sstevel@tonic-gate { 1348*0Sstevel@tonic-gate session_t *sp; 1349*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 1350*0Sstevel@tonic-gate ap_id_cmp_params_t *op_data; 1351*0Sstevel@tonic-gate int snd_status; 1352*0Sstevel@tonic-gate int cmp_result; 1353*0Sstevel@tonic-gate static char *op_name = "config_ap_id_cmp"; 1354*0Sstevel@tonic-gate 1355*0Sstevel@tonic-gate 1356*0Sstevel@tonic-gate assert(hdr); 1357*0Sstevel@tonic-gate assert(param); 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate /* get the current session information */ 1360*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1361*0Sstevel@tonic-gate ses_close(DCS_ERROR); 1362*0Sstevel@tonic-gate return (-1); 1363*0Sstevel@tonic-gate } 1364*0Sstevel@tonic-gate 1365*0Sstevel@tonic-gate op_data = ¶m->cmp; 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate /* make sure we have a session established */ 1368*0Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 1369*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 1370*0Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 1371*0Sstevel@tonic-gate return (-1); 1372*0Sstevel@tonic-gate } 1373*0Sstevel@tonic-gate 1374*0Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 1375*0Sstevel@tonic-gate 1376*0Sstevel@tonic-gate /* 1377*0Sstevel@tonic-gate * Call into libcfgadm 1378*0Sstevel@tonic-gate */ 1379*0Sstevel@tonic-gate ses_abort_enable(); 1380*0Sstevel@tonic-gate 1381*0Sstevel@tonic-gate cmp_result = config_ap_id_cmp(op_data->ap_log_id1, op_data->ap_log_id2); 1382*0Sstevel@tonic-gate 1383*0Sstevel@tonic-gate ses_abort_disable(); 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 1386*0Sstevel@tonic-gate 1387*0Sstevel@tonic-gate /* prepare header information */ 1388*0Sstevel@tonic-gate init_msg(&reply_hdr); 1389*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_AP_ID_CMP; 1390*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 1391*0Sstevel@tonic-gate 1392*0Sstevel@tonic-gate /* 1393*0Sstevel@tonic-gate * Return result of comparison as error code. 1394*0Sstevel@tonic-gate * Since all values are valid, it is impossible 1395*0Sstevel@tonic-gate * to report an error. 1396*0Sstevel@tonic-gate */ 1397*0Sstevel@tonic-gate reply_hdr.status = cmp_result; 1398*0Sstevel@tonic-gate 1399*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 1400*0Sstevel@tonic-gate 1401*0Sstevel@tonic-gate /* send the message */ 1402*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1405*0Sstevel@tonic-gate abort_handler(); 1406*0Sstevel@tonic-gate } 1407*0Sstevel@tonic-gate 1408*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1409*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1410*0Sstevel@tonic-gate } 1411*0Sstevel@tonic-gate 1412*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 1413*0Sstevel@tonic-gate } 1414*0Sstevel@tonic-gate 1415*0Sstevel@tonic-gate 1416*0Sstevel@tonic-gate /* 1417*0Sstevel@tonic-gate * dcs_abort_cmd: 1418*0Sstevel@tonic-gate * 1419*0Sstevel@tonic-gate * Handle an abort request message (RDR_CONF_ABORT_CMD). 1420*0Sstevel@tonic-gate */ 1421*0Sstevel@tonic-gate /* ARGSUSED */ 1422*0Sstevel@tonic-gate static int 1423*0Sstevel@tonic-gate dcs_abort_cmd(rdr_msg_hdr_t *hdr, cfga_params_t *param) 1424*0Sstevel@tonic-gate { 1425*0Sstevel@tonic-gate session_t *sp; 1426*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 1427*0Sstevel@tonic-gate abort_cmd_params_t *op_data; 1428*0Sstevel@tonic-gate int op_status = RDR_SUCCESS; 1429*0Sstevel@tonic-gate int snd_status; 1430*0Sstevel@tonic-gate static char *op_name = "abort command"; 1431*0Sstevel@tonic-gate 1432*0Sstevel@tonic-gate 1433*0Sstevel@tonic-gate assert(hdr); 1434*0Sstevel@tonic-gate assert(param); 1435*0Sstevel@tonic-gate 1436*0Sstevel@tonic-gate /* get the current session information */ 1437*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1438*0Sstevel@tonic-gate ses_close(DCS_ERROR); 1439*0Sstevel@tonic-gate return (-1); 1440*0Sstevel@tonic-gate } 1441*0Sstevel@tonic-gate 1442*0Sstevel@tonic-gate op_data = (abort_cmd_params_t *)param; 1443*0Sstevel@tonic-gate 1444*0Sstevel@tonic-gate op_status = ses_abort(op_data->session_id); 1445*0Sstevel@tonic-gate 1446*0Sstevel@tonic-gate if (op_status == -1) { 1447*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_ABORT_ERR, op_data->session_id); 1448*0Sstevel@tonic-gate } 1449*0Sstevel@tonic-gate 1450*0Sstevel@tonic-gate /* prepare header information */ 1451*0Sstevel@tonic-gate init_msg(&reply_hdr); 1452*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_ABORT_CMD; 1453*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 1454*0Sstevel@tonic-gate reply_hdr.status = op_status; 1455*0Sstevel@tonic-gate 1456*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 1457*0Sstevel@tonic-gate 1458*0Sstevel@tonic-gate /* send the message */ 1459*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 1460*0Sstevel@tonic-gate 1461*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1462*0Sstevel@tonic-gate abort_handler(); 1463*0Sstevel@tonic-gate } 1464*0Sstevel@tonic-gate 1465*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1466*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1467*0Sstevel@tonic-gate } 1468*0Sstevel@tonic-gate 1469*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 1470*0Sstevel@tonic-gate 1471*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 1472*0Sstevel@tonic-gate } 1473*0Sstevel@tonic-gate 1474*0Sstevel@tonic-gate 1475*0Sstevel@tonic-gate /* 1476*0Sstevel@tonic-gate * dcs_rsrc_info: 1477*0Sstevel@tonic-gate * 1478*0Sstevel@tonic-gate * Handle a resource info request message (RDR_RSRC_INFO). 1479*0Sstevel@tonic-gate */ 1480*0Sstevel@tonic-gate static int 1481*0Sstevel@tonic-gate dcs_rsrc_info(rdr_msg_hdr_t *hdr, cfga_params_t *param) 1482*0Sstevel@tonic-gate { 1483*0Sstevel@tonic-gate session_t *sp; 1484*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 1485*0Sstevel@tonic-gate rsrc_info_params_t *op_data; 1486*0Sstevel@tonic-gate int rsrc_status; 1487*0Sstevel@tonic-gate int snd_status; 1488*0Sstevel@tonic-gate static char *op_name = "resource info init"; 1489*0Sstevel@tonic-gate 1490*0Sstevel@tonic-gate assert(hdr); 1491*0Sstevel@tonic-gate assert(param); 1492*0Sstevel@tonic-gate 1493*0Sstevel@tonic-gate /* get the current session information */ 1494*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1495*0Sstevel@tonic-gate ses_close(DCS_ERROR); 1496*0Sstevel@tonic-gate return (-1); 1497*0Sstevel@tonic-gate } 1498*0Sstevel@tonic-gate 1499*0Sstevel@tonic-gate op_data = (rsrc_info_params_t *)¶m->rsrc_info; 1500*0Sstevel@tonic-gate 1501*0Sstevel@tonic-gate /* make sure we have a session established */ 1502*0Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 1503*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 1504*0Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 1505*0Sstevel@tonic-gate return (-1); 1506*0Sstevel@tonic-gate } 1507*0Sstevel@tonic-gate 1508*0Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 1509*0Sstevel@tonic-gate 1510*0Sstevel@tonic-gate /* 1511*0Sstevel@tonic-gate * Request resource info data. 1512*0Sstevel@tonic-gate */ 1513*0Sstevel@tonic-gate ses_abort_enable(); 1514*0Sstevel@tonic-gate 1515*0Sstevel@tonic-gate rsrc_status = ri_init(op_data->num_ap_ids, op_data->ap_ids, 1516*0Sstevel@tonic-gate op_data->flags, &op_data->hdl); 1517*0Sstevel@tonic-gate 1518*0Sstevel@tonic-gate ses_abort_disable(); 1519*0Sstevel@tonic-gate 1520*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 1521*0Sstevel@tonic-gate 1522*0Sstevel@tonic-gate /* log errors */ 1523*0Sstevel@tonic-gate if (rsrc_status != RI_SUCCESS) { 1524*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_RSRC_ERR, rsrc_status); 1525*0Sstevel@tonic-gate } 1526*0Sstevel@tonic-gate 1527*0Sstevel@tonic-gate /* prepare header information */ 1528*0Sstevel@tonic-gate init_msg(&reply_hdr); 1529*0Sstevel@tonic-gate reply_hdr.message_opcode = RDR_RSRC_INFO; 1530*0Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 1531*0Sstevel@tonic-gate reply_hdr.status = rsrc_status; 1532*0Sstevel@tonic-gate 1533*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 1534*0Sstevel@tonic-gate 1535*0Sstevel@tonic-gate /* send the message */ 1536*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 1537*0Sstevel@tonic-gate 1538*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1539*0Sstevel@tonic-gate abort_handler(); 1540*0Sstevel@tonic-gate } 1541*0Sstevel@tonic-gate 1542*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1543*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1544*0Sstevel@tonic-gate } 1545*0Sstevel@tonic-gate 1546*0Sstevel@tonic-gate ri_fini(op_data->hdl); 1547*0Sstevel@tonic-gate 1548*0Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 1549*0Sstevel@tonic-gate } 1550*0Sstevel@tonic-gate 1551*0Sstevel@tonic-gate 1552*0Sstevel@tonic-gate /* 1553*0Sstevel@tonic-gate * dcs_unknown_op: 1554*0Sstevel@tonic-gate * 1555*0Sstevel@tonic-gate * Handle all unknown requests. 1556*0Sstevel@tonic-gate */ 1557*0Sstevel@tonic-gate /* ARGSUSED */ 1558*0Sstevel@tonic-gate static int 1559*0Sstevel@tonic-gate dcs_unknown_op(rdr_msg_hdr_t *hdr, cfga_params_t *param) 1560*0Sstevel@tonic-gate { 1561*0Sstevel@tonic-gate session_t *sp; 1562*0Sstevel@tonic-gate 1563*0Sstevel@tonic-gate 1564*0Sstevel@tonic-gate assert(hdr); 1565*0Sstevel@tonic-gate assert(param); 1566*0Sstevel@tonic-gate 1567*0Sstevel@tonic-gate assert(hdr); 1568*0Sstevel@tonic-gate 1569*0Sstevel@tonic-gate /* get the current session information */ 1570*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1571*0Sstevel@tonic-gate ses_close(DCS_ERROR); 1572*0Sstevel@tonic-gate return (-1); 1573*0Sstevel@tonic-gate } 1574*0Sstevel@tonic-gate 1575*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_UNKNOWN_OP, hdr->message_opcode); 1576*0Sstevel@tonic-gate 1577*0Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 1578*0Sstevel@tonic-gate 1579*0Sstevel@tonic-gate return (-1); 1580*0Sstevel@tonic-gate } 1581*0Sstevel@tonic-gate 1582*0Sstevel@tonic-gate 1583*0Sstevel@tonic-gate /* 1584*0Sstevel@tonic-gate * dcs_confirm_callback: 1585*0Sstevel@tonic-gate * 1586*0Sstevel@tonic-gate * Perform a confirm callback and wait for the reply. As defined 1587*0Sstevel@tonic-gate * in the config_admin(3CFGADM) man page, 1 is returned if the 1588*0Sstevel@tonic-gate * operation should be allowed to continue and 0 otherwise. 1589*0Sstevel@tonic-gate */ 1590*0Sstevel@tonic-gate static int 1591*0Sstevel@tonic-gate dcs_confirm_callback(void *appdata_ptr, const char *message) 1592*0Sstevel@tonic-gate { 1593*0Sstevel@tonic-gate session_t *sp; 1594*0Sstevel@tonic-gate rdr_msg_hdr_t req_hdr; 1595*0Sstevel@tonic-gate cfga_params_t req_data; 1596*0Sstevel@tonic-gate struct cfga_confirm *cb_data; 1597*0Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 1598*0Sstevel@tonic-gate cfga_params_t reply_data; 1599*0Sstevel@tonic-gate int snd_status; 1600*0Sstevel@tonic-gate int rcv_status; 1601*0Sstevel@tonic-gate static char *op_name = "confirm callback"; 1602*0Sstevel@tonic-gate 1603*0Sstevel@tonic-gate 1604*0Sstevel@tonic-gate /* sanity check */ 1605*0Sstevel@tonic-gate if (appdata_ptr == NULL) { 1606*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 1607*0Sstevel@tonic-gate return (0); 1608*0Sstevel@tonic-gate } 1609*0Sstevel@tonic-gate 1610*0Sstevel@tonic-gate /* get the current session information */ 1611*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1612*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 1613*0Sstevel@tonic-gate return (0); 1614*0Sstevel@tonic-gate } 1615*0Sstevel@tonic-gate 1616*0Sstevel@tonic-gate cb_data = (struct cfga_confirm *)appdata_ptr; 1617*0Sstevel@tonic-gate 1618*0Sstevel@tonic-gate /* prepare header information */ 1619*0Sstevel@tonic-gate init_msg(&req_hdr); 1620*0Sstevel@tonic-gate req_hdr.message_opcode = RDR_CONF_CONFIRM_CALLBACK; 1621*0Sstevel@tonic-gate req_hdr.data_type = RDR_REQUEST; 1622*0Sstevel@tonic-gate 1623*0Sstevel@tonic-gate /* prepare confirm callback specific data */ 1624*0Sstevel@tonic-gate (void) memset(&req_data, 0, sizeof (req_data)); 1625*0Sstevel@tonic-gate req_data.conf_cb.confp = cb_data; 1626*0Sstevel@tonic-gate req_data.conf_cb.message = (char *)message; 1627*0Sstevel@tonic-gate 1628*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &req_hdr); 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gate /* send the message */ 1631*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &req_hdr, &req_data, DCS_SND_TIMEOUT); 1632*0Sstevel@tonic-gate 1633*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1634*0Sstevel@tonic-gate abort_handler(); 1635*0Sstevel@tonic-gate } 1636*0Sstevel@tonic-gate 1637*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1638*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 1639*0Sstevel@tonic-gate return (0); 1640*0Sstevel@tonic-gate } 1641*0Sstevel@tonic-gate 1642*0Sstevel@tonic-gate /* 1643*0Sstevel@tonic-gate * Wait for response 1644*0Sstevel@tonic-gate */ 1645*0Sstevel@tonic-gate rcv_status = rdr_rcv_msg(sp->fd, &reply_hdr, &reply_data, 1646*0Sstevel@tonic-gate DCS_RCV_CB_TIMEOUT); 1647*0Sstevel@tonic-gate 1648*0Sstevel@tonic-gate if (rcv_status != RDR_OK) { 1649*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1650*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 1651*0Sstevel@tonic-gate return (0); 1652*0Sstevel@tonic-gate } 1653*0Sstevel@tonic-gate 1654*0Sstevel@tonic-gate /* 1655*0Sstevel@tonic-gate * Perform several checks to see if we have a 1656*0Sstevel@tonic-gate * valid response to the confirm callback. 1657*0Sstevel@tonic-gate */ 1658*0Sstevel@tonic-gate if (invalid_msg(&reply_hdr)) { 1659*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 1660*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 1661*0Sstevel@tonic-gate return (0); 1662*0Sstevel@tonic-gate } 1663*0Sstevel@tonic-gate 1664*0Sstevel@tonic-gate /* check the opcode and type */ 1665*0Sstevel@tonic-gate if ((reply_hdr.message_opcode != RDR_CONF_CONFIRM_CALLBACK) || 1666*0Sstevel@tonic-gate (reply_hdr.data_type != RDR_REPLY)) { 1667*0Sstevel@tonic-gate DCS_DBG(DBG_MSG, "bad opcode or message type"); 1668*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 1669*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 1670*0Sstevel@tonic-gate return (0); 1671*0Sstevel@tonic-gate } 1672*0Sstevel@tonic-gate 1673*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_RECEIVE, &reply_hdr); 1674*0Sstevel@tonic-gate 1675*0Sstevel@tonic-gate /* check for incorrect callback id */ 1676*0Sstevel@tonic-gate if (reply_data.conf_cb.confp->confirm != cb_data->confirm) { 1677*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 1678*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 1679*0Sstevel@tonic-gate return (0); 1680*0Sstevel@tonic-gate } 1681*0Sstevel@tonic-gate 1682*0Sstevel@tonic-gate /* 1683*0Sstevel@tonic-gate * Got back valid response: return the user's answer 1684*0Sstevel@tonic-gate */ 1685*0Sstevel@tonic-gate return (reply_data.conf_cb.response); 1686*0Sstevel@tonic-gate } 1687*0Sstevel@tonic-gate 1688*0Sstevel@tonic-gate 1689*0Sstevel@tonic-gate /* 1690*0Sstevel@tonic-gate * dcs_message_callback: 1691*0Sstevel@tonic-gate * 1692*0Sstevel@tonic-gate * Perform a message callback to display a string to the user. 1693*0Sstevel@tonic-gate * 1694*0Sstevel@tonic-gate * Note: There is no documentation about possible return values 1695*0Sstevel@tonic-gate * for the message callback. It is assumed that the value returned 1696*0Sstevel@tonic-gate * is ignored, so 0 is returned for all cases. 1697*0Sstevel@tonic-gate */ 1698*0Sstevel@tonic-gate static int 1699*0Sstevel@tonic-gate dcs_message_callback(void *appdata_ptr, const char *message) 1700*0Sstevel@tonic-gate { 1701*0Sstevel@tonic-gate session_t *sp; 1702*0Sstevel@tonic-gate rdr_msg_hdr_t req_hdr; 1703*0Sstevel@tonic-gate cfga_params_t req_data; 1704*0Sstevel@tonic-gate struct cfga_msg *cb_data; 1705*0Sstevel@tonic-gate int snd_status; 1706*0Sstevel@tonic-gate static char *op_name = "message callback"; 1707*0Sstevel@tonic-gate 1708*0Sstevel@tonic-gate 1709*0Sstevel@tonic-gate /* sanity check */ 1710*0Sstevel@tonic-gate if (appdata_ptr == NULL) { 1711*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 1712*0Sstevel@tonic-gate return (0); 1713*0Sstevel@tonic-gate } 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate /* get the current session information */ 1716*0Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 1717*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 1718*0Sstevel@tonic-gate return (0); 1719*0Sstevel@tonic-gate } 1720*0Sstevel@tonic-gate 1721*0Sstevel@tonic-gate cb_data = (struct cfga_msg *)appdata_ptr; 1722*0Sstevel@tonic-gate 1723*0Sstevel@tonic-gate /* prepare header information */ 1724*0Sstevel@tonic-gate init_msg(&req_hdr); 1725*0Sstevel@tonic-gate req_hdr.message_opcode = RDR_CONF_MSG_CALLBACK; 1726*0Sstevel@tonic-gate req_hdr.data_type = RDR_REQUEST; 1727*0Sstevel@tonic-gate 1728*0Sstevel@tonic-gate /* prepare message callback specific data */ 1729*0Sstevel@tonic-gate (void) memset(&req_data, 0, sizeof (req_data)); 1730*0Sstevel@tonic-gate req_data.msg_cb.msgp = cb_data; 1731*0Sstevel@tonic-gate req_data.msg_cb.message = (char *)message; 1732*0Sstevel@tonic-gate 1733*0Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &req_hdr); 1734*0Sstevel@tonic-gate 1735*0Sstevel@tonic-gate /* send the message */ 1736*0Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &req_hdr, (cfga_params_t *)&req_data, 1737*0Sstevel@tonic-gate DCS_SND_TIMEOUT); 1738*0Sstevel@tonic-gate 1739*0Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 1740*0Sstevel@tonic-gate abort_handler(); 1741*0Sstevel@tonic-gate } 1742*0Sstevel@tonic-gate 1743*0Sstevel@tonic-gate if (snd_status != RDR_OK) { 1744*0Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 1745*0Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 1746*0Sstevel@tonic-gate } 1747*0Sstevel@tonic-gate 1748*0Sstevel@tonic-gate return (0); 1749*0Sstevel@tonic-gate } 1750*0Sstevel@tonic-gate 1751*0Sstevel@tonic-gate 1752*0Sstevel@tonic-gate /* 1753*0Sstevel@tonic-gate * resolve_version: 1754*0Sstevel@tonic-gate * 1755*0Sstevel@tonic-gate * Consult the list of supported versions and find the highest supported 1756*0Sstevel@tonic-gate * version that is less than or equal to the version requested in the 1757*0Sstevel@tonic-gate * parameters. This assumes that the list of supported versions is ordered 1758*0Sstevel@tonic-gate * so that the highest supported version is the first element, and that 1759*0Sstevel@tonic-gate * the versions are strictly decreasing. 1760*0Sstevel@tonic-gate */ 1761*0Sstevel@tonic-gate static dcs_ver_t 1762*0Sstevel@tonic-gate resolve_version(ushort_t req_major, ushort_t req_minor) 1763*0Sstevel@tonic-gate { 1764*0Sstevel@tonic-gate int i; 1765*0Sstevel@tonic-gate dcs_ver_t act_ver; 1766*0Sstevel@tonic-gate int num_vers; 1767*0Sstevel@tonic-gate 1768*0Sstevel@tonic-gate 1769*0Sstevel@tonic-gate num_vers = sizeof (ver_supp) / sizeof (*ver_supp); 1770*0Sstevel@tonic-gate 1771*0Sstevel@tonic-gate /* default to the lowest version */ 1772*0Sstevel@tonic-gate act_ver = ver_supp[num_vers - 1]; 1773*0Sstevel@tonic-gate 1774*0Sstevel@tonic-gate for (i = 0; i < num_vers; i++) { 1775*0Sstevel@tonic-gate 1776*0Sstevel@tonic-gate if (req_major == ver_supp[i].major) { 1777*0Sstevel@tonic-gate 1778*0Sstevel@tonic-gate if (req_minor >= ver_supp[i].minor) { 1779*0Sstevel@tonic-gate /* 1780*0Sstevel@tonic-gate * The major version matches and the 1781*0Sstevel@tonic-gate * minor version either matches, or 1782*0Sstevel@tonic-gate * is the best match that we have. 1783*0Sstevel@tonic-gate */ 1784*0Sstevel@tonic-gate act_ver = ver_supp[i]; 1785*0Sstevel@tonic-gate break; 1786*0Sstevel@tonic-gate } 1787*0Sstevel@tonic-gate 1788*0Sstevel@tonic-gate } else if (req_major > ver_supp[i].major) { 1789*0Sstevel@tonic-gate /* 1790*0Sstevel@tonic-gate * The requested major version is larger than 1791*0Sstevel@tonic-gate * the current version we are checking. There 1792*0Sstevel@tonic-gate * is not going to be a better match. 1793*0Sstevel@tonic-gate */ 1794*0Sstevel@tonic-gate act_ver = ver_supp[i]; 1795*0Sstevel@tonic-gate break; 1796*0Sstevel@tonic-gate } 1797*0Sstevel@tonic-gate } 1798*0Sstevel@tonic-gate 1799*0Sstevel@tonic-gate DCS_DBG(DBG_SES, "requested ver: %d.%d, closest match: %d.%d", 1800*0Sstevel@tonic-gate req_major, req_minor, act_ver.major, act_ver.minor); 1801*0Sstevel@tonic-gate 1802*0Sstevel@tonic-gate return (act_ver); 1803*0Sstevel@tonic-gate } 1804*0Sstevel@tonic-gate 1805*0Sstevel@tonic-gate 1806*0Sstevel@tonic-gate /* 1807*0Sstevel@tonic-gate * filter_list_data: 1808*0Sstevel@tonic-gate * 1809*0Sstevel@tonic-gate * Check a list of cfga_list_data_t structures to filter out the ones 1810*0Sstevel@tonic-gate * that don't have other-read permissions. All valid entries are placed 1811*0Sstevel@tonic-gate * at the beginning of the array and the count of entries is updated. 1812*0Sstevel@tonic-gate */ 1813*0Sstevel@tonic-gate static void 1814*0Sstevel@tonic-gate filter_list_data(int perm, int *nlistp, cfga_list_data_t *linfo) 1815*0Sstevel@tonic-gate { 1816*0Sstevel@tonic-gate int num_aps; 1817*0Sstevel@tonic-gate int num_aps_ret; 1818*0Sstevel@tonic-gate int curr_ap; 1819*0Sstevel@tonic-gate int next_aval; 1820*0Sstevel@tonic-gate int end_block; 1821*0Sstevel@tonic-gate int block_size; 1822*0Sstevel@tonic-gate struct stat ap_info; 1823*0Sstevel@tonic-gate 1824*0Sstevel@tonic-gate 1825*0Sstevel@tonic-gate DCS_DBG(DBG_MSG, "list access = %s", (perm == RDR_PRIVILEGED) ? 1826*0Sstevel@tonic-gate "RDR_PRIVILEGED" : "RDR_NOT_PRIVILEGED"); 1827*0Sstevel@tonic-gate 1828*0Sstevel@tonic-gate /* 1829*0Sstevel@tonic-gate * Check if the user has priviledged access 1830*0Sstevel@tonic-gate * to view all attachment points 1831*0Sstevel@tonic-gate */ 1832*0Sstevel@tonic-gate if (perm == RDR_PRIVILEGED) { 1833*0Sstevel@tonic-gate return; 1834*0Sstevel@tonic-gate } 1835*0Sstevel@tonic-gate 1836*0Sstevel@tonic-gate if (*nlistp < 0) { 1837*0Sstevel@tonic-gate *nlistp = 0; 1838*0Sstevel@tonic-gate } 1839*0Sstevel@tonic-gate 1840*0Sstevel@tonic-gate /* 1841*0Sstevel@tonic-gate * No priviledged access, check each attachment point to 1842*0Sstevel@tonic-gate * see if the user has access (other:read) to view it. 1843*0Sstevel@tonic-gate */ 1844*0Sstevel@tonic-gate num_aps = *nlistp; 1845*0Sstevel@tonic-gate next_aval = 0; 1846*0Sstevel@tonic-gate num_aps_ret = 0; 1847*0Sstevel@tonic-gate curr_ap = 0; 1848*0Sstevel@tonic-gate 1849*0Sstevel@tonic-gate /* 1850*0Sstevel@tonic-gate * Use a simple algorithm to compact the array so that 1851*0Sstevel@tonic-gate * all attachment points that can be viewed are at the 1852*0Sstevel@tonic-gate * beginning of the array. Adjust the count of the 1853*0Sstevel@tonic-gate * attachment points accordingly. 1854*0Sstevel@tonic-gate */ 1855*0Sstevel@tonic-gate while (curr_ap < num_aps) { 1856*0Sstevel@tonic-gate 1857*0Sstevel@tonic-gate stat(linfo[curr_ap].ap_phys_id, &ap_info); 1858*0Sstevel@tonic-gate 1859*0Sstevel@tonic-gate /* check for unrestricted read permission */ 1860*0Sstevel@tonic-gate if (ap_info.st_mode & S_IROTH) { 1861*0Sstevel@tonic-gate 1862*0Sstevel@tonic-gate end_block = curr_ap + 1; 1863*0Sstevel@tonic-gate 1864*0Sstevel@tonic-gate /* 1865*0Sstevel@tonic-gate * Check if this is the beginning of a 1866*0Sstevel@tonic-gate * block of consecutive ap ids that can 1867*0Sstevel@tonic-gate * be returned. 1868*0Sstevel@tonic-gate */ 1869*0Sstevel@tonic-gate while (end_block < num_aps) { 1870*0Sstevel@tonic-gate 1871*0Sstevel@tonic-gate stat(linfo[end_block].ap_phys_id, &ap_info); 1872*0Sstevel@tonic-gate 1873*0Sstevel@tonic-gate /* search until the end of the block */ 1874*0Sstevel@tonic-gate if (ap_info.st_mode & S_IROTH) { 1875*0Sstevel@tonic-gate end_block++; 1876*0Sstevel@tonic-gate } else { 1877*0Sstevel@tonic-gate break; 1878*0Sstevel@tonic-gate } 1879*0Sstevel@tonic-gate } 1880*0Sstevel@tonic-gate 1881*0Sstevel@tonic-gate block_size = end_block - curr_ap; 1882*0Sstevel@tonic-gate 1883*0Sstevel@tonic-gate /* make sure a copy is necessary */ 1884*0Sstevel@tonic-gate if (curr_ap != next_aval) { 1885*0Sstevel@tonic-gate 1886*0Sstevel@tonic-gate /* copy the block of ap ids all at once */ 1887*0Sstevel@tonic-gate (void) memmove(&linfo[next_aval], 1888*0Sstevel@tonic-gate &linfo[curr_ap], 1889*0Sstevel@tonic-gate block_size * sizeof (cfga_list_data_t)); 1890*0Sstevel@tonic-gate } 1891*0Sstevel@tonic-gate 1892*0Sstevel@tonic-gate /* move past the copied block */ 1893*0Sstevel@tonic-gate next_aval += block_size; 1894*0Sstevel@tonic-gate curr_ap = end_block; 1895*0Sstevel@tonic-gate 1896*0Sstevel@tonic-gate num_aps_ret += block_size; 1897*0Sstevel@tonic-gate } else { 1898*0Sstevel@tonic-gate curr_ap++; 1899*0Sstevel@tonic-gate } 1900*0Sstevel@tonic-gate } 1901*0Sstevel@tonic-gate 1902*0Sstevel@tonic-gate DCS_DBG(DBG_ALL, "filtered %d of %d ap ids", (*nlistp - num_aps_ret), 1903*0Sstevel@tonic-gate *nlistp); 1904*0Sstevel@tonic-gate 1905*0Sstevel@tonic-gate /* 1906*0Sstevel@tonic-gate * return the number of aps that have the correct 1907*0Sstevel@tonic-gate * access permissions. 1908*0Sstevel@tonic-gate */ 1909*0Sstevel@tonic-gate *nlistp = num_aps_ret; 1910*0Sstevel@tonic-gate } 1911*0Sstevel@tonic-gate 1912*0Sstevel@tonic-gate 1913*0Sstevel@tonic-gate /* 1914*0Sstevel@tonic-gate * generate_sort_order: 1915*0Sstevel@tonic-gate * 1916*0Sstevel@tonic-gate * Determine the sort order of an array of cfga_list_data_t structures 1917*0Sstevel@tonic-gate * and create an array of rdr_list_t structures that contain the original 1918*0Sstevel@tonic-gate * elements tagged with the sort order. 1919*0Sstevel@tonic-gate * 1920*0Sstevel@tonic-gate * This function is used to eliminate unnecessary network traffic that 1921*0Sstevel@tonic-gate * might occur if the client needs the output of config_list_ext(3CFGADM) 1922*0Sstevel@tonic-gate * sorted. Since a comparison is performed in a platform specific manner 1923*0Sstevel@tonic-gate * using config_ap_id_cmp(3CFGADM), a client must establish a new session 1924*0Sstevel@tonic-gate * for each comparison. For a long lists of attachment points, this can 1925*0Sstevel@tonic-gate * slow down a simple list_ext operation significantly. With the sort 1926*0Sstevel@tonic-gate * information included in the array of rdr_list_t structures, the client 1927*0Sstevel@tonic-gate * can perform the sort operation locally, thus eliminating a great deal 1928*0Sstevel@tonic-gate * of network traffic. 1929*0Sstevel@tonic-gate */ 1930*0Sstevel@tonic-gate static rdr_list_t * 1931*0Sstevel@tonic-gate generate_sort_order(cfga_list_data_t *listp, int nlist) 1932*0Sstevel@tonic-gate { 1933*0Sstevel@tonic-gate int curr_ap; 1934*0Sstevel@tonic-gate rdr_list_t *datalp; 1935*0Sstevel@tonic-gate cfga_list_data_t *sortlp; 1936*0Sstevel@tonic-gate cfga_list_data_t *match; 1937*0Sstevel@tonic-gate 1938*0Sstevel@tonic-gate 1939*0Sstevel@tonic-gate assert(listp); 1940*0Sstevel@tonic-gate 1941*0Sstevel@tonic-gate if (nlist <= 0) { 1942*0Sstevel@tonic-gate return (NULL); 1943*0Sstevel@tonic-gate } 1944*0Sstevel@tonic-gate 1945*0Sstevel@tonic-gate /* create our new array */ 1946*0Sstevel@tonic-gate datalp = (rdr_list_t *)malloc(nlist * sizeof (rdr_list_t)); 1947*0Sstevel@tonic-gate 1948*0Sstevel@tonic-gate if (datalp == NULL) { 1949*0Sstevel@tonic-gate return (NULL); 1950*0Sstevel@tonic-gate } 1951*0Sstevel@tonic-gate 1952*0Sstevel@tonic-gate 1953*0Sstevel@tonic-gate /* copy over the elements, preserving the original order */ 1954*0Sstevel@tonic-gate for (curr_ap = 0; curr_ap < nlist; curr_ap++) { 1955*0Sstevel@tonic-gate datalp[curr_ap].ap_id_info = listp[curr_ap]; 1956*0Sstevel@tonic-gate } 1957*0Sstevel@tonic-gate 1958*0Sstevel@tonic-gate /* handle a one element list */ 1959*0Sstevel@tonic-gate if (nlist == 1) { 1960*0Sstevel@tonic-gate datalp[0].sort_order = 0; 1961*0Sstevel@tonic-gate return (datalp); 1962*0Sstevel@tonic-gate } 1963*0Sstevel@tonic-gate 1964*0Sstevel@tonic-gate /* sort the cfga_list_data_t array */ 1965*0Sstevel@tonic-gate qsort(listp, nlist, sizeof (listp[0]), ldata_compare); 1966*0Sstevel@tonic-gate 1967*0Sstevel@tonic-gate sortlp = listp; 1968*0Sstevel@tonic-gate 1969*0Sstevel@tonic-gate /* process each item in the original list */ 1970*0Sstevel@tonic-gate for (curr_ap = 0; curr_ap < nlist; curr_ap++) { 1971*0Sstevel@tonic-gate 1972*0Sstevel@tonic-gate /* look up the sort order in the sorted list */ 1973*0Sstevel@tonic-gate match = bsearch(&datalp[curr_ap].ap_id_info, sortlp, 1974*0Sstevel@tonic-gate nlist, sizeof (cfga_list_data_t), ldata_compare); 1975*0Sstevel@tonic-gate 1976*0Sstevel@tonic-gate /* found a match */ 1977*0Sstevel@tonic-gate if (match != NULL) { 1978*0Sstevel@tonic-gate datalp[curr_ap].sort_order = match - sortlp; 1979*0Sstevel@tonic-gate } else { 1980*0Sstevel@tonic-gate /* 1981*0Sstevel@tonic-gate * Should never get here. Since we did a 1982*0Sstevel@tonic-gate * direct copy of the array, we should always 1983*0Sstevel@tonic-gate * be able to find the ap id that we were 1984*0Sstevel@tonic-gate * looking for. 1985*0Sstevel@tonic-gate */ 1986*0Sstevel@tonic-gate DCS_DBG(DBG_ALL, "could not find a matching " 1987*0Sstevel@tonic-gate "ap id in the sorted list"); 1988*0Sstevel@tonic-gate datalp[curr_ap].sort_order = 0; 1989*0Sstevel@tonic-gate } 1990*0Sstevel@tonic-gate } 1991*0Sstevel@tonic-gate 1992*0Sstevel@tonic-gate return (datalp); 1993*0Sstevel@tonic-gate } 1994*0Sstevel@tonic-gate 1995*0Sstevel@tonic-gate 1996*0Sstevel@tonic-gate /* 1997*0Sstevel@tonic-gate * ldata_compare: 1998*0Sstevel@tonic-gate * 1999*0Sstevel@tonic-gate * Compare the two inputs to produce a strcmp(3C) style result. It uses 2000*0Sstevel@tonic-gate * config_ap_id_cmp(3CFGADM) to perform the comparison. 2001*0Sstevel@tonic-gate * 2002*0Sstevel@tonic-gate * This function is passed to qsort(3C) in generate_sort_order() to sort a 2003*0Sstevel@tonic-gate * list of attachment points. 2004*0Sstevel@tonic-gate */ 2005*0Sstevel@tonic-gate static int 2006*0Sstevel@tonic-gate ldata_compare(const void *ap1, const void *ap2) 2007*0Sstevel@tonic-gate { 2008*0Sstevel@tonic-gate cfga_list_data_t *ap_id1; 2009*0Sstevel@tonic-gate cfga_list_data_t *ap_id2; 2010*0Sstevel@tonic-gate 2011*0Sstevel@tonic-gate ap_id1 = (cfga_list_data_t *)ap1; 2012*0Sstevel@tonic-gate ap_id2 = (cfga_list_data_t *)ap2; 2013*0Sstevel@tonic-gate 2014*0Sstevel@tonic-gate return (config_ap_id_cmp(ap_id1->ap_log_id, ap_id2->ap_log_id)); 2015*0Sstevel@tonic-gate } 2016*0Sstevel@tonic-gate 2017*0Sstevel@tonic-gate 2018*0Sstevel@tonic-gate /* 2019*0Sstevel@tonic-gate * basename: 2020*0Sstevel@tonic-gate * 2021*0Sstevel@tonic-gate * Find short path name of a full path name. If a short path name 2022*0Sstevel@tonic-gate * is passed in, the original pointer is returned. 2023*0Sstevel@tonic-gate */ 2024*0Sstevel@tonic-gate static char * 2025*0Sstevel@tonic-gate basename(char *cp) 2026*0Sstevel@tonic-gate { 2027*0Sstevel@tonic-gate char *sp; 2028*0Sstevel@tonic-gate 2029*0Sstevel@tonic-gate if ((sp = strrchr(cp, '/')) != NULL) { 2030*0Sstevel@tonic-gate return (sp + 1); 2031*0Sstevel@tonic-gate } 2032*0Sstevel@tonic-gate 2033*0Sstevel@tonic-gate return (cp); 2034*0Sstevel@tonic-gate } 2035