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