10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1518Smb158278 * Common Development and Distribution License (the "License"). 6*1518Smb158278 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1518Smb158278 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 231120Smb158278 * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * This is the main file for the Domain Configuration Server (DCS). 300Sstevel@tonic-gate * 310Sstevel@tonic-gate * The DCS is a server that runs on a domain and communicates with 320Sstevel@tonic-gate * a Domain Configuration Agent (DCA) running on a remote host. The 330Sstevel@tonic-gate * DCA initiates DR requests that the DCS performs by calling the 340Sstevel@tonic-gate * appropriate libcfgadm(3LIB) function. 350Sstevel@tonic-gate * 360Sstevel@tonic-gate * This file contains functions that receive and process the messages 370Sstevel@tonic-gate * received from the DCA. It also handles the initialization of the 380Sstevel@tonic-gate * server and is responsible for starting a concurrent session to 390Sstevel@tonic-gate * handle each DR request. 400Sstevel@tonic-gate */ 410Sstevel@tonic-gate 420Sstevel@tonic-gate #include <stdlib.h> 430Sstevel@tonic-gate #include <stdio.h> 440Sstevel@tonic-gate #include <unistd.h> 450Sstevel@tonic-gate #include <string.h> 460Sstevel@tonic-gate #include <fcntl.h> 470Sstevel@tonic-gate #include <errno.h> 480Sstevel@tonic-gate #include <syslog.h> 490Sstevel@tonic-gate #include <assert.h> 500Sstevel@tonic-gate #include <signal.h> 510Sstevel@tonic-gate #include <netdb.h> 520Sstevel@tonic-gate #include <config_admin.h> 530Sstevel@tonic-gate #include <sys/param.h> 540Sstevel@tonic-gate #include <sys/time.h> 550Sstevel@tonic-gate #include <sys/stat.h> 560Sstevel@tonic-gate #include <sys/socket.h> 571120Smb158278 #include <strings.h> 580Sstevel@tonic-gate 590Sstevel@tonic-gate #include "dcs.h" 600Sstevel@tonic-gate #include "remote_cfg.h" 610Sstevel@tonic-gate #include "rdr_param_types.h" 620Sstevel@tonic-gate #include "rdr_messages.h" 630Sstevel@tonic-gate #include "rsrc_info.h" 640Sstevel@tonic-gate 650Sstevel@tonic-gate 660Sstevel@tonic-gate typedef struct { 670Sstevel@tonic-gate ushort_t major; 680Sstevel@tonic-gate ushort_t minor; 690Sstevel@tonic-gate } dcs_ver_t; 700Sstevel@tonic-gate 710Sstevel@tonic-gate 720Sstevel@tonic-gate /* initialization functions */ 731120Smb158278 static int init_server(struct pollfd *pfd, uint8_t ah_auth_alg, 741120Smb158278 uint8_t esp_encr_alg, uint8_t esp_auth_alg); 750Sstevel@tonic-gate static void init_signals(void); 760Sstevel@tonic-gate 770Sstevel@tonic-gate /* message processing functions */ 780Sstevel@tonic-gate static int invalid_msg(rdr_msg_hdr_t *hdr); 790Sstevel@tonic-gate 800Sstevel@tonic-gate /* message handling functions */ 810Sstevel@tonic-gate static int dcs_ses_req(rdr_msg_hdr_t *hdr, cfga_params_t *param); 820Sstevel@tonic-gate static int dcs_ses_estbl(rdr_msg_hdr_t *hdr, cfga_params_t *param); 830Sstevel@tonic-gate static int dcs_ses_end(rdr_msg_hdr_t *hdr, cfga_params_t *param); 840Sstevel@tonic-gate static int dcs_change_state(rdr_msg_hdr_t *hdr, cfga_params_t *param); 850Sstevel@tonic-gate static int dcs_private_func(rdr_msg_hdr_t *hdr, cfga_params_t *param); 860Sstevel@tonic-gate static int dcs_test(rdr_msg_hdr_t *hdr, cfga_params_t *param); 870Sstevel@tonic-gate static int dcs_list_ext(rdr_msg_hdr_t *hdr, cfga_params_t *param); 880Sstevel@tonic-gate static int dcs_help(rdr_msg_hdr_t *hdr, cfga_params_t *param); 890Sstevel@tonic-gate static int dcs_ap_id_cmp(rdr_msg_hdr_t *hdr, cfga_params_t *param); 900Sstevel@tonic-gate static int dcs_abort_cmd(rdr_msg_hdr_t *hdr, cfga_params_t *param); 910Sstevel@tonic-gate static int dcs_rsrc_info(rdr_msg_hdr_t *hdr, cfga_params_t *param); 920Sstevel@tonic-gate static int dcs_unknown_op(rdr_msg_hdr_t *hdr, cfga_params_t *param); 930Sstevel@tonic-gate 940Sstevel@tonic-gate /* local callback functions */ 950Sstevel@tonic-gate static int dcs_confirm_callback(void *appdata_ptr, const char *message); 960Sstevel@tonic-gate static int dcs_message_callback(void *appdata_ptr, const char *message); 970Sstevel@tonic-gate 980Sstevel@tonic-gate /* utility functions */ 990Sstevel@tonic-gate static dcs_ver_t resolve_version(ushort_t req_major, ushort_t req_minor); 1000Sstevel@tonic-gate static void filter_list_data(int perm, int *nlistp, cfga_list_data_t *linfo); 1010Sstevel@tonic-gate static rdr_list_t *generate_sort_order(cfga_list_data_t *listp, int nlist); 1020Sstevel@tonic-gate static int ldata_compare(const void *ap1, const void *ap2); 1030Sstevel@tonic-gate static int invalid_msg(rdr_msg_hdr_t *hdr); 1040Sstevel@tonic-gate static char *basename(char *path); 1051120Smb158278 static boolean_t is_socket(int fd); 1061120Smb158278 static uint8_t dcs_get_alg(dcs_alg_t *algs, char *arg, dcs_err_code *error); 1071120Smb158278 static void dcs_log_bad_alg(char optopt, char *optarg); 108*1518Smb158278 static boolean_t dcs_global_policy(void); 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /* 1120Sstevel@tonic-gate * Lookup table for handling different message types. This 1130Sstevel@tonic-gate * assumes the ordering of rdr_msg_opcode_t in remote_cfg.h. 1140Sstevel@tonic-gate * If this enum changes, the lookup table must be updated. 1150Sstevel@tonic-gate * 1160Sstevel@tonic-gate * The lookup table handles all _known_ opcodes >= 0. Unsupported 1170Sstevel@tonic-gate * opcodes, or opcodes that should not be received by the 1180Sstevel@tonic-gate * dispatcher are handled by the dcs_unknown_op() function. 1190Sstevel@tonic-gate */ 1200Sstevel@tonic-gate int (*dcs_cmd[])(rdr_msg_hdr_t *, cfga_params_t *) = { 1210Sstevel@tonic-gate dcs_unknown_op, /* 0 is an invalid opcode */ 1220Sstevel@tonic-gate dcs_ses_req, /* RDR_SES_REQ */ 1230Sstevel@tonic-gate dcs_ses_estbl, /* RDR_SES_ESTBL */ 1240Sstevel@tonic-gate dcs_ses_end, /* RDR_SES_END */ 1250Sstevel@tonic-gate dcs_change_state, /* RDR_CONF_CHANGE_STATE */ 1260Sstevel@tonic-gate dcs_private_func, /* RDR_CONF_PRIVATE_FUNC */ 1270Sstevel@tonic-gate dcs_test, /* RDR_CONF_TEST */ 1280Sstevel@tonic-gate dcs_list_ext, /* RDR_CONF_LIST_EXT */ 1290Sstevel@tonic-gate dcs_help, /* RDR_CONF_HELP */ 1300Sstevel@tonic-gate dcs_ap_id_cmp, /* RDR_CONF_AP_ID_CMP */ 1310Sstevel@tonic-gate dcs_abort_cmd, /* RDR_CONF_ABORT_CMD */ 1320Sstevel@tonic-gate dcs_unknown_op, /* RDR_CONF_CONFIRM_CALLBACK */ 1330Sstevel@tonic-gate dcs_unknown_op, /* RDR_CONF_MSG_CALLBACK */ 1340Sstevel@tonic-gate dcs_rsrc_info /* RDR_RSRC_INFO */ 1350Sstevel@tonic-gate }; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate /* 1390Sstevel@tonic-gate * ver_supp[] is an array of the supported versions for the network 1400Sstevel@tonic-gate * transport protocol used by the DCA and DCS. Each item in the array 1410Sstevel@tonic-gate * is a pair: { major_version, minor_version }. 1420Sstevel@tonic-gate * 1430Sstevel@tonic-gate * The order of the array is significant. The first element should be 1440Sstevel@tonic-gate * the highest supported version and all successive elements should be 1450Sstevel@tonic-gate * strictly decreasing. 1460Sstevel@tonic-gate */ 1470Sstevel@tonic-gate dcs_ver_t ver_supp[] = { 1480Sstevel@tonic-gate { 1, 0 } 1490Sstevel@tonic-gate }; 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate #define DCS_CURR_VER ver_supp[0] 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate /* 1550Sstevel@tonic-gate * Global Data 1560Sstevel@tonic-gate */ 1570Sstevel@tonic-gate char *cmdname = NULL; /* the name of the executable */ 1580Sstevel@tonic-gate ulong_t dcs_debug = 0; /* control the amount of debugging */ 1590Sstevel@tonic-gate int standalone = 0; /* control standalone mode */ 1601120Smb158278 boolean_t inetd = B_FALSE; /* control daemon mode */ 1610Sstevel@tonic-gate ulong_t max_sessions = DCS_MAX_SESSIONS; /* control maximum active sessions */ 1620Sstevel@tonic-gate int dcsfd = STDIN_FILENO; /* fd for the DCS reserved port */ 1630Sstevel@tonic-gate 1641120Smb158278 /* 1651120Smb158278 * Array of acceptable -a, -e and -u arguments. 1661120Smb158278 */ 1671120Smb158278 static dcs_alg_t auth_algs_array[] = { 1681120Smb158278 { "none", SADB_AALG_NONE }, /* -a none or -u none */ 1691120Smb158278 { "md5", SADB_AALG_MD5HMAC }, /* -a md5 or -u md5 */ 1701120Smb158278 { "sha1", SADB_AALG_SHA1HMAC }, /* -a sha1 or -u sha1 */ 1711120Smb158278 { NULL, 0x0 } 1721120Smb158278 }, esp_algs_array[] = { 1731120Smb158278 { "none", SADB_EALG_NONE }, /* -e none */ 1741120Smb158278 { "des", SADB_EALG_DESCBC }, /* -e des */ 1751120Smb158278 { "3des", SADB_EALG_3DESCBC }, /* -e 3des */ 1761120Smb158278 { NULL, 0x0 } 1771120Smb158278 }; 1781120Smb158278 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate /* 1810Sstevel@tonic-gate * main: 1820Sstevel@tonic-gate * 1830Sstevel@tonic-gate * Initialize the DCS and then enter an infinite loop. This loop waits 1840Sstevel@tonic-gate * for connection requests to come and then establishes a connection. 1850Sstevel@tonic-gate * It dispatches the connection to be handled in a concurrent session. 1860Sstevel@tonic-gate */ 1870Sstevel@tonic-gate int 1880Sstevel@tonic-gate main(int argc, char **argv) 1890Sstevel@tonic-gate { 1900Sstevel@tonic-gate int opt; 1910Sstevel@tonic-gate struct timeval tv; 1920Sstevel@tonic-gate struct pollfd dcs_rcv; 1930Sstevel@tonic-gate int newfd; 1941120Smb158278 uint8_t ah_auth_alg = SADB_AALG_NONE; 1951120Smb158278 uint8_t esp_encr_alg = SADB_EALG_NONE; 1961120Smb158278 uint8_t esp_auth_alg = SADB_AALG_NONE; 1971120Smb158278 dcs_err_code alg_ec = DCS_NO_ERR; 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate /* initialize globals */ 2010Sstevel@tonic-gate dcs_debug = DBG_NONE; 2020Sstevel@tonic-gate cmdname = basename(argv[0]); 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate /* open log file with unique prefix */ 2050Sstevel@tonic-gate openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON); 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate /* 2080Sstevel@tonic-gate * Process command line args 2090Sstevel@tonic-gate */ 2100Sstevel@tonic-gate opterr = 0; /* disable getopt error messages */ 2110Sstevel@tonic-gate while ((opt = getopt(argc, argv, OPT_STR)) != EOF) { 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate switch (opt) { 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate case 'd': { 2160Sstevel@tonic-gate int usr_debug; 2170Sstevel@tonic-gate char *err_str; 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate usr_debug = strtol(optarg, &err_str, 0); 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate /* 2220Sstevel@tonic-gate * The err_str parameter will be an 2230Sstevel@tonic-gate * empty string if successful. 2240Sstevel@tonic-gate */ 2250Sstevel@tonic-gate if (*err_str != '\0') { 2260Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_BAD_OPT_ARG, optopt, 2270Sstevel@tonic-gate optarg, "exiting"); 2280Sstevel@tonic-gate (void) rdr_reject(dcsfd); 2290Sstevel@tonic-gate exit(1); 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate dcs_debug = usr_debug; 2330Sstevel@tonic-gate break; 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate case 'S': 2370Sstevel@tonic-gate standalone++; 2380Sstevel@tonic-gate break; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate case 's': { 2410Sstevel@tonic-gate int usr_ses; 2420Sstevel@tonic-gate char *err_str; 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate usr_ses = strtol(optarg, &err_str, 0); 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate if (usr_ses >= 1) { 2470Sstevel@tonic-gate max_sessions = usr_ses; 2480Sstevel@tonic-gate } else { 2490Sstevel@tonic-gate char behavior_str[MAX_MSG_LEN]; 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate snprintf(behavior_str, MAX_MSG_LEN, 2520Sstevel@tonic-gate "using default value (%d)", max_sessions); 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_OPT_ARG, optopt, 2550Sstevel@tonic-gate optarg, behavior_str); 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate break; 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate 2611120Smb158278 case 'a': 2621120Smb158278 case 'u': 2631120Smb158278 if (opt == 'a') 2641120Smb158278 ah_auth_alg = dcs_get_alg(auth_algs_array, 2651120Smb158278 optarg, &alg_ec); 2661120Smb158278 else /* opt == 'u' */ 2671120Smb158278 esp_auth_alg = dcs_get_alg(auth_algs_array, 2681120Smb158278 optarg, &alg_ec); 2691120Smb158278 2701120Smb158278 if (alg_ec == DCS_BAD_OPT_ARG) { 2711120Smb158278 dcs_log_bad_alg(optopt, optarg); 2721120Smb158278 (void) rdr_reject(dcsfd); 2731120Smb158278 exit(1); 2741120Smb158278 } 2751120Smb158278 2761120Smb158278 break; 2771120Smb158278 2781120Smb158278 case 'e': 2791120Smb158278 esp_encr_alg = dcs_get_alg(esp_algs_array, optarg, 2801120Smb158278 &alg_ec); 2811120Smb158278 2821120Smb158278 if (alg_ec == DCS_BAD_OPT_ARG) { 2831120Smb158278 dcs_log_bad_alg(optopt, optarg); 2841120Smb158278 (void) rdr_reject(dcsfd); 2851120Smb158278 exit(1); 2861120Smb158278 } 2871120Smb158278 2881120Smb158278 break; 2891120Smb158278 2900Sstevel@tonic-gate default: 2911120Smb158278 if (optopt == 'a' || optopt == 'e' || optopt == 'u') 2921120Smb158278 dcs_log_bad_alg(optopt, optarg); 2931120Smb158278 else 2941120Smb158278 dcs_log_msg(LOG_ERR, DCS_BAD_OPT, optopt); 2950Sstevel@tonic-gate (void) rdr_reject(dcsfd); 2960Sstevel@tonic-gate exit(1); 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* NOTREACHED */ 2990Sstevel@tonic-gate break; 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate 3031120Smb158278 /* 3041120Smb158278 * In the future if inetd supports per-socket IPsec dcs can be run 3051120Smb158278 * under inetd. 3061120Smb158278 * Daemonize if we were not started by inetd unless running standalone. 3071120Smb158278 */ 3081120Smb158278 inetd = is_socket(STDIN_FILENO); 3091120Smb158278 if (inetd == B_FALSE && standalone == 0) { 3101120Smb158278 closefrom(0); 3111120Smb158278 (void) chdir("/"); 3121120Smb158278 (void) umask(0); 3131120Smb158278 3141120Smb158278 if (fork() != 0) 3151120Smb158278 exit(0); 3161120Smb158278 3171120Smb158278 (void) setsid(); 3181120Smb158278 3191120Smb158278 /* open log again after all files were closed */ 3201120Smb158278 openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON); 3211120Smb158278 } 3221120Smb158278 3230Sstevel@tonic-gate DCS_DBG(DBG_ALL, "initializing %s...", cmdname); 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate init_signals(); 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate /* must be root */ 3280Sstevel@tonic-gate if (geteuid() != 0) { 3290Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_PRIV); 3300Sstevel@tonic-gate (void) rdr_reject(dcsfd); 3310Sstevel@tonic-gate exit(1); 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* 3350Sstevel@tonic-gate * Seed the random number generator for 3360Sstevel@tonic-gate * generating random session identifiers. 3370Sstevel@tonic-gate */ 3380Sstevel@tonic-gate gettimeofday(&tv, NULL); 3390Sstevel@tonic-gate srand48(tv.tv_usec); 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate /* initialize our transport endpoint */ 3421120Smb158278 if (init_server(&dcs_rcv, ah_auth_alg, esp_encr_alg, esp_auth_alg) == 3431120Smb158278 -1) { 3440Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_INIT_ERR); 3450Sstevel@tonic-gate (void) rdr_reject(dcsfd); 3460Sstevel@tonic-gate exit(1); 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate 3500Sstevel@tonic-gate DCS_DBG(DBG_ALL, "%s initialized, debug level = 0x%X, " 3510Sstevel@tonic-gate "max sessions = %d", cmdname, dcs_debug, max_sessions); 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate /* 3540Sstevel@tonic-gate * Main service loop 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate for (;;) { 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate /* wait for a connection request */ 3590Sstevel@tonic-gate if (ses_poll(&dcs_rcv, 1, BLOCKFOREVER) == -1) { 3600Sstevel@tonic-gate if (errno != EINTR) { 3610Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_INT_ERR, "poll", 3620Sstevel@tonic-gate strerror(errno)); 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate continue; 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate /* attempt to connect */ 3680Sstevel@tonic-gate newfd = rdr_connect_srv(dcs_rcv.fd); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate if ((newfd == RDR_ERROR) || (newfd == RDR_NET_ERR)) { 3710Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CONNECT_ERR); 3720Sstevel@tonic-gate continue; 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate /* process the session concurrently */ 3770Sstevel@tonic-gate if (ses_start(newfd) == -1) { 3780Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_HAND_ERR); 3790Sstevel@tonic-gate (void) rdr_close(newfd); 3800Sstevel@tonic-gate break; 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate close(dcs_rcv.fd); 3850Sstevel@tonic-gate return (1); 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /* 3901120Smb158278 * dcs_get_alg: 3911120Smb158278 * 3921120Smb158278 * Returns the ID of the first algorithm found in the 'algs' array 3931120Smb158278 * with a name matching 'arg'. If there is no matching algorithm, 3941120Smb158278 * 'error' is set to DCS_BAD_OPT_ARG, otherwise it is set to DCS_NO_ERR. 3951120Smb158278 * The 'algs' array must be terminated by an entry containing a NULL 3961120Smb158278 * 'arg_name' field. The 'error' argument must be a valid pointer. 3971120Smb158278 */ 3981120Smb158278 static uint8_t 3991120Smb158278 dcs_get_alg(dcs_alg_t *algs, char *arg, dcs_err_code *error) 4001120Smb158278 { 4011120Smb158278 dcs_alg_t *alg; 4021120Smb158278 4031120Smb158278 *error = DCS_NO_ERR; 4041120Smb158278 4051120Smb158278 for (alg = algs; alg->arg_name != NULL && arg != NULL; alg++) { 4061120Smb158278 if (strncmp(alg->arg_name, arg, strlen(alg->arg_name) + 1) 4071120Smb158278 == 0) { 4081120Smb158278 return (alg->alg_id); 4091120Smb158278 } 4101120Smb158278 } 4111120Smb158278 4121120Smb158278 *error = DCS_BAD_OPT_ARG; 4131120Smb158278 4141120Smb158278 return (0); 4151120Smb158278 } 4161120Smb158278 4171120Smb158278 4181120Smb158278 /* 4191120Smb158278 * dcs_log_bad_alg: 4201120Smb158278 * 4211120Smb158278 * Logs an appropriate message when an invalid command line argument 4221120Smb158278 * was provided. 'optarg' is the invalid argument string for the 4231120Smb158278 * command line option 'optopt', where 'optopt' = 'a' for the '-a' 4241120Smb158278 * option. A NULL 'optarg' indicates the required option was not 4251120Smb158278 * provided. 4261120Smb158278 */ 4271120Smb158278 static void 4281120Smb158278 dcs_log_bad_alg(char optopt, char *optarg) 4291120Smb158278 { 4301120Smb158278 if (optarg == NULL) { 4311120Smb158278 dcs_log_msg(LOG_ERR, DCS_BAD_OPT_ARG, optopt, 4321120Smb158278 "empty string", "an argument is required, exiting"); 4331120Smb158278 } else { 4341120Smb158278 dcs_log_msg(LOG_ERR, DCS_BAD_OPT_ARG, optopt, 4351120Smb158278 optarg, "exiting"); 4361120Smb158278 } 4371120Smb158278 } 4381120Smb158278 4391120Smb158278 4401120Smb158278 /* 4410Sstevel@tonic-gate * init_server: 4420Sstevel@tonic-gate * 4430Sstevel@tonic-gate * Perform all the operations that are required to initialize the 4440Sstevel@tonic-gate * transport endpoint used by the DCS. After this routine succeeds, 4450Sstevel@tonic-gate * the DCS is ready to accept session requests on its well known 4460Sstevel@tonic-gate * port. 4470Sstevel@tonic-gate */ 4480Sstevel@tonic-gate static int 4491120Smb158278 init_server(struct pollfd *pfd, uint8_t ah_auth_alg, uint8_t esp_encr_alg, 4501120Smb158278 uint8_t esp_auth_alg) 4510Sstevel@tonic-gate { 4520Sstevel@tonic-gate struct servent *se; 4530Sstevel@tonic-gate struct sockaddr_storage ss; 4540Sstevel@tonic-gate struct sockaddr_in *sin; 4550Sstevel@tonic-gate struct sockaddr_in6 *sin6; 4561120Smb158278 ipsec_req_t ipsec_req; 4570Sstevel@tonic-gate int req_port; 4580Sstevel@tonic-gate int act_port; 4590Sstevel@tonic-gate int init_status; 4600Sstevel@tonic-gate int num_sock_opts; 4610Sstevel@tonic-gate int sock_opts[] = { SO_REUSEADDR }; 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate assert(pfd); 4651120Smb158278 pfd->fd = dcsfd; 4661120Smb158278 pfd->events = POLLIN | POLLPRI; 4671120Smb158278 pfd->revents = 0; 4681120Smb158278 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate /* 4710Sstevel@tonic-gate * In standalone mode, we have to initialize the transport 4720Sstevel@tonic-gate * endpoint for our reserved port. In daemon mode, inetd 4730Sstevel@tonic-gate * starts the DCS and hands off STDIN_FILENO connected to 4740Sstevel@tonic-gate * our reserved port. 4750Sstevel@tonic-gate */ 4760Sstevel@tonic-gate 4771120Smb158278 if (inetd == B_FALSE || standalone) { 4780Sstevel@tonic-gate /* in standalone mode, init fd for reserved port */ 4790Sstevel@tonic-gate if ((dcsfd = rdr_open(AF_INET6)) == -1) { 4800Sstevel@tonic-gate DCS_DBG(DBG_ALL, "rdr_open failed"); 4811120Smb158278 return (-1); 4821120Smb158278 } 4831120Smb158278 pfd->fd = dcsfd; 4841120Smb158278 4851120Smb158278 /* 4861120Smb158278 * Enable per-socket IPsec if the user specified an 487*1518Smb158278 * AH or ESP algorithm to use and global policy is not in 488*1518Smb158278 * effect. 4891120Smb158278 */ 490*1518Smb158278 if (!dcs_global_policy() && 491*1518Smb158278 (ah_auth_alg != SADB_AALG_NONE || 4921120Smb158278 esp_encr_alg != SADB_EALG_NONE || 493*1518Smb158278 esp_auth_alg != SADB_AALG_NONE)) { 4941120Smb158278 int err; 4951120Smb158278 4961120Smb158278 bzero(&ipsec_req, sizeof (ipsec_req)); 4971120Smb158278 4981120Smb158278 /* Hardcoded values */ 4991120Smb158278 ipsec_req.ipsr_self_encap_req = SELF_ENCAP_REQ; 5001120Smb158278 /* User defined */ 5011120Smb158278 ipsec_req.ipsr_auth_alg = ah_auth_alg; 5021120Smb158278 ipsec_req.ipsr_esp_alg = esp_encr_alg; 5031120Smb158278 if (ah_auth_alg != SADB_AALG_NONE) 5041120Smb158278 ipsec_req.ipsr_ah_req = AH_REQ; 5051120Smb158278 if (esp_encr_alg != SADB_EALG_NONE || 5061120Smb158278 esp_auth_alg != SADB_AALG_NONE) { 5071120Smb158278 ipsec_req.ipsr_esp_req = ESP_REQ; 5081120Smb158278 ipsec_req.ipsr_esp_auth_alg = esp_auth_alg; 5091120Smb158278 } 5101120Smb158278 5111120Smb158278 err = rdr_setsockopt(pfd->fd, IPPROTO_IPV6, 5121120Smb158278 IPV6_SEC_OPT, (void *)&ipsec_req, 5131120Smb158278 sizeof (ipsec_req)); 5141120Smb158278 5151120Smb158278 if (err != RDR_OK) { 5161120Smb158278 DCS_DBG(DBG_ALL, "rdr_setsockopt failed"); 5171120Smb158278 return (-1); 5181120Smb158278 } 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate /* 5230Sstevel@tonic-gate * Look up our service to get the reserved port number 5240Sstevel@tonic-gate */ 5250Sstevel@tonic-gate if ((se = getservbyname(DCS_SERVICE, "tcp")) == NULL) { 5260Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_NO_SERV, DCS_SERVICE); 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate /* use the known port if service wasn't found */ 5290Sstevel@tonic-gate req_port = SUN_DR_PORT; 5300Sstevel@tonic-gate } else { 5310Sstevel@tonic-gate req_port = se->s_port; 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate /* initialize our local address */ 5350Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)&ss; 5360Sstevel@tonic-gate (void) memset(sin6, 0, sizeof (*sin6)); 5370Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 5380Sstevel@tonic-gate sin6->sin6_port = htons(req_port); 5390Sstevel@tonic-gate sin6->sin6_addr = in6addr_any; 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate num_sock_opts = sizeof (sock_opts) / sizeof (*sock_opts); 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate init_status = rdr_init(pfd->fd, (struct sockaddr *)sin6, 5440Sstevel@tonic-gate sock_opts, num_sock_opts, DCS_BACKLOG); 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate if (init_status != RDR_OK) { 5470Sstevel@tonic-gate return (-1); 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate switch (ss.ss_family) { 5510Sstevel@tonic-gate case AF_INET: 5520Sstevel@tonic-gate DCS_DBG(DBG_ALL, "using AF_INET socket"); 5530Sstevel@tonic-gate sin = (struct sockaddr_in *)&ss; 5540Sstevel@tonic-gate act_port = ntohs(sin->sin_port); 5550Sstevel@tonic-gate break; 5560Sstevel@tonic-gate case AF_INET6: 5570Sstevel@tonic-gate DCS_DBG(DBG_ALL, "using AF_INET6 socket"); 5580Sstevel@tonic-gate /* sin6 already set correctly */ 5590Sstevel@tonic-gate act_port = ntohs(sin6->sin6_port); 5600Sstevel@tonic-gate break; 5610Sstevel@tonic-gate default: 5620Sstevel@tonic-gate DCS_DBG(DBG_ALL, "unknown socket type"); 5630Sstevel@tonic-gate return (-1); 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate /* check that we got the requested port */ 5670Sstevel@tonic-gate if (req_port != act_port) { 5680Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_PORT, req_port); 5690Sstevel@tonic-gate return (-1); 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate return (0); 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate 5760Sstevel@tonic-gate /* 5770Sstevel@tonic-gate * init_signals: 5780Sstevel@tonic-gate * 5790Sstevel@tonic-gate * Initialize signals for the current session. All signals will be 5800Sstevel@tonic-gate * blocked with two possible exceptions. SIGINT is not blocked in 5810Sstevel@tonic-gate * standalone mode, and ses_init_signals() is called to selectively 5820Sstevel@tonic-gate * unblock any signals required to handle concurrent sessions. 5830Sstevel@tonic-gate */ 5840Sstevel@tonic-gate static void 5850Sstevel@tonic-gate init_signals(void) 5860Sstevel@tonic-gate { 5870Sstevel@tonic-gate sigset_t mask; 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate /* block all signals */ 5910Sstevel@tonic-gate sigfillset(&mask); 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate /* in standalone, allow user to abort */ 5940Sstevel@tonic-gate if (standalone) { 5950Sstevel@tonic-gate sigdelset(&mask, SIGINT); 5960Sstevel@tonic-gate } 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate ses_init_signals(&mask); 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &mask, NULL); 6010Sstevel@tonic-gate } 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate /* 6050Sstevel@tonic-gate * dcs_dispatch_message: 6060Sstevel@tonic-gate * 6070Sstevel@tonic-gate * This function dispatches a message to the correct function. The 6080Sstevel@tonic-gate * correct handler is determined by the opcode field of the message 6090Sstevel@tonic-gate * header. 6100Sstevel@tonic-gate */ 6110Sstevel@tonic-gate int 6120Sstevel@tonic-gate dcs_dispatch_message(rdr_msg_hdr_t *hdr, cfga_params_t *params) 6130Sstevel@tonic-gate { 6140Sstevel@tonic-gate session_t *sp; 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate 6170Sstevel@tonic-gate assert(hdr); 6180Sstevel@tonic-gate assert(params); 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate /* get the current session information */ 6210Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 6220Sstevel@tonic-gate ses_close(DCS_ERROR); 6230Sstevel@tonic-gate return (-1); 6240Sstevel@tonic-gate } 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate /* check the message */ 6270Sstevel@tonic-gate if (invalid_msg(hdr)) { 6280Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 6290Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 6300Sstevel@tonic-gate return (-1); 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate /* save the current message */ 6340Sstevel@tonic-gate sp->curr_msg.hdr = hdr; 6350Sstevel@tonic-gate sp->curr_msg.params = params; 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate /* 6380Sstevel@tonic-gate * hdr->message_opcode is unsigned so don't need 6390Sstevel@tonic-gate * to check for values less than zero 6400Sstevel@tonic-gate */ 6410Sstevel@tonic-gate if (hdr->message_opcode >= RDR_NUM_OPS) { 6420Sstevel@tonic-gate dcs_unknown_op(hdr, params); 6430Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 6440Sstevel@tonic-gate return (-1); 6450Sstevel@tonic-gate } 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate PRINT_MSG_DBG(DCS_RECEIVE, hdr); 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate /* dispatch the message */ 6500Sstevel@tonic-gate if ((*dcs_cmd[hdr->message_opcode])(hdr, params) == -1) { 6510Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_FAILED); 6520Sstevel@tonic-gate ses_close(DCS_ERROR); 6530Sstevel@tonic-gate return (-1); 6540Sstevel@tonic-gate } 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate return (0); 6570Sstevel@tonic-gate } 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate /* 6610Sstevel@tonic-gate * init_msg: 6620Sstevel@tonic-gate * 6630Sstevel@tonic-gate * Initialize the message header with information from the current 6640Sstevel@tonic-gate * session. Fields not set directly are initialized to zero. 6650Sstevel@tonic-gate */ 6660Sstevel@tonic-gate void 6670Sstevel@tonic-gate init_msg(rdr_msg_hdr_t *hdr) 6680Sstevel@tonic-gate { 6690Sstevel@tonic-gate session_t *sp; 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate assert(hdr); 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate /* get the current session information */ 6750Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 6760Sstevel@tonic-gate ses_close(DCS_ERROR); 6770Sstevel@tonic-gate return; 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate (void) memset(hdr, 0, sizeof (rdr_msg_hdr_t)); 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate /* set the session information */ 6830Sstevel@tonic-gate hdr->random_req = sp->random_req; 6840Sstevel@tonic-gate hdr->random_resp = sp->random_resp; 6850Sstevel@tonic-gate 6860Sstevel@tonic-gate /* set the version being used */ 6870Sstevel@tonic-gate hdr->major_version = sp->major_version; 6880Sstevel@tonic-gate hdr->minor_version = sp->minor_version; 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate /* 6930Sstevel@tonic-gate * invalid_msg: 6940Sstevel@tonic-gate * 6950Sstevel@tonic-gate * Check if the message is valid for the current session. This 6960Sstevel@tonic-gate * is accomplished by checking various information in the header 6970Sstevel@tonic-gate * against the information for the current session. 6980Sstevel@tonic-gate */ 6990Sstevel@tonic-gate static int 7000Sstevel@tonic-gate invalid_msg(rdr_msg_hdr_t *hdr) 7010Sstevel@tonic-gate { 7020Sstevel@tonic-gate session_t *sp; 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate assert(hdr); 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate /* get the current session information */ 7080Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 7090Sstevel@tonic-gate ses_close(DCS_ERROR); 7100Sstevel@tonic-gate return (-1); 7110Sstevel@tonic-gate } 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate /* 7140Sstevel@tonic-gate * Only perform the following checks if the message 7150Sstevel@tonic-gate * is not a session request. The information to check 7160Sstevel@tonic-gate * will not be set at the time a session request is 7170Sstevel@tonic-gate * received. 7180Sstevel@tonic-gate */ 7190Sstevel@tonic-gate if (hdr->message_opcode != RDR_SES_REQ) { 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate /* check major and minor version */ 7220Sstevel@tonic-gate if ((sp->major_version != hdr->major_version) || 7230Sstevel@tonic-gate (sp->minor_version != hdr->minor_version)) { 7240Sstevel@tonic-gate DCS_DBG(DBG_MSG, "unsupported version %d.%d", 7250Sstevel@tonic-gate hdr->major_version, hdr->minor_version); 7260Sstevel@tonic-gate return (-1); 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate /* check session identifiers */ 7300Sstevel@tonic-gate if ((sp->random_req != hdr->random_req) || 7310Sstevel@tonic-gate (sp->random_resp != hdr->random_resp)) { 7320Sstevel@tonic-gate DCS_DBG(DBG_MSG, "invalid session identifiers: " 7330Sstevel@tonic-gate "<%d, %d>", hdr->random_req, hdr->random_resp); 7340Sstevel@tonic-gate return (-1); 7350Sstevel@tonic-gate } 7360Sstevel@tonic-gate } 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate return (0); 7390Sstevel@tonic-gate } 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate /* 7430Sstevel@tonic-gate * dcs_ses_req: 7440Sstevel@tonic-gate * 7450Sstevel@tonic-gate * Handle a session request message (RDR_SES_REQ). 7460Sstevel@tonic-gate */ 7470Sstevel@tonic-gate static int 7480Sstevel@tonic-gate dcs_ses_req(rdr_msg_hdr_t *hdr, cfga_params_t *param) 7490Sstevel@tonic-gate { 7500Sstevel@tonic-gate session_t *sp; 7510Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 7520Sstevel@tonic-gate cfga_params_t reply_param; 7530Sstevel@tonic-gate dcs_ver_t act_ver; 7540Sstevel@tonic-gate int snd_status; 7550Sstevel@tonic-gate static char *op_name = "session request"; 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate 7580Sstevel@tonic-gate assert(hdr); 7590Sstevel@tonic-gate assert(param); 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate /* get the current session information */ 7620Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 7630Sstevel@tonic-gate ses_close(DCS_ERROR); 7640Sstevel@tonic-gate return (-1); 7650Sstevel@tonic-gate } 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate /* make sure that a session hasn't been requested yet */ 7680Sstevel@tonic-gate if (sp->state != DCS_CONNECTED) { 7690Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_SEQ_INVAL); 7700Sstevel@tonic-gate ses_close(DCS_SES_SEQ_INVAL); 7710Sstevel@tonic-gate return (-1); 7720Sstevel@tonic-gate } 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate ses_setlocale(param->req.locale_str); 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate /* get the best matching version supported */ 7770Sstevel@tonic-gate act_ver = resolve_version(hdr->major_version, hdr->minor_version); 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate /* initialize session information */ 7800Sstevel@tonic-gate sp->random_req = hdr->random_req; 7810Sstevel@tonic-gate sp->major_version = act_ver.major; 7820Sstevel@tonic-gate sp->minor_version = act_ver.minor; 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate /* prepare header information */ 7850Sstevel@tonic-gate init_msg(&reply_hdr); 7860Sstevel@tonic-gate reply_hdr.message_opcode = RDR_SES_REQ; 7870Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 7880Sstevel@tonic-gate reply_hdr.status = DCS_OK; 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate /* prepare session request specific data */ 7910Sstevel@tonic-gate (void) memset(&reply_param, 0, sizeof (cfga_params_t)); 7920Sstevel@tonic-gate reply_param.req.session_id = sp->id; 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate /* send the message */ 7970Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, &reply_param, 7980Sstevel@tonic-gate DCS_SND_TIMEOUT); 7990Sstevel@tonic-gate 8000Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 8010Sstevel@tonic-gate abort_handler(); 8020Sstevel@tonic-gate } 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate if (snd_status != RDR_OK) { 8050Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 8060Sstevel@tonic-gate return (-1); 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate sp->state = DCS_SES_REQ; 8100Sstevel@tonic-gate return (0); 8110Sstevel@tonic-gate } 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate 8140Sstevel@tonic-gate /* 8150Sstevel@tonic-gate * dcs_ses_estbl: 8160Sstevel@tonic-gate * 8170Sstevel@tonic-gate * Handle a session establishment message (RDR_SES_ESTBL). 8180Sstevel@tonic-gate */ 8190Sstevel@tonic-gate /* ARGSUSED */ 8200Sstevel@tonic-gate static int 8210Sstevel@tonic-gate dcs_ses_estbl(rdr_msg_hdr_t *hdr, cfga_params_t *param) 8220Sstevel@tonic-gate { 8230Sstevel@tonic-gate session_t *sp; 8240Sstevel@tonic-gate dcs_ver_t act_ver; 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate assert(hdr); 8280Sstevel@tonic-gate assert(param); 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate /* get the current session information */ 8310Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 8320Sstevel@tonic-gate ses_close(DCS_ERROR); 8330Sstevel@tonic-gate return (-1); 8340Sstevel@tonic-gate } 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate /* 8370Sstevel@tonic-gate * Make sure that a session has not been 8380Sstevel@tonic-gate * established yet, and that a session 8390Sstevel@tonic-gate * request has already been processed. 8400Sstevel@tonic-gate */ 8410Sstevel@tonic-gate if (sp->state != DCS_SES_REQ) { 8420Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_SEQ_INVAL); 8430Sstevel@tonic-gate ses_close(DCS_SES_SEQ_INVAL); 8440Sstevel@tonic-gate return (-1); 8450Sstevel@tonic-gate } 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate /* get the best matching version supported */ 8480Sstevel@tonic-gate act_ver = resolve_version(hdr->major_version, hdr->minor_version); 8490Sstevel@tonic-gate 8500Sstevel@tonic-gate if ((act_ver.major != hdr->major_version) || 8510Sstevel@tonic-gate (act_ver.minor != hdr->minor_version)) { 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate /* end the session because protocol not supported */ 8540Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_VER_INVAL, hdr->major_version, 8550Sstevel@tonic-gate hdr->minor_version); 8560Sstevel@tonic-gate ses_close(DCS_VER_INVAL); 8570Sstevel@tonic-gate return (-1); 8580Sstevel@tonic-gate } 8590Sstevel@tonic-gate 8600Sstevel@tonic-gate DCS_DBG(DBG_SES, "Session Established"); 8610Sstevel@tonic-gate sp->state = DCS_SES_ESTBL; 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate return (0); 8640Sstevel@tonic-gate } 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate 8670Sstevel@tonic-gate /* 8680Sstevel@tonic-gate * dcs_ses_end: 8690Sstevel@tonic-gate * 8700Sstevel@tonic-gate * Handle a session end message (RDR_SES_END). 8710Sstevel@tonic-gate */ 8720Sstevel@tonic-gate static int 8730Sstevel@tonic-gate dcs_ses_end(rdr_msg_hdr_t *hdr, cfga_params_t *param) 8740Sstevel@tonic-gate { 8750Sstevel@tonic-gate session_t *sp; 8760Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 8770Sstevel@tonic-gate cfga_params_t reply_param; 8780Sstevel@tonic-gate int snd_status; 8790Sstevel@tonic-gate static char *op_name = "session end"; 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate 8820Sstevel@tonic-gate assert(hdr); 8830Sstevel@tonic-gate assert(param); 8840Sstevel@tonic-gate 8850Sstevel@tonic-gate /* get the current session information */ 8860Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 8870Sstevel@tonic-gate ses_close(DCS_ERROR); 8880Sstevel@tonic-gate return (-1); 8890Sstevel@tonic-gate } 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate /* 8920Sstevel@tonic-gate * Session end is valid from any state. However, only 8930Sstevel@tonic-gate * send back a reply if the error code is zero. A non-zero 8940Sstevel@tonic-gate * error code indicates that the session is being terminated 8950Sstevel@tonic-gate * under an error condition, and no acknowledgement is 8960Sstevel@tonic-gate * required. 8970Sstevel@tonic-gate */ 8980Sstevel@tonic-gate if (param->end.error_code == 0) { 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate /* prepare header information */ 9010Sstevel@tonic-gate init_msg(&reply_hdr); 9020Sstevel@tonic-gate reply_hdr.message_opcode = RDR_SES_END; 9030Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 9040Sstevel@tonic-gate reply_hdr.status = DCS_OK; 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate /* return empty data - no information needed in reply */ 9070Sstevel@tonic-gate (void) memset(&reply_param, 0, sizeof (cfga_params_t)); 9080Sstevel@tonic-gate 9090Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, &reply_param, 9120Sstevel@tonic-gate DCS_SND_TIMEOUT); 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 9150Sstevel@tonic-gate abort_handler(); 9160Sstevel@tonic-gate } 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate if (snd_status != RDR_OK) { 9190Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 9200Sstevel@tonic-gate } 9210Sstevel@tonic-gate } 9220Sstevel@tonic-gate 9230Sstevel@tonic-gate sp->state = DCS_SES_END; 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 9260Sstevel@tonic-gate } 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate /* 9300Sstevel@tonic-gate * dcs_change_state: 9310Sstevel@tonic-gate * 9320Sstevel@tonic-gate * Handle a change state request message (RDR_CONF_CHANGE_STATE). 9330Sstevel@tonic-gate */ 9340Sstevel@tonic-gate static int 9350Sstevel@tonic-gate dcs_change_state(rdr_msg_hdr_t *hdr, cfga_params_t *param) 9360Sstevel@tonic-gate { 9370Sstevel@tonic-gate session_t *sp; 9380Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 9390Sstevel@tonic-gate change_state_params_t *op_data; 9400Sstevel@tonic-gate struct cfga_confirm local_conf_cb; 9410Sstevel@tonic-gate struct cfga_msg local_msg_cb; 9420Sstevel@tonic-gate int cfga_status = 0; 9430Sstevel@tonic-gate int snd_status; 9440Sstevel@tonic-gate char *err_str; 9450Sstevel@tonic-gate unsigned int curr_attempt; 9460Sstevel@tonic-gate unsigned int num_attempts; 9470Sstevel@tonic-gate char retry_msg[MAX_MSG_LEN]; 9480Sstevel@tonic-gate static char *op_name = "config_change_state"; 9490Sstevel@tonic-gate 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate assert(hdr); 9520Sstevel@tonic-gate assert(param); 9530Sstevel@tonic-gate 9540Sstevel@tonic-gate /* get the current session information */ 9550Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 9560Sstevel@tonic-gate ses_close(DCS_ERROR); 9570Sstevel@tonic-gate return (-1); 9580Sstevel@tonic-gate } 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate op_data = ¶m->change; 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate /* make sure we have a session established */ 9630Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 9640Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 9650Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 9660Sstevel@tonic-gate return (-1); 9670Sstevel@tonic-gate } 9680Sstevel@tonic-gate 9690Sstevel@tonic-gate /* initialize local confirm callback */ 9700Sstevel@tonic-gate local_conf_cb.confirm = dcs_confirm_callback; 9710Sstevel@tonic-gate local_conf_cb.appdata_ptr = (void *)op_data->confp; 9720Sstevel@tonic-gate 9730Sstevel@tonic-gate /* initialize local message callback */ 9740Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 9750Sstevel@tonic-gate local_msg_cb.appdata_ptr = (void *)op_data->msgp; 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate /* verify retry value */ 9780Sstevel@tonic-gate if (op_data->retries < 0) { 9790Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_RETRY_VAL, op_data->retries); 9800Sstevel@tonic-gate op_data->retries = 0; 9810Sstevel@tonic-gate } 9820Sstevel@tonic-gate 9830Sstevel@tonic-gate /* verify timeout value */ 9840Sstevel@tonic-gate if (op_data->timeval < 0) { 9850Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_TIME_VAL, op_data->timeval); 9860Sstevel@tonic-gate op_data->timeval = 0; 9870Sstevel@tonic-gate } 9880Sstevel@tonic-gate 9890Sstevel@tonic-gate num_attempts = 1 + op_data->retries; 9900Sstevel@tonic-gate curr_attempt = 0; 9910Sstevel@tonic-gate 9920Sstevel@tonic-gate while (curr_attempt < num_attempts) { 9930Sstevel@tonic-gate 9940Sstevel@tonic-gate /* don't sleep the first time around */ 9950Sstevel@tonic-gate if (curr_attempt != 0) { 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate /* log the error message and alert the user */ 9980Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 9990Sstevel@tonic-gate if (err_str) { 10000Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, 10010Sstevel@tonic-gate err_str); 10020Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, 10030Sstevel@tonic-gate err_str); 10040Sstevel@tonic-gate free((void *)err_str); 10050Sstevel@tonic-gate } else { 10060Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_UNKNOWN); 10070Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, 10080Sstevel@tonic-gate dcs_strerror(DCS_CFGA_UNKNOWN)); 10090Sstevel@tonic-gate } 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 10120Sstevel@tonic-gate free((void *)*op_data->errstring); 10130Sstevel@tonic-gate *op_data->errstring = NULL; 10140Sstevel@tonic-gate } 10150Sstevel@tonic-gate 10160Sstevel@tonic-gate /* sleep with abort enabled */ 10170Sstevel@tonic-gate ses_sleep(op_data->timeval); 10180Sstevel@tonic-gate 10190Sstevel@tonic-gate /* log the retry attempt and alert the user */ 10200Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_RETRY, curr_attempt); 10210Sstevel@tonic-gate snprintf(retry_msg, MAX_MSG_LEN, 10220Sstevel@tonic-gate dcs_strerror(DCS_RETRY), curr_attempt); 10230Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, retry_msg); 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 10270Sstevel@tonic-gate 10280Sstevel@tonic-gate /* 10290Sstevel@tonic-gate * Call into libcfgadm 10300Sstevel@tonic-gate */ 10310Sstevel@tonic-gate ses_abort_enable(); 10320Sstevel@tonic-gate 10330Sstevel@tonic-gate cfga_status = config_change_state(op_data->state_change, 10340Sstevel@tonic-gate op_data->num_ap_ids, op_data->ap_ids, op_data->options, 10350Sstevel@tonic-gate &local_conf_cb, &local_msg_cb, op_data->errstring, 10360Sstevel@tonic-gate op_data->flags); 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate ses_abort_disable(); 10390Sstevel@tonic-gate 10400Sstevel@tonic-gate /* 10410Sstevel@tonic-gate * Retry only the operations that have a chance to 10420Sstevel@tonic-gate * succeed if retried. All libcfgadm errors not 10430Sstevel@tonic-gate * included below will always fail, regardless of 10440Sstevel@tonic-gate * a retry. 10450Sstevel@tonic-gate */ 10460Sstevel@tonic-gate if ((cfga_status != CFGA_BUSY) && 10470Sstevel@tonic-gate (cfga_status != CFGA_SYSTEM_BUSY) && 10480Sstevel@tonic-gate (cfga_status != CFGA_ERROR)) { 10490Sstevel@tonic-gate break; 10500Sstevel@tonic-gate } 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate /* prepare for another attempt */ 10530Sstevel@tonic-gate ++curr_attempt; 10540Sstevel@tonic-gate } 10550Sstevel@tonic-gate 10560Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 10570Sstevel@tonic-gate 10580Sstevel@tonic-gate /* log any libcfgadm errors */ 10590Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 10600Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 10610Sstevel@tonic-gate if (err_str) { 10620Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 10630Sstevel@tonic-gate free((void *)err_str); 10640Sstevel@tonic-gate } 10650Sstevel@tonic-gate } 10660Sstevel@tonic-gate 10670Sstevel@tonic-gate /* prepare header information */ 10680Sstevel@tonic-gate init_msg(&reply_hdr); 10690Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_CHANGE_STATE; 10700Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 10710Sstevel@tonic-gate reply_hdr.status = cfga_status; 10720Sstevel@tonic-gate 10730Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate /* send the message */ 10760Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 10790Sstevel@tonic-gate abort_handler(); 10800Sstevel@tonic-gate } 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate if (snd_status != RDR_OK) { 10830Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 10840Sstevel@tonic-gate } 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate /* clean up */ 10870Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 10880Sstevel@tonic-gate free((void *)*op_data->errstring); 10890Sstevel@tonic-gate *op_data->errstring = NULL; 10900Sstevel@tonic-gate } 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 10930Sstevel@tonic-gate } 10940Sstevel@tonic-gate 10950Sstevel@tonic-gate 10960Sstevel@tonic-gate /* 10970Sstevel@tonic-gate * dcs_private_func: 10980Sstevel@tonic-gate * 10990Sstevel@tonic-gate * Handle a private function request message (RDR_CONF_PRIVATE_FUNC). 11000Sstevel@tonic-gate */ 11010Sstevel@tonic-gate static int 11020Sstevel@tonic-gate dcs_private_func(rdr_msg_hdr_t *hdr, cfga_params_t *param) 11030Sstevel@tonic-gate { 11040Sstevel@tonic-gate session_t *sp; 11050Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 11060Sstevel@tonic-gate private_func_params_t *op_data; 11070Sstevel@tonic-gate struct cfga_confirm local_conf_cb; 11080Sstevel@tonic-gate struct cfga_msg local_msg_cb; 11090Sstevel@tonic-gate int cfga_status; 11100Sstevel@tonic-gate int snd_status; 11110Sstevel@tonic-gate char *err_str; 11120Sstevel@tonic-gate static char *op_name = "config_private_func"; 11130Sstevel@tonic-gate 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate assert(hdr); 11160Sstevel@tonic-gate assert(param); 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate /* get the current session information */ 11190Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 11200Sstevel@tonic-gate ses_close(DCS_ERROR); 11210Sstevel@tonic-gate return (-1); 11220Sstevel@tonic-gate } 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate op_data = ¶m->priv; 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate /* make sure we have a session established */ 11270Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 11280Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 11290Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 11300Sstevel@tonic-gate return (-1); 11310Sstevel@tonic-gate } 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate /* initialize local confirm callback */ 11340Sstevel@tonic-gate local_conf_cb.confirm = dcs_confirm_callback; 11350Sstevel@tonic-gate local_conf_cb.appdata_ptr = (void *)op_data->confp; 11360Sstevel@tonic-gate 11370Sstevel@tonic-gate /* initialize local message callback */ 11380Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 11390Sstevel@tonic-gate local_msg_cb.appdata_ptr = (void *)op_data->msgp; 11400Sstevel@tonic-gate 11410Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 11420Sstevel@tonic-gate 11430Sstevel@tonic-gate /* 11440Sstevel@tonic-gate * Call into libcfgadm 11450Sstevel@tonic-gate */ 11460Sstevel@tonic-gate ses_abort_enable(); 11470Sstevel@tonic-gate 11480Sstevel@tonic-gate cfga_status = config_private_func(op_data->function, 11490Sstevel@tonic-gate op_data->num_ap_ids, op_data->ap_ids, op_data->options, 11500Sstevel@tonic-gate &local_conf_cb, &local_msg_cb, op_data->errstring, op_data->flags); 11510Sstevel@tonic-gate 11520Sstevel@tonic-gate ses_abort_disable(); 11530Sstevel@tonic-gate 11540Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate /* log any libcfgadm errors */ 11570Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 11580Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 11590Sstevel@tonic-gate if (err_str) { 11600Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 11610Sstevel@tonic-gate free((void *)err_str); 11620Sstevel@tonic-gate } 11630Sstevel@tonic-gate } 11640Sstevel@tonic-gate 11650Sstevel@tonic-gate /* prepare header information */ 11660Sstevel@tonic-gate init_msg(&reply_hdr); 11670Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_PRIVATE_FUNC; 11680Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 11690Sstevel@tonic-gate reply_hdr.status = cfga_status; 11700Sstevel@tonic-gate 11710Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 11720Sstevel@tonic-gate 11730Sstevel@tonic-gate /* send the message */ 11740Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 11750Sstevel@tonic-gate 11760Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 11770Sstevel@tonic-gate abort_handler(); 11780Sstevel@tonic-gate } 11790Sstevel@tonic-gate 11800Sstevel@tonic-gate if (snd_status != RDR_OK) { 11810Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 11820Sstevel@tonic-gate } 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 11850Sstevel@tonic-gate free((void *)*op_data->errstring); 11860Sstevel@tonic-gate *op_data->errstring = NULL; 11870Sstevel@tonic-gate } 11880Sstevel@tonic-gate 11890Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 11900Sstevel@tonic-gate } 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate 11930Sstevel@tonic-gate /* 11940Sstevel@tonic-gate * dcs_test: 11950Sstevel@tonic-gate * 11960Sstevel@tonic-gate * Handle a test request message (RDR_CONF_TEST). 11970Sstevel@tonic-gate */ 11980Sstevel@tonic-gate static int 11990Sstevel@tonic-gate dcs_test(rdr_msg_hdr_t *hdr, cfga_params_t *param) 12000Sstevel@tonic-gate { 12010Sstevel@tonic-gate session_t *sp; 12020Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 12030Sstevel@tonic-gate test_params_t *op_data; 12040Sstevel@tonic-gate struct cfga_msg local_msg_cb; 12050Sstevel@tonic-gate int cfga_status; 12060Sstevel@tonic-gate int snd_status; 12070Sstevel@tonic-gate char *err_str; 12080Sstevel@tonic-gate static char *op_name = "config_test"; 12090Sstevel@tonic-gate 12100Sstevel@tonic-gate 12110Sstevel@tonic-gate assert(hdr); 12120Sstevel@tonic-gate assert(param); 12130Sstevel@tonic-gate 12140Sstevel@tonic-gate /* get the current session information */ 12150Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 12160Sstevel@tonic-gate ses_close(DCS_ERROR); 12170Sstevel@tonic-gate return (-1); 12180Sstevel@tonic-gate } 12190Sstevel@tonic-gate 12200Sstevel@tonic-gate op_data = ¶m->test; 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate /* make sure we have a session established */ 12230Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 12240Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 12250Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 12260Sstevel@tonic-gate return (-1); 12270Sstevel@tonic-gate } 12280Sstevel@tonic-gate 12290Sstevel@tonic-gate /* initialize local message callback */ 12300Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 12310Sstevel@tonic-gate local_msg_cb.appdata_ptr = op_data->msgp; 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 12340Sstevel@tonic-gate 12350Sstevel@tonic-gate /* 12360Sstevel@tonic-gate * Call into libcfgadm 12370Sstevel@tonic-gate */ 12380Sstevel@tonic-gate ses_abort_enable(); 12390Sstevel@tonic-gate 12400Sstevel@tonic-gate cfga_status = config_test(op_data->num_ap_ids, op_data->ap_ids, 12410Sstevel@tonic-gate op_data->options, &local_msg_cb, op_data->errstring, 12420Sstevel@tonic-gate op_data->flags); 12430Sstevel@tonic-gate 12440Sstevel@tonic-gate ses_abort_disable(); 12450Sstevel@tonic-gate 12460Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 12470Sstevel@tonic-gate 12480Sstevel@tonic-gate /* log any libcfgadm errors */ 12490Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 12500Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 12510Sstevel@tonic-gate if (err_str) { 12520Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 12530Sstevel@tonic-gate free((void *)err_str); 12540Sstevel@tonic-gate } 12550Sstevel@tonic-gate } 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate /* prepare header information */ 12580Sstevel@tonic-gate init_msg(&reply_hdr); 12590Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_TEST; 12600Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 12610Sstevel@tonic-gate reply_hdr.status = cfga_status; 12620Sstevel@tonic-gate 12630Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 12640Sstevel@tonic-gate 12650Sstevel@tonic-gate /* send the message */ 12660Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 12690Sstevel@tonic-gate abort_handler(); 12700Sstevel@tonic-gate } 12710Sstevel@tonic-gate 12720Sstevel@tonic-gate if (snd_status != RDR_OK) { 12730Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 12740Sstevel@tonic-gate } 12750Sstevel@tonic-gate 12760Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 12770Sstevel@tonic-gate free((void *)*op_data->errstring); 12780Sstevel@tonic-gate *op_data->errstring = NULL; 12790Sstevel@tonic-gate } 12800Sstevel@tonic-gate 12810Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 12820Sstevel@tonic-gate } 12830Sstevel@tonic-gate 12840Sstevel@tonic-gate 12850Sstevel@tonic-gate /* 12860Sstevel@tonic-gate * dcs_list_ext: 12870Sstevel@tonic-gate * 12880Sstevel@tonic-gate * Handle a list request message (RDR_CONF_LIST_EXT). 12890Sstevel@tonic-gate */ 12900Sstevel@tonic-gate static int 12910Sstevel@tonic-gate dcs_list_ext(rdr_msg_hdr_t *hdr, cfga_params_t *param) 12920Sstevel@tonic-gate { 12930Sstevel@tonic-gate session_t *sp; 12940Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 12950Sstevel@tonic-gate list_ext_params_t *op_data; 12960Sstevel@tonic-gate int cfga_status; 12970Sstevel@tonic-gate int snd_status; 12980Sstevel@tonic-gate char *err_str; 12990Sstevel@tonic-gate static char *op_name = "config_list_ext"; 13000Sstevel@tonic-gate cfga_list_data_t *ap_ids; 13010Sstevel@tonic-gate 13020Sstevel@tonic-gate 13030Sstevel@tonic-gate assert(hdr); 13040Sstevel@tonic-gate assert(param); 13050Sstevel@tonic-gate 13060Sstevel@tonic-gate /* get the current session information */ 13070Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 13080Sstevel@tonic-gate ses_close(DCS_ERROR); 13090Sstevel@tonic-gate return (-1); 13100Sstevel@tonic-gate } 13110Sstevel@tonic-gate 13120Sstevel@tonic-gate op_data = ¶m->list_ext; 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate /* make sure we have a session established */ 13150Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 13160Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 13170Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 13180Sstevel@tonic-gate return (-1); 13190Sstevel@tonic-gate } 13200Sstevel@tonic-gate 13210Sstevel@tonic-gate /* 13220Sstevel@tonic-gate * Make sure that we can retrieve the data 13230Sstevel@tonic-gate * from libcfgadm. If not, report the error. 13240Sstevel@tonic-gate */ 13250Sstevel@tonic-gate if (op_data->ap_id_list == NULL) { 13260Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 13270Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 13280Sstevel@tonic-gate return (-1); 13290Sstevel@tonic-gate } 13300Sstevel@tonic-gate 13310Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 13320Sstevel@tonic-gate 13330Sstevel@tonic-gate /* 13340Sstevel@tonic-gate * Call into libcfgadm 13350Sstevel@tonic-gate */ 13360Sstevel@tonic-gate ses_abort_enable(); 13370Sstevel@tonic-gate 13380Sstevel@tonic-gate cfga_status = config_list_ext(op_data->num_ap_ids, op_data->ap_ids, 13390Sstevel@tonic-gate &ap_ids, op_data->nlist, op_data->options, op_data->listopts, 13400Sstevel@tonic-gate op_data->errstring, op_data->flags); 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate ses_abort_disable(); 13430Sstevel@tonic-gate 13440Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 13450Sstevel@tonic-gate 13460Sstevel@tonic-gate /* 13470Sstevel@tonic-gate * Log any libcfgadm errors at a low priority level. 13480Sstevel@tonic-gate * Since a status request does not modify the system 13490Sstevel@tonic-gate * in any way, we do not need to worry about these 13500Sstevel@tonic-gate * errors here on the host. 13510Sstevel@tonic-gate */ 13520Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 13530Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 13540Sstevel@tonic-gate if (err_str) { 13550Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_CFGA_ERR, op_name, err_str); 13560Sstevel@tonic-gate free((void *)err_str); 13570Sstevel@tonic-gate } 13580Sstevel@tonic-gate } 13590Sstevel@tonic-gate 13600Sstevel@tonic-gate /* 13610Sstevel@tonic-gate * Filter ap ids to return only appropriate information 13620Sstevel@tonic-gate */ 13630Sstevel@tonic-gate filter_list_data(op_data->permissions, op_data->nlist, ap_ids); 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate /* if all aps were filtered out, return an error */ 13660Sstevel@tonic-gate if ((cfga_status == CFGA_OK) && (*op_data->nlist == 0)) { 13670Sstevel@tonic-gate cfga_status = CFGA_APID_NOEXIST; 13680Sstevel@tonic-gate } 13690Sstevel@tonic-gate 13700Sstevel@tonic-gate /* calculate the sort order */ 13710Sstevel@tonic-gate if (cfga_status == CFGA_OK) { 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate *op_data->ap_id_list = generate_sort_order(ap_ids, 13740Sstevel@tonic-gate *op_data->nlist); 13750Sstevel@tonic-gate 13760Sstevel@tonic-gate if (*op_data->ap_id_list == NULL) { 13770Sstevel@tonic-gate cfga_status = CFGA_LIB_ERROR; 13780Sstevel@tonic-gate } 13790Sstevel@tonic-gate } 13800Sstevel@tonic-gate 13810Sstevel@tonic-gate /* ensure that nlist is 0 for errors */ 13820Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 13830Sstevel@tonic-gate *op_data->nlist = 0; 13840Sstevel@tonic-gate } 13850Sstevel@tonic-gate 13860Sstevel@tonic-gate /* prepare header information */ 13870Sstevel@tonic-gate init_msg(&reply_hdr); 13880Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_LIST_EXT; 13890Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 13900Sstevel@tonic-gate reply_hdr.status = cfga_status; 13910Sstevel@tonic-gate 13920Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 13930Sstevel@tonic-gate 13940Sstevel@tonic-gate /* send the message */ 13950Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 13960Sstevel@tonic-gate 13970Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 13980Sstevel@tonic-gate abort_handler(); 13990Sstevel@tonic-gate } 14000Sstevel@tonic-gate 14010Sstevel@tonic-gate if (snd_status != RDR_OK) { 14020Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 14030Sstevel@tonic-gate } 14040Sstevel@tonic-gate 14050Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 14060Sstevel@tonic-gate free((void *)*op_data->errstring); 14070Sstevel@tonic-gate *op_data->errstring = NULL; 14080Sstevel@tonic-gate } 14090Sstevel@tonic-gate 14100Sstevel@tonic-gate if (ap_ids != NULL) { 14110Sstevel@tonic-gate free((void *)ap_ids); 14120Sstevel@tonic-gate } 14130Sstevel@tonic-gate 14140Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 14150Sstevel@tonic-gate } 14160Sstevel@tonic-gate 14170Sstevel@tonic-gate 14180Sstevel@tonic-gate /* 14190Sstevel@tonic-gate * dcs_help: 14200Sstevel@tonic-gate * 14210Sstevel@tonic-gate * Handle a help request message (RDR_CONF_HELP). 14220Sstevel@tonic-gate */ 14230Sstevel@tonic-gate static int 14240Sstevel@tonic-gate dcs_help(rdr_msg_hdr_t *hdr, cfga_params_t *param) 14250Sstevel@tonic-gate { 14260Sstevel@tonic-gate session_t *sp; 14270Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 14280Sstevel@tonic-gate help_params_t *op_data; 14290Sstevel@tonic-gate struct cfga_msg local_msg_cb; 14300Sstevel@tonic-gate int cfga_status; 14310Sstevel@tonic-gate int snd_status; 14320Sstevel@tonic-gate char *err_str; 14330Sstevel@tonic-gate static char *op_name = "config_help"; 14340Sstevel@tonic-gate 14350Sstevel@tonic-gate 14360Sstevel@tonic-gate assert(hdr); 14370Sstevel@tonic-gate assert(param); 14380Sstevel@tonic-gate 14390Sstevel@tonic-gate /* get the current session information */ 14400Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 14410Sstevel@tonic-gate ses_close(DCS_ERROR); 14420Sstevel@tonic-gate return (-1); 14430Sstevel@tonic-gate } 14440Sstevel@tonic-gate 14450Sstevel@tonic-gate op_data = ¶m->help; 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate /* make sure we have a session established */ 14480Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 14490Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 14500Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 14510Sstevel@tonic-gate return (-1); 14520Sstevel@tonic-gate } 14530Sstevel@tonic-gate 14540Sstevel@tonic-gate /* initialize local message callback */ 14550Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 14560Sstevel@tonic-gate local_msg_cb.appdata_ptr = op_data->msgp; 14570Sstevel@tonic-gate 14580Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 14590Sstevel@tonic-gate 14600Sstevel@tonic-gate /* 14610Sstevel@tonic-gate * Call into libcfgadm 14620Sstevel@tonic-gate */ 14630Sstevel@tonic-gate ses_abort_enable(); 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate cfga_status = config_help(op_data->num_ap_ids, op_data->ap_ids, 14660Sstevel@tonic-gate &local_msg_cb, op_data->options, op_data->flags); 14670Sstevel@tonic-gate 14680Sstevel@tonic-gate ses_abort_disable(); 14690Sstevel@tonic-gate 14700Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 14710Sstevel@tonic-gate 14720Sstevel@tonic-gate /* 14730Sstevel@tonic-gate * Log any libcfgadm errors at a low priority level. 14740Sstevel@tonic-gate * Since a help request does not modify the system 14750Sstevel@tonic-gate * in any way, we do not need to worry about these 14760Sstevel@tonic-gate * errors here on the host. 14770Sstevel@tonic-gate */ 14780Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 14790Sstevel@tonic-gate err_str = dcs_cfga_str(NULL, cfga_status); 14800Sstevel@tonic-gate if (err_str) { 14810Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_CFGA_ERR, op_name, err_str); 14820Sstevel@tonic-gate free((void *)err_str); 14830Sstevel@tonic-gate } 14840Sstevel@tonic-gate } 14850Sstevel@tonic-gate 14860Sstevel@tonic-gate /* prepare header information */ 14870Sstevel@tonic-gate init_msg(&reply_hdr); 14880Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_HELP; 14890Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 14900Sstevel@tonic-gate reply_hdr.status = cfga_status; 14910Sstevel@tonic-gate 14920Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 14930Sstevel@tonic-gate 14940Sstevel@tonic-gate /* send the message */ 14950Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 14960Sstevel@tonic-gate 14970Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 14980Sstevel@tonic-gate abort_handler(); 14990Sstevel@tonic-gate } 15000Sstevel@tonic-gate 15010Sstevel@tonic-gate if (snd_status != RDR_OK) { 15020Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 15030Sstevel@tonic-gate } 15040Sstevel@tonic-gate 15050Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 15060Sstevel@tonic-gate } 15070Sstevel@tonic-gate 15080Sstevel@tonic-gate 15090Sstevel@tonic-gate /* 15100Sstevel@tonic-gate * dcs_ap_id_cmp: 15110Sstevel@tonic-gate * 15120Sstevel@tonic-gate * Handle an attachment point comparison request message (RDR_AP_ID_CMP). 15130Sstevel@tonic-gate */ 15140Sstevel@tonic-gate static int 15150Sstevel@tonic-gate dcs_ap_id_cmp(rdr_msg_hdr_t *hdr, cfga_params_t *param) 15160Sstevel@tonic-gate { 15170Sstevel@tonic-gate session_t *sp; 15180Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 15190Sstevel@tonic-gate ap_id_cmp_params_t *op_data; 15200Sstevel@tonic-gate int snd_status; 15210Sstevel@tonic-gate int cmp_result; 15220Sstevel@tonic-gate static char *op_name = "config_ap_id_cmp"; 15230Sstevel@tonic-gate 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate assert(hdr); 15260Sstevel@tonic-gate assert(param); 15270Sstevel@tonic-gate 15280Sstevel@tonic-gate /* get the current session information */ 15290Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 15300Sstevel@tonic-gate ses_close(DCS_ERROR); 15310Sstevel@tonic-gate return (-1); 15320Sstevel@tonic-gate } 15330Sstevel@tonic-gate 15340Sstevel@tonic-gate op_data = ¶m->cmp; 15350Sstevel@tonic-gate 15360Sstevel@tonic-gate /* make sure we have a session established */ 15370Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 15380Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 15390Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 15400Sstevel@tonic-gate return (-1); 15410Sstevel@tonic-gate } 15420Sstevel@tonic-gate 15430Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 15440Sstevel@tonic-gate 15450Sstevel@tonic-gate /* 15460Sstevel@tonic-gate * Call into libcfgadm 15470Sstevel@tonic-gate */ 15480Sstevel@tonic-gate ses_abort_enable(); 15490Sstevel@tonic-gate 15500Sstevel@tonic-gate cmp_result = config_ap_id_cmp(op_data->ap_log_id1, op_data->ap_log_id2); 15510Sstevel@tonic-gate 15520Sstevel@tonic-gate ses_abort_disable(); 15530Sstevel@tonic-gate 15540Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 15550Sstevel@tonic-gate 15560Sstevel@tonic-gate /* prepare header information */ 15570Sstevel@tonic-gate init_msg(&reply_hdr); 15580Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_AP_ID_CMP; 15590Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 15600Sstevel@tonic-gate 15610Sstevel@tonic-gate /* 15620Sstevel@tonic-gate * Return result of comparison as error code. 15630Sstevel@tonic-gate * Since all values are valid, it is impossible 15640Sstevel@tonic-gate * to report an error. 15650Sstevel@tonic-gate */ 15660Sstevel@tonic-gate reply_hdr.status = cmp_result; 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 15690Sstevel@tonic-gate 15700Sstevel@tonic-gate /* send the message */ 15710Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 15720Sstevel@tonic-gate 15730Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 15740Sstevel@tonic-gate abort_handler(); 15750Sstevel@tonic-gate } 15760Sstevel@tonic-gate 15770Sstevel@tonic-gate if (snd_status != RDR_OK) { 15780Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 15790Sstevel@tonic-gate } 15800Sstevel@tonic-gate 15810Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 15820Sstevel@tonic-gate } 15830Sstevel@tonic-gate 15840Sstevel@tonic-gate 15850Sstevel@tonic-gate /* 15860Sstevel@tonic-gate * dcs_abort_cmd: 15870Sstevel@tonic-gate * 15880Sstevel@tonic-gate * Handle an abort request message (RDR_CONF_ABORT_CMD). 15890Sstevel@tonic-gate */ 15900Sstevel@tonic-gate /* ARGSUSED */ 15910Sstevel@tonic-gate static int 15920Sstevel@tonic-gate dcs_abort_cmd(rdr_msg_hdr_t *hdr, cfga_params_t *param) 15930Sstevel@tonic-gate { 15940Sstevel@tonic-gate session_t *sp; 15950Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 15960Sstevel@tonic-gate abort_cmd_params_t *op_data; 15970Sstevel@tonic-gate int op_status = RDR_SUCCESS; 15980Sstevel@tonic-gate int snd_status; 15990Sstevel@tonic-gate static char *op_name = "abort command"; 16000Sstevel@tonic-gate 16010Sstevel@tonic-gate 16020Sstevel@tonic-gate assert(hdr); 16030Sstevel@tonic-gate assert(param); 16040Sstevel@tonic-gate 16050Sstevel@tonic-gate /* get the current session information */ 16060Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 16070Sstevel@tonic-gate ses_close(DCS_ERROR); 16080Sstevel@tonic-gate return (-1); 16090Sstevel@tonic-gate } 16100Sstevel@tonic-gate 16110Sstevel@tonic-gate op_data = (abort_cmd_params_t *)param; 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate op_status = ses_abort(op_data->session_id); 16140Sstevel@tonic-gate 16150Sstevel@tonic-gate if (op_status == -1) { 16160Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_ABORT_ERR, op_data->session_id); 16170Sstevel@tonic-gate } 16180Sstevel@tonic-gate 16190Sstevel@tonic-gate /* prepare header information */ 16200Sstevel@tonic-gate init_msg(&reply_hdr); 16210Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_ABORT_CMD; 16220Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 16230Sstevel@tonic-gate reply_hdr.status = op_status; 16240Sstevel@tonic-gate 16250Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 16260Sstevel@tonic-gate 16270Sstevel@tonic-gate /* send the message */ 16280Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 16290Sstevel@tonic-gate 16300Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 16310Sstevel@tonic-gate abort_handler(); 16320Sstevel@tonic-gate } 16330Sstevel@tonic-gate 16340Sstevel@tonic-gate if (snd_status != RDR_OK) { 16350Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 16360Sstevel@tonic-gate } 16370Sstevel@tonic-gate 16380Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 16390Sstevel@tonic-gate 16400Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 16410Sstevel@tonic-gate } 16420Sstevel@tonic-gate 16430Sstevel@tonic-gate 16440Sstevel@tonic-gate /* 16450Sstevel@tonic-gate * dcs_rsrc_info: 16460Sstevel@tonic-gate * 16470Sstevel@tonic-gate * Handle a resource info request message (RDR_RSRC_INFO). 16480Sstevel@tonic-gate */ 16490Sstevel@tonic-gate static int 16500Sstevel@tonic-gate dcs_rsrc_info(rdr_msg_hdr_t *hdr, cfga_params_t *param) 16510Sstevel@tonic-gate { 16520Sstevel@tonic-gate session_t *sp; 16530Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 16540Sstevel@tonic-gate rsrc_info_params_t *op_data; 16550Sstevel@tonic-gate int rsrc_status; 16560Sstevel@tonic-gate int snd_status; 16570Sstevel@tonic-gate static char *op_name = "resource info init"; 16580Sstevel@tonic-gate 16590Sstevel@tonic-gate assert(hdr); 16600Sstevel@tonic-gate assert(param); 16610Sstevel@tonic-gate 16620Sstevel@tonic-gate /* get the current session information */ 16630Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 16640Sstevel@tonic-gate ses_close(DCS_ERROR); 16650Sstevel@tonic-gate return (-1); 16660Sstevel@tonic-gate } 16670Sstevel@tonic-gate 16680Sstevel@tonic-gate op_data = (rsrc_info_params_t *)¶m->rsrc_info; 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate /* make sure we have a session established */ 16710Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 16720Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 16730Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 16740Sstevel@tonic-gate return (-1); 16750Sstevel@tonic-gate } 16760Sstevel@tonic-gate 16770Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 16780Sstevel@tonic-gate 16790Sstevel@tonic-gate /* 16800Sstevel@tonic-gate * Request resource info data. 16810Sstevel@tonic-gate */ 16820Sstevel@tonic-gate ses_abort_enable(); 16830Sstevel@tonic-gate 16840Sstevel@tonic-gate rsrc_status = ri_init(op_data->num_ap_ids, op_data->ap_ids, 16850Sstevel@tonic-gate op_data->flags, &op_data->hdl); 16860Sstevel@tonic-gate 16870Sstevel@tonic-gate ses_abort_disable(); 16880Sstevel@tonic-gate 16890Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 16900Sstevel@tonic-gate 16910Sstevel@tonic-gate /* log errors */ 16920Sstevel@tonic-gate if (rsrc_status != RI_SUCCESS) { 16930Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_RSRC_ERR, rsrc_status); 16940Sstevel@tonic-gate } 16950Sstevel@tonic-gate 16960Sstevel@tonic-gate /* prepare header information */ 16970Sstevel@tonic-gate init_msg(&reply_hdr); 16980Sstevel@tonic-gate reply_hdr.message_opcode = RDR_RSRC_INFO; 16990Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 17000Sstevel@tonic-gate reply_hdr.status = rsrc_status; 17010Sstevel@tonic-gate 17020Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 17030Sstevel@tonic-gate 17040Sstevel@tonic-gate /* send the message */ 17050Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 17060Sstevel@tonic-gate 17070Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 17080Sstevel@tonic-gate abort_handler(); 17090Sstevel@tonic-gate } 17100Sstevel@tonic-gate 17110Sstevel@tonic-gate if (snd_status != RDR_OK) { 17120Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 17130Sstevel@tonic-gate } 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate ri_fini(op_data->hdl); 17160Sstevel@tonic-gate 17170Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 17180Sstevel@tonic-gate } 17190Sstevel@tonic-gate 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate /* 17220Sstevel@tonic-gate * dcs_unknown_op: 17230Sstevel@tonic-gate * 17240Sstevel@tonic-gate * Handle all unknown requests. 17250Sstevel@tonic-gate */ 17260Sstevel@tonic-gate /* ARGSUSED */ 17270Sstevel@tonic-gate static int 17280Sstevel@tonic-gate dcs_unknown_op(rdr_msg_hdr_t *hdr, cfga_params_t *param) 17290Sstevel@tonic-gate { 17300Sstevel@tonic-gate session_t *sp; 17310Sstevel@tonic-gate 17320Sstevel@tonic-gate 17330Sstevel@tonic-gate assert(hdr); 17340Sstevel@tonic-gate assert(param); 17350Sstevel@tonic-gate 17360Sstevel@tonic-gate assert(hdr); 17370Sstevel@tonic-gate 17380Sstevel@tonic-gate /* get the current session information */ 17390Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 17400Sstevel@tonic-gate ses_close(DCS_ERROR); 17410Sstevel@tonic-gate return (-1); 17420Sstevel@tonic-gate } 17430Sstevel@tonic-gate 17440Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_UNKNOWN_OP, hdr->message_opcode); 17450Sstevel@tonic-gate 17460Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 17470Sstevel@tonic-gate 17480Sstevel@tonic-gate return (-1); 17490Sstevel@tonic-gate } 17500Sstevel@tonic-gate 17510Sstevel@tonic-gate 17520Sstevel@tonic-gate /* 17530Sstevel@tonic-gate * dcs_confirm_callback: 17540Sstevel@tonic-gate * 17550Sstevel@tonic-gate * Perform a confirm callback and wait for the reply. As defined 17560Sstevel@tonic-gate * in the config_admin(3CFGADM) man page, 1 is returned if the 17570Sstevel@tonic-gate * operation should be allowed to continue and 0 otherwise. 17580Sstevel@tonic-gate */ 17590Sstevel@tonic-gate static int 17600Sstevel@tonic-gate dcs_confirm_callback(void *appdata_ptr, const char *message) 17610Sstevel@tonic-gate { 17620Sstevel@tonic-gate session_t *sp; 17630Sstevel@tonic-gate rdr_msg_hdr_t req_hdr; 17640Sstevel@tonic-gate cfga_params_t req_data; 17650Sstevel@tonic-gate struct cfga_confirm *cb_data; 17660Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 17670Sstevel@tonic-gate cfga_params_t reply_data; 17680Sstevel@tonic-gate int snd_status; 17690Sstevel@tonic-gate int rcv_status; 17700Sstevel@tonic-gate static char *op_name = "confirm callback"; 17710Sstevel@tonic-gate 17720Sstevel@tonic-gate 17730Sstevel@tonic-gate /* sanity check */ 17740Sstevel@tonic-gate if (appdata_ptr == NULL) { 17750Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 17760Sstevel@tonic-gate return (0); 17770Sstevel@tonic-gate } 17780Sstevel@tonic-gate 17790Sstevel@tonic-gate /* get the current session information */ 17800Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 17810Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 17820Sstevel@tonic-gate return (0); 17830Sstevel@tonic-gate } 17840Sstevel@tonic-gate 17850Sstevel@tonic-gate cb_data = (struct cfga_confirm *)appdata_ptr; 17860Sstevel@tonic-gate 17870Sstevel@tonic-gate /* prepare header information */ 17880Sstevel@tonic-gate init_msg(&req_hdr); 17890Sstevel@tonic-gate req_hdr.message_opcode = RDR_CONF_CONFIRM_CALLBACK; 17900Sstevel@tonic-gate req_hdr.data_type = RDR_REQUEST; 17910Sstevel@tonic-gate 17920Sstevel@tonic-gate /* prepare confirm callback specific data */ 17930Sstevel@tonic-gate (void) memset(&req_data, 0, sizeof (req_data)); 17940Sstevel@tonic-gate req_data.conf_cb.confp = cb_data; 17950Sstevel@tonic-gate req_data.conf_cb.message = (char *)message; 17960Sstevel@tonic-gate 17970Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &req_hdr); 17980Sstevel@tonic-gate 17990Sstevel@tonic-gate /* send the message */ 18000Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &req_hdr, &req_data, DCS_SND_TIMEOUT); 18010Sstevel@tonic-gate 18020Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 18030Sstevel@tonic-gate abort_handler(); 18040Sstevel@tonic-gate } 18050Sstevel@tonic-gate 18060Sstevel@tonic-gate if (snd_status != RDR_OK) { 18070Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18080Sstevel@tonic-gate return (0); 18090Sstevel@tonic-gate } 18100Sstevel@tonic-gate 18110Sstevel@tonic-gate /* 18120Sstevel@tonic-gate * Wait for response 18130Sstevel@tonic-gate */ 18140Sstevel@tonic-gate rcv_status = rdr_rcv_msg(sp->fd, &reply_hdr, &reply_data, 18150Sstevel@tonic-gate DCS_RCV_CB_TIMEOUT); 18160Sstevel@tonic-gate 18170Sstevel@tonic-gate if (rcv_status != RDR_OK) { 18180Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 18190Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18200Sstevel@tonic-gate return (0); 18210Sstevel@tonic-gate } 18220Sstevel@tonic-gate 18230Sstevel@tonic-gate /* 18240Sstevel@tonic-gate * Perform several checks to see if we have a 18250Sstevel@tonic-gate * valid response to the confirm callback. 18260Sstevel@tonic-gate */ 18270Sstevel@tonic-gate if (invalid_msg(&reply_hdr)) { 18280Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 18290Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18300Sstevel@tonic-gate return (0); 18310Sstevel@tonic-gate } 18320Sstevel@tonic-gate 18330Sstevel@tonic-gate /* check the opcode and type */ 18340Sstevel@tonic-gate if ((reply_hdr.message_opcode != RDR_CONF_CONFIRM_CALLBACK) || 18350Sstevel@tonic-gate (reply_hdr.data_type != RDR_REPLY)) { 18360Sstevel@tonic-gate DCS_DBG(DBG_MSG, "bad opcode or message type"); 18370Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 18380Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18390Sstevel@tonic-gate return (0); 18400Sstevel@tonic-gate } 18410Sstevel@tonic-gate 18420Sstevel@tonic-gate PRINT_MSG_DBG(DCS_RECEIVE, &reply_hdr); 18430Sstevel@tonic-gate 18440Sstevel@tonic-gate /* check for incorrect callback id */ 18450Sstevel@tonic-gate if (reply_data.conf_cb.confp->confirm != cb_data->confirm) { 18460Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 18470Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18480Sstevel@tonic-gate return (0); 18490Sstevel@tonic-gate } 18500Sstevel@tonic-gate 18510Sstevel@tonic-gate /* 18520Sstevel@tonic-gate * Got back valid response: return the user's answer 18530Sstevel@tonic-gate */ 18540Sstevel@tonic-gate return (reply_data.conf_cb.response); 18550Sstevel@tonic-gate } 18560Sstevel@tonic-gate 18570Sstevel@tonic-gate 18580Sstevel@tonic-gate /* 18590Sstevel@tonic-gate * dcs_message_callback: 18600Sstevel@tonic-gate * 18610Sstevel@tonic-gate * Perform a message callback to display a string to the user. 18620Sstevel@tonic-gate * 18630Sstevel@tonic-gate * Note: There is no documentation about possible return values 18640Sstevel@tonic-gate * for the message callback. It is assumed that the value returned 18650Sstevel@tonic-gate * is ignored, so 0 is returned for all cases. 18660Sstevel@tonic-gate */ 18670Sstevel@tonic-gate static int 18680Sstevel@tonic-gate dcs_message_callback(void *appdata_ptr, const char *message) 18690Sstevel@tonic-gate { 18700Sstevel@tonic-gate session_t *sp; 18710Sstevel@tonic-gate rdr_msg_hdr_t req_hdr; 18720Sstevel@tonic-gate cfga_params_t req_data; 18730Sstevel@tonic-gate struct cfga_msg *cb_data; 18740Sstevel@tonic-gate int snd_status; 18750Sstevel@tonic-gate static char *op_name = "message callback"; 18760Sstevel@tonic-gate 18770Sstevel@tonic-gate 18780Sstevel@tonic-gate /* sanity check */ 18790Sstevel@tonic-gate if (appdata_ptr == NULL) { 18800Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 18810Sstevel@tonic-gate return (0); 18820Sstevel@tonic-gate } 18830Sstevel@tonic-gate 18840Sstevel@tonic-gate /* get the current session information */ 18850Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 18860Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 18870Sstevel@tonic-gate return (0); 18880Sstevel@tonic-gate } 18890Sstevel@tonic-gate 18900Sstevel@tonic-gate cb_data = (struct cfga_msg *)appdata_ptr; 18910Sstevel@tonic-gate 18920Sstevel@tonic-gate /* prepare header information */ 18930Sstevel@tonic-gate init_msg(&req_hdr); 18940Sstevel@tonic-gate req_hdr.message_opcode = RDR_CONF_MSG_CALLBACK; 18950Sstevel@tonic-gate req_hdr.data_type = RDR_REQUEST; 18960Sstevel@tonic-gate 18970Sstevel@tonic-gate /* prepare message callback specific data */ 18980Sstevel@tonic-gate (void) memset(&req_data, 0, sizeof (req_data)); 18990Sstevel@tonic-gate req_data.msg_cb.msgp = cb_data; 19000Sstevel@tonic-gate req_data.msg_cb.message = (char *)message; 19010Sstevel@tonic-gate 19020Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &req_hdr); 19030Sstevel@tonic-gate 19040Sstevel@tonic-gate /* send the message */ 19050Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &req_hdr, (cfga_params_t *)&req_data, 19060Sstevel@tonic-gate DCS_SND_TIMEOUT); 19070Sstevel@tonic-gate 19080Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 19090Sstevel@tonic-gate abort_handler(); 19100Sstevel@tonic-gate } 19110Sstevel@tonic-gate 19120Sstevel@tonic-gate if (snd_status != RDR_OK) { 19130Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 19140Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 19150Sstevel@tonic-gate } 19160Sstevel@tonic-gate 19170Sstevel@tonic-gate return (0); 19180Sstevel@tonic-gate } 19190Sstevel@tonic-gate 19200Sstevel@tonic-gate 19210Sstevel@tonic-gate /* 19220Sstevel@tonic-gate * resolve_version: 19230Sstevel@tonic-gate * 19240Sstevel@tonic-gate * Consult the list of supported versions and find the highest supported 19250Sstevel@tonic-gate * version that is less than or equal to the version requested in the 19260Sstevel@tonic-gate * parameters. This assumes that the list of supported versions is ordered 19270Sstevel@tonic-gate * so that the highest supported version is the first element, and that 19280Sstevel@tonic-gate * the versions are strictly decreasing. 19290Sstevel@tonic-gate */ 19300Sstevel@tonic-gate static dcs_ver_t 19310Sstevel@tonic-gate resolve_version(ushort_t req_major, ushort_t req_minor) 19320Sstevel@tonic-gate { 19330Sstevel@tonic-gate int i; 19340Sstevel@tonic-gate dcs_ver_t act_ver; 19350Sstevel@tonic-gate int num_vers; 19360Sstevel@tonic-gate 19370Sstevel@tonic-gate 19380Sstevel@tonic-gate num_vers = sizeof (ver_supp) / sizeof (*ver_supp); 19390Sstevel@tonic-gate 19400Sstevel@tonic-gate /* default to the lowest version */ 19410Sstevel@tonic-gate act_ver = ver_supp[num_vers - 1]; 19420Sstevel@tonic-gate 19430Sstevel@tonic-gate for (i = 0; i < num_vers; i++) { 19440Sstevel@tonic-gate 19450Sstevel@tonic-gate if (req_major == ver_supp[i].major) { 19460Sstevel@tonic-gate 19470Sstevel@tonic-gate if (req_minor >= ver_supp[i].minor) { 19480Sstevel@tonic-gate /* 19490Sstevel@tonic-gate * The major version matches and the 19500Sstevel@tonic-gate * minor version either matches, or 19510Sstevel@tonic-gate * is the best match that we have. 19520Sstevel@tonic-gate */ 19530Sstevel@tonic-gate act_ver = ver_supp[i]; 19540Sstevel@tonic-gate break; 19550Sstevel@tonic-gate } 19560Sstevel@tonic-gate 19570Sstevel@tonic-gate } else if (req_major > ver_supp[i].major) { 19580Sstevel@tonic-gate /* 19590Sstevel@tonic-gate * The requested major version is larger than 19600Sstevel@tonic-gate * the current version we are checking. There 19610Sstevel@tonic-gate * is not going to be a better match. 19620Sstevel@tonic-gate */ 19630Sstevel@tonic-gate act_ver = ver_supp[i]; 19640Sstevel@tonic-gate break; 19650Sstevel@tonic-gate } 19660Sstevel@tonic-gate } 19670Sstevel@tonic-gate 19680Sstevel@tonic-gate DCS_DBG(DBG_SES, "requested ver: %d.%d, closest match: %d.%d", 19690Sstevel@tonic-gate req_major, req_minor, act_ver.major, act_ver.minor); 19700Sstevel@tonic-gate 19710Sstevel@tonic-gate return (act_ver); 19720Sstevel@tonic-gate } 19730Sstevel@tonic-gate 19740Sstevel@tonic-gate 19750Sstevel@tonic-gate /* 19760Sstevel@tonic-gate * filter_list_data: 19770Sstevel@tonic-gate * 19780Sstevel@tonic-gate * Check a list of cfga_list_data_t structures to filter out the ones 19790Sstevel@tonic-gate * that don't have other-read permissions. All valid entries are placed 19800Sstevel@tonic-gate * at the beginning of the array and the count of entries is updated. 19810Sstevel@tonic-gate */ 19820Sstevel@tonic-gate static void 19830Sstevel@tonic-gate filter_list_data(int perm, int *nlistp, cfga_list_data_t *linfo) 19840Sstevel@tonic-gate { 19850Sstevel@tonic-gate int num_aps; 19860Sstevel@tonic-gate int num_aps_ret; 19870Sstevel@tonic-gate int curr_ap; 19880Sstevel@tonic-gate int next_aval; 19890Sstevel@tonic-gate int end_block; 19900Sstevel@tonic-gate int block_size; 19910Sstevel@tonic-gate struct stat ap_info; 19920Sstevel@tonic-gate 19930Sstevel@tonic-gate 19940Sstevel@tonic-gate DCS_DBG(DBG_MSG, "list access = %s", (perm == RDR_PRIVILEGED) ? 19950Sstevel@tonic-gate "RDR_PRIVILEGED" : "RDR_NOT_PRIVILEGED"); 19960Sstevel@tonic-gate 19970Sstevel@tonic-gate /* 19980Sstevel@tonic-gate * Check if the user has priviledged access 19990Sstevel@tonic-gate * to view all attachment points 20000Sstevel@tonic-gate */ 20010Sstevel@tonic-gate if (perm == RDR_PRIVILEGED) { 20020Sstevel@tonic-gate return; 20030Sstevel@tonic-gate } 20040Sstevel@tonic-gate 20050Sstevel@tonic-gate if (*nlistp < 0) { 20060Sstevel@tonic-gate *nlistp = 0; 20070Sstevel@tonic-gate } 20080Sstevel@tonic-gate 20090Sstevel@tonic-gate /* 20100Sstevel@tonic-gate * No priviledged access, check each attachment point to 20110Sstevel@tonic-gate * see if the user has access (other:read) to view it. 20120Sstevel@tonic-gate */ 20130Sstevel@tonic-gate num_aps = *nlistp; 20140Sstevel@tonic-gate next_aval = 0; 20150Sstevel@tonic-gate num_aps_ret = 0; 20160Sstevel@tonic-gate curr_ap = 0; 20170Sstevel@tonic-gate 20180Sstevel@tonic-gate /* 20190Sstevel@tonic-gate * Use a simple algorithm to compact the array so that 20200Sstevel@tonic-gate * all attachment points that can be viewed are at the 20210Sstevel@tonic-gate * beginning of the array. Adjust the count of the 20220Sstevel@tonic-gate * attachment points accordingly. 20230Sstevel@tonic-gate */ 20240Sstevel@tonic-gate while (curr_ap < num_aps) { 20250Sstevel@tonic-gate 20260Sstevel@tonic-gate stat(linfo[curr_ap].ap_phys_id, &ap_info); 20270Sstevel@tonic-gate 20280Sstevel@tonic-gate /* check for unrestricted read permission */ 20290Sstevel@tonic-gate if (ap_info.st_mode & S_IROTH) { 20300Sstevel@tonic-gate 20310Sstevel@tonic-gate end_block = curr_ap + 1; 20320Sstevel@tonic-gate 20330Sstevel@tonic-gate /* 20340Sstevel@tonic-gate * Check if this is the beginning of a 20350Sstevel@tonic-gate * block of consecutive ap ids that can 20360Sstevel@tonic-gate * be returned. 20370Sstevel@tonic-gate */ 20380Sstevel@tonic-gate while (end_block < num_aps) { 20390Sstevel@tonic-gate 20400Sstevel@tonic-gate stat(linfo[end_block].ap_phys_id, &ap_info); 20410Sstevel@tonic-gate 20420Sstevel@tonic-gate /* search until the end of the block */ 20430Sstevel@tonic-gate if (ap_info.st_mode & S_IROTH) { 20440Sstevel@tonic-gate end_block++; 20450Sstevel@tonic-gate } else { 20460Sstevel@tonic-gate break; 20470Sstevel@tonic-gate } 20480Sstevel@tonic-gate } 20490Sstevel@tonic-gate 20500Sstevel@tonic-gate block_size = end_block - curr_ap; 20510Sstevel@tonic-gate 20520Sstevel@tonic-gate /* make sure a copy is necessary */ 20530Sstevel@tonic-gate if (curr_ap != next_aval) { 20540Sstevel@tonic-gate 20550Sstevel@tonic-gate /* copy the block of ap ids all at once */ 20560Sstevel@tonic-gate (void) memmove(&linfo[next_aval], 20570Sstevel@tonic-gate &linfo[curr_ap], 20580Sstevel@tonic-gate block_size * sizeof (cfga_list_data_t)); 20590Sstevel@tonic-gate } 20600Sstevel@tonic-gate 20610Sstevel@tonic-gate /* move past the copied block */ 20620Sstevel@tonic-gate next_aval += block_size; 20630Sstevel@tonic-gate curr_ap = end_block; 20640Sstevel@tonic-gate 20650Sstevel@tonic-gate num_aps_ret += block_size; 20660Sstevel@tonic-gate } else { 20670Sstevel@tonic-gate curr_ap++; 20680Sstevel@tonic-gate } 20690Sstevel@tonic-gate } 20700Sstevel@tonic-gate 20710Sstevel@tonic-gate DCS_DBG(DBG_ALL, "filtered %d of %d ap ids", (*nlistp - num_aps_ret), 20720Sstevel@tonic-gate *nlistp); 20730Sstevel@tonic-gate 20740Sstevel@tonic-gate /* 20750Sstevel@tonic-gate * return the number of aps that have the correct 20760Sstevel@tonic-gate * access permissions. 20770Sstevel@tonic-gate */ 20780Sstevel@tonic-gate *nlistp = num_aps_ret; 20790Sstevel@tonic-gate } 20800Sstevel@tonic-gate 20810Sstevel@tonic-gate 20820Sstevel@tonic-gate /* 20830Sstevel@tonic-gate * generate_sort_order: 20840Sstevel@tonic-gate * 20850Sstevel@tonic-gate * Determine the sort order of an array of cfga_list_data_t structures 20860Sstevel@tonic-gate * and create an array of rdr_list_t structures that contain the original 20870Sstevel@tonic-gate * elements tagged with the sort order. 20880Sstevel@tonic-gate * 20890Sstevel@tonic-gate * This function is used to eliminate unnecessary network traffic that 20900Sstevel@tonic-gate * might occur if the client needs the output of config_list_ext(3CFGADM) 20910Sstevel@tonic-gate * sorted. Since a comparison is performed in a platform specific manner 20920Sstevel@tonic-gate * using config_ap_id_cmp(3CFGADM), a client must establish a new session 20930Sstevel@tonic-gate * for each comparison. For a long lists of attachment points, this can 20940Sstevel@tonic-gate * slow down a simple list_ext operation significantly. With the sort 20950Sstevel@tonic-gate * information included in the array of rdr_list_t structures, the client 20960Sstevel@tonic-gate * can perform the sort operation locally, thus eliminating a great deal 20970Sstevel@tonic-gate * of network traffic. 20980Sstevel@tonic-gate */ 20990Sstevel@tonic-gate static rdr_list_t * 21000Sstevel@tonic-gate generate_sort_order(cfga_list_data_t *listp, int nlist) 21010Sstevel@tonic-gate { 21020Sstevel@tonic-gate int curr_ap; 21030Sstevel@tonic-gate rdr_list_t *datalp; 21040Sstevel@tonic-gate cfga_list_data_t *sortlp; 21050Sstevel@tonic-gate cfga_list_data_t *match; 21060Sstevel@tonic-gate 21070Sstevel@tonic-gate 21080Sstevel@tonic-gate assert(listp); 21090Sstevel@tonic-gate 21100Sstevel@tonic-gate if (nlist <= 0) { 21110Sstevel@tonic-gate return (NULL); 21120Sstevel@tonic-gate } 21130Sstevel@tonic-gate 21140Sstevel@tonic-gate /* create our new array */ 21150Sstevel@tonic-gate datalp = (rdr_list_t *)malloc(nlist * sizeof (rdr_list_t)); 21160Sstevel@tonic-gate 21170Sstevel@tonic-gate if (datalp == NULL) { 21180Sstevel@tonic-gate return (NULL); 21190Sstevel@tonic-gate } 21200Sstevel@tonic-gate 21210Sstevel@tonic-gate 21220Sstevel@tonic-gate /* copy over the elements, preserving the original order */ 21230Sstevel@tonic-gate for (curr_ap = 0; curr_ap < nlist; curr_ap++) { 21240Sstevel@tonic-gate datalp[curr_ap].ap_id_info = listp[curr_ap]; 21250Sstevel@tonic-gate } 21260Sstevel@tonic-gate 21270Sstevel@tonic-gate /* handle a one element list */ 21280Sstevel@tonic-gate if (nlist == 1) { 21290Sstevel@tonic-gate datalp[0].sort_order = 0; 21300Sstevel@tonic-gate return (datalp); 21310Sstevel@tonic-gate } 21320Sstevel@tonic-gate 21330Sstevel@tonic-gate /* sort the cfga_list_data_t array */ 21340Sstevel@tonic-gate qsort(listp, nlist, sizeof (listp[0]), ldata_compare); 21350Sstevel@tonic-gate 21360Sstevel@tonic-gate sortlp = listp; 21370Sstevel@tonic-gate 21380Sstevel@tonic-gate /* process each item in the original list */ 21390Sstevel@tonic-gate for (curr_ap = 0; curr_ap < nlist; curr_ap++) { 21400Sstevel@tonic-gate 21410Sstevel@tonic-gate /* look up the sort order in the sorted list */ 21420Sstevel@tonic-gate match = bsearch(&datalp[curr_ap].ap_id_info, sortlp, 21430Sstevel@tonic-gate nlist, sizeof (cfga_list_data_t), ldata_compare); 21440Sstevel@tonic-gate 21450Sstevel@tonic-gate /* found a match */ 21460Sstevel@tonic-gate if (match != NULL) { 21470Sstevel@tonic-gate datalp[curr_ap].sort_order = match - sortlp; 21480Sstevel@tonic-gate } else { 21490Sstevel@tonic-gate /* 21500Sstevel@tonic-gate * Should never get here. Since we did a 21510Sstevel@tonic-gate * direct copy of the array, we should always 21520Sstevel@tonic-gate * be able to find the ap id that we were 21530Sstevel@tonic-gate * looking for. 21540Sstevel@tonic-gate */ 21550Sstevel@tonic-gate DCS_DBG(DBG_ALL, "could not find a matching " 21560Sstevel@tonic-gate "ap id in the sorted list"); 21570Sstevel@tonic-gate datalp[curr_ap].sort_order = 0; 21580Sstevel@tonic-gate } 21590Sstevel@tonic-gate } 21600Sstevel@tonic-gate 21610Sstevel@tonic-gate return (datalp); 21620Sstevel@tonic-gate } 21630Sstevel@tonic-gate 21640Sstevel@tonic-gate 21650Sstevel@tonic-gate /* 21660Sstevel@tonic-gate * ldata_compare: 21670Sstevel@tonic-gate * 21680Sstevel@tonic-gate * Compare the two inputs to produce a strcmp(3C) style result. It uses 21690Sstevel@tonic-gate * config_ap_id_cmp(3CFGADM) to perform the comparison. 21700Sstevel@tonic-gate * 21710Sstevel@tonic-gate * This function is passed to qsort(3C) in generate_sort_order() to sort a 21720Sstevel@tonic-gate * list of attachment points. 21730Sstevel@tonic-gate */ 21740Sstevel@tonic-gate static int 21750Sstevel@tonic-gate ldata_compare(const void *ap1, const void *ap2) 21760Sstevel@tonic-gate { 21770Sstevel@tonic-gate cfga_list_data_t *ap_id1; 21780Sstevel@tonic-gate cfga_list_data_t *ap_id2; 21790Sstevel@tonic-gate 21800Sstevel@tonic-gate ap_id1 = (cfga_list_data_t *)ap1; 21810Sstevel@tonic-gate ap_id2 = (cfga_list_data_t *)ap2; 21820Sstevel@tonic-gate 21830Sstevel@tonic-gate return (config_ap_id_cmp(ap_id1->ap_log_id, ap_id2->ap_log_id)); 21840Sstevel@tonic-gate } 21850Sstevel@tonic-gate 21860Sstevel@tonic-gate 21870Sstevel@tonic-gate /* 21880Sstevel@tonic-gate * basename: 21890Sstevel@tonic-gate * 21900Sstevel@tonic-gate * Find short path name of a full path name. If a short path name 21910Sstevel@tonic-gate * is passed in, the original pointer is returned. 21920Sstevel@tonic-gate */ 21930Sstevel@tonic-gate static char * 21940Sstevel@tonic-gate basename(char *cp) 21950Sstevel@tonic-gate { 21960Sstevel@tonic-gate char *sp; 21970Sstevel@tonic-gate 21980Sstevel@tonic-gate if ((sp = strrchr(cp, '/')) != NULL) { 21990Sstevel@tonic-gate return (sp + 1); 22000Sstevel@tonic-gate } 22010Sstevel@tonic-gate 22020Sstevel@tonic-gate return (cp); 22030Sstevel@tonic-gate } 22041120Smb158278 22051120Smb158278 /* 22061120Smb158278 * is_socket: 22071120Smb158278 * 22081120Smb158278 * determine if fd represents a socket file type. 22091120Smb158278 */ 22101120Smb158278 static boolean_t 22111120Smb158278 is_socket(int fd) 22121120Smb158278 { 22131120Smb158278 struct stat statb; 22141120Smb158278 if (fstat(fd, &statb) < 0) { 22151120Smb158278 return (B_FALSE); 22161120Smb158278 } 22171120Smb158278 return (S_ISSOCK(statb.st_mode)); 22181120Smb158278 } 2219*1518Smb158278 2220*1518Smb158278 /* 2221*1518Smb158278 * has_dcs_token 2222*1518Smb158278 * 2223*1518Smb158278 * Look for "?port [sun-dr|665]" in input buf. 2224*1518Smb158278 * Assume only a single thread calls here. 2225*1518Smb158278 */ 2226*1518Smb158278 static boolean_t 2227*1518Smb158278 has_dcs_token(char *buf) 2228*1518Smb158278 { 2229*1518Smb158278 char *token; 2230*1518Smb158278 char *delims = "{} \t\n"; 2231*1518Smb158278 boolean_t port = B_FALSE; 2232*1518Smb158278 2233*1518Smb158278 while ((token = strtok(buf, delims)) != NULL) { 2234*1518Smb158278 buf = NULL; 2235*1518Smb158278 if (port == B_TRUE) { 2236*1518Smb158278 if (strcmp(token, "sun-dr") == 0 || 2237*1518Smb158278 strcmp(token, "665") == 0) { 2238*1518Smb158278 return (B_TRUE); 2239*1518Smb158278 } else { 2240*1518Smb158278 return (B_FALSE); 2241*1518Smb158278 } 2242*1518Smb158278 } 2243*1518Smb158278 if (strlen(token) == 5) { 2244*1518Smb158278 token++; 2245*1518Smb158278 if (strcmp(token, "port") == 0) { 2246*1518Smb158278 port = B_TRUE; 2247*1518Smb158278 continue; 2248*1518Smb158278 } 2249*1518Smb158278 } 2250*1518Smb158278 } 2251*1518Smb158278 return (B_FALSE); 2252*1518Smb158278 } 2253*1518Smb158278 2254*1518Smb158278 /* 2255*1518Smb158278 * dcs_global_policy 2256*1518Smb158278 * 2257*1518Smb158278 * Check global policy file for dcs entry. Just covers common cases. 2258*1518Smb158278 */ 2259*1518Smb158278 static boolean_t 2260*1518Smb158278 dcs_global_policy() 2261*1518Smb158278 { 2262*1518Smb158278 FILE *fp; 2263*1518Smb158278 char buf[256]; 2264*1518Smb158278 boolean_t rv = B_FALSE; 2265*1518Smb158278 2266*1518Smb158278 fp = fopen("/etc/inet/ipsecinit.conf", "r"); 2267*1518Smb158278 if (fp == NULL) 2268*1518Smb158278 return (B_FALSE); 2269*1518Smb158278 while (fgets(buf, sizeof (buf), fp) != NULL) { 2270*1518Smb158278 if (buf[0] == '#') 2271*1518Smb158278 continue; 2272*1518Smb158278 if (has_dcs_token(buf)) { 2273*1518Smb158278 rv = B_TRUE; 2274*1518Smb158278 syslog(LOG_NOTICE, "dcs using global policy"); 2275*1518Smb158278 break; 2276*1518Smb158278 } 2277*1518Smb158278 } 2278*1518Smb158278 (void) fclose(fp); 2279*1518Smb158278 return (rv); 2280*1518Smb158278 } 2281