17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53a3e8d7aSmb158278 * Common Development and Distribution License (the "License"). 63a3e8d7aSmb158278 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 223a3e8d7aSmb158278 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 232eaee53eSmb158278 * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * This is the main file for the Domain Configuration Server (DCS). 307c478bd9Sstevel@tonic-gate * 317c478bd9Sstevel@tonic-gate * The DCS is a server that runs on a domain and communicates with 327c478bd9Sstevel@tonic-gate * a Domain Configuration Agent (DCA) running on a remote host. The 337c478bd9Sstevel@tonic-gate * DCA initiates DR requests that the DCS performs by calling the 347c478bd9Sstevel@tonic-gate * appropriate libcfgadm(3LIB) function. 357c478bd9Sstevel@tonic-gate * 367c478bd9Sstevel@tonic-gate * This file contains functions that receive and process the messages 377c478bd9Sstevel@tonic-gate * received from the DCA. It also handles the initialization of the 387c478bd9Sstevel@tonic-gate * server and is responsible for starting a concurrent session to 397c478bd9Sstevel@tonic-gate * handle each DR request. 407c478bd9Sstevel@tonic-gate */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include <stdlib.h> 437c478bd9Sstevel@tonic-gate #include <stdio.h> 447c478bd9Sstevel@tonic-gate #include <unistd.h> 457c478bd9Sstevel@tonic-gate #include <string.h> 467c478bd9Sstevel@tonic-gate #include <fcntl.h> 477c478bd9Sstevel@tonic-gate #include <errno.h> 487c478bd9Sstevel@tonic-gate #include <syslog.h> 497c478bd9Sstevel@tonic-gate #include <assert.h> 507c478bd9Sstevel@tonic-gate #include <signal.h> 517c478bd9Sstevel@tonic-gate #include <netdb.h> 527c478bd9Sstevel@tonic-gate #include <config_admin.h> 537c478bd9Sstevel@tonic-gate #include <sys/param.h> 547c478bd9Sstevel@tonic-gate #include <sys/time.h> 557c478bd9Sstevel@tonic-gate #include <sys/stat.h> 567c478bd9Sstevel@tonic-gate #include <sys/socket.h> 572eaee53eSmb158278 #include <strings.h> 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #include "dcs.h" 607c478bd9Sstevel@tonic-gate #include "remote_cfg.h" 617c478bd9Sstevel@tonic-gate #include "rdr_param_types.h" 627c478bd9Sstevel@tonic-gate #include "rdr_messages.h" 637c478bd9Sstevel@tonic-gate #include "rsrc_info.h" 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate typedef struct { 677c478bd9Sstevel@tonic-gate ushort_t major; 687c478bd9Sstevel@tonic-gate ushort_t minor; 697c478bd9Sstevel@tonic-gate } dcs_ver_t; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate /* initialization functions */ 732eaee53eSmb158278 static int init_server(struct pollfd *pfd, uint8_t ah_auth_alg, 742eaee53eSmb158278 uint8_t esp_encr_alg, uint8_t esp_auth_alg); 757c478bd9Sstevel@tonic-gate static void init_signals(void); 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* message processing functions */ 787c478bd9Sstevel@tonic-gate static int invalid_msg(rdr_msg_hdr_t *hdr); 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* message handling functions */ 817c478bd9Sstevel@tonic-gate static int dcs_ses_req(rdr_msg_hdr_t *hdr, cfga_params_t *param); 827c478bd9Sstevel@tonic-gate static int dcs_ses_estbl(rdr_msg_hdr_t *hdr, cfga_params_t *param); 837c478bd9Sstevel@tonic-gate static int dcs_ses_end(rdr_msg_hdr_t *hdr, cfga_params_t *param); 847c478bd9Sstevel@tonic-gate static int dcs_change_state(rdr_msg_hdr_t *hdr, cfga_params_t *param); 857c478bd9Sstevel@tonic-gate static int dcs_private_func(rdr_msg_hdr_t *hdr, cfga_params_t *param); 867c478bd9Sstevel@tonic-gate static int dcs_test(rdr_msg_hdr_t *hdr, cfga_params_t *param); 877c478bd9Sstevel@tonic-gate static int dcs_list_ext(rdr_msg_hdr_t *hdr, cfga_params_t *param); 887c478bd9Sstevel@tonic-gate static int dcs_help(rdr_msg_hdr_t *hdr, cfga_params_t *param); 897c478bd9Sstevel@tonic-gate static int dcs_ap_id_cmp(rdr_msg_hdr_t *hdr, cfga_params_t *param); 907c478bd9Sstevel@tonic-gate static int dcs_abort_cmd(rdr_msg_hdr_t *hdr, cfga_params_t *param); 917c478bd9Sstevel@tonic-gate static int dcs_rsrc_info(rdr_msg_hdr_t *hdr, cfga_params_t *param); 927c478bd9Sstevel@tonic-gate static int dcs_unknown_op(rdr_msg_hdr_t *hdr, cfga_params_t *param); 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* local callback functions */ 957c478bd9Sstevel@tonic-gate static int dcs_confirm_callback(void *appdata_ptr, const char *message); 967c478bd9Sstevel@tonic-gate static int dcs_message_callback(void *appdata_ptr, const char *message); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* utility functions */ 997c478bd9Sstevel@tonic-gate static dcs_ver_t resolve_version(ushort_t req_major, ushort_t req_minor); 1007c478bd9Sstevel@tonic-gate static void filter_list_data(int perm, int *nlistp, cfga_list_data_t *linfo); 1017c478bd9Sstevel@tonic-gate static rdr_list_t *generate_sort_order(cfga_list_data_t *listp, int nlist); 1027c478bd9Sstevel@tonic-gate static int ldata_compare(const void *ap1, const void *ap2); 1037c478bd9Sstevel@tonic-gate static int invalid_msg(rdr_msg_hdr_t *hdr); 1047c478bd9Sstevel@tonic-gate static char *basename(char *path); 1052eaee53eSmb158278 static boolean_t is_socket(int fd); 1062eaee53eSmb158278 static uint8_t dcs_get_alg(dcs_alg_t *algs, char *arg, dcs_err_code *error); 1072eaee53eSmb158278 static void dcs_log_bad_alg(char optopt, char *optarg); 1083a3e8d7aSmb158278 static boolean_t dcs_global_policy(void); 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * Lookup table for handling different message types. This 1137c478bd9Sstevel@tonic-gate * assumes the ordering of rdr_msg_opcode_t in remote_cfg.h. 1147c478bd9Sstevel@tonic-gate * If this enum changes, the lookup table must be updated. 1157c478bd9Sstevel@tonic-gate * 1167c478bd9Sstevel@tonic-gate * The lookup table handles all _known_ opcodes >= 0. Unsupported 1177c478bd9Sstevel@tonic-gate * opcodes, or opcodes that should not be received by the 1187c478bd9Sstevel@tonic-gate * dispatcher are handled by the dcs_unknown_op() function. 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate int (*dcs_cmd[])(rdr_msg_hdr_t *, cfga_params_t *) = { 1217c478bd9Sstevel@tonic-gate dcs_unknown_op, /* 0 is an invalid opcode */ 1227c478bd9Sstevel@tonic-gate dcs_ses_req, /* RDR_SES_REQ */ 1237c478bd9Sstevel@tonic-gate dcs_ses_estbl, /* RDR_SES_ESTBL */ 1247c478bd9Sstevel@tonic-gate dcs_ses_end, /* RDR_SES_END */ 1257c478bd9Sstevel@tonic-gate dcs_change_state, /* RDR_CONF_CHANGE_STATE */ 1267c478bd9Sstevel@tonic-gate dcs_private_func, /* RDR_CONF_PRIVATE_FUNC */ 1277c478bd9Sstevel@tonic-gate dcs_test, /* RDR_CONF_TEST */ 1287c478bd9Sstevel@tonic-gate dcs_list_ext, /* RDR_CONF_LIST_EXT */ 1297c478bd9Sstevel@tonic-gate dcs_help, /* RDR_CONF_HELP */ 1307c478bd9Sstevel@tonic-gate dcs_ap_id_cmp, /* RDR_CONF_AP_ID_CMP */ 1317c478bd9Sstevel@tonic-gate dcs_abort_cmd, /* RDR_CONF_ABORT_CMD */ 1327c478bd9Sstevel@tonic-gate dcs_unknown_op, /* RDR_CONF_CONFIRM_CALLBACK */ 1337c478bd9Sstevel@tonic-gate dcs_unknown_op, /* RDR_CONF_MSG_CALLBACK */ 1347c478bd9Sstevel@tonic-gate dcs_rsrc_info /* RDR_RSRC_INFO */ 1357c478bd9Sstevel@tonic-gate }; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * ver_supp[] is an array of the supported versions for the network 1407c478bd9Sstevel@tonic-gate * transport protocol used by the DCA and DCS. Each item in the array 1417c478bd9Sstevel@tonic-gate * is a pair: { major_version, minor_version }. 1427c478bd9Sstevel@tonic-gate * 1437c478bd9Sstevel@tonic-gate * The order of the array is significant. The first element should be 1447c478bd9Sstevel@tonic-gate * the highest supported version and all successive elements should be 1457c478bd9Sstevel@tonic-gate * strictly decreasing. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate dcs_ver_t ver_supp[] = { 14825cf1a30Sjl139090 { 1, 1 }, 1497c478bd9Sstevel@tonic-gate { 1, 0 } 1507c478bd9Sstevel@tonic-gate }; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate #define DCS_CURR_VER ver_supp[0] 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* 1567c478bd9Sstevel@tonic-gate * Global Data 1577c478bd9Sstevel@tonic-gate */ 1587c478bd9Sstevel@tonic-gate char *cmdname = NULL; /* the name of the executable */ 1597c478bd9Sstevel@tonic-gate ulong_t dcs_debug = 0; /* control the amount of debugging */ 1607c478bd9Sstevel@tonic-gate int standalone = 0; /* control standalone mode */ 1612eaee53eSmb158278 boolean_t inetd = B_FALSE; /* control daemon mode */ 1627c478bd9Sstevel@tonic-gate ulong_t max_sessions = DCS_MAX_SESSIONS; /* control maximum active sessions */ 1637c478bd9Sstevel@tonic-gate int dcsfd = STDIN_FILENO; /* fd for the DCS reserved port */ 16425cf1a30Sjl139090 int use_libdscp = 0; /* control use of libdscp */ 16525cf1a30Sjl139090 sa_family_t use_family = AF_INET6; /* control use of AF_INET/AF_INET6 */ 1667c478bd9Sstevel@tonic-gate 1672eaee53eSmb158278 /* 1682eaee53eSmb158278 * Array of acceptable -a, -e and -u arguments. 1692eaee53eSmb158278 */ 1702eaee53eSmb158278 static dcs_alg_t auth_algs_array[] = { 1712eaee53eSmb158278 { "none", SADB_AALG_NONE }, /* -a none or -u none */ 1722eaee53eSmb158278 { "md5", SADB_AALG_MD5HMAC }, /* -a md5 or -u md5 */ 1732eaee53eSmb158278 { "sha1", SADB_AALG_SHA1HMAC }, /* -a sha1 or -u sha1 */ 1742eaee53eSmb158278 { NULL, 0x0 } 1752eaee53eSmb158278 }, esp_algs_array[] = { 1762eaee53eSmb158278 { "none", SADB_EALG_NONE }, /* -e none */ 1772eaee53eSmb158278 { "des", SADB_EALG_DESCBC }, /* -e des */ 1782eaee53eSmb158278 { "3des", SADB_EALG_3DESCBC }, /* -e 3des */ 1792eaee53eSmb158278 { NULL, 0x0 } 1802eaee53eSmb158278 }; 1812eaee53eSmb158278 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * main: 1857c478bd9Sstevel@tonic-gate * 1867c478bd9Sstevel@tonic-gate * Initialize the DCS and then enter an infinite loop. This loop waits 1877c478bd9Sstevel@tonic-gate * for connection requests to come and then establishes a connection. 1887c478bd9Sstevel@tonic-gate * It dispatches the connection to be handled in a concurrent session. 1897c478bd9Sstevel@tonic-gate */ 1907c478bd9Sstevel@tonic-gate int 1917c478bd9Sstevel@tonic-gate main(int argc, char **argv) 1927c478bd9Sstevel@tonic-gate { 1937c478bd9Sstevel@tonic-gate int opt; 1947c478bd9Sstevel@tonic-gate struct timeval tv; 1957c478bd9Sstevel@tonic-gate struct pollfd dcs_rcv; 1967c478bd9Sstevel@tonic-gate int newfd; 1972eaee53eSmb158278 uint8_t ah_auth_alg = SADB_AALG_NONE; 1982eaee53eSmb158278 uint8_t esp_encr_alg = SADB_EALG_NONE; 1992eaee53eSmb158278 uint8_t esp_auth_alg = SADB_AALG_NONE; 2002eaee53eSmb158278 dcs_err_code alg_ec = DCS_NO_ERR; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* initialize globals */ 2047c478bd9Sstevel@tonic-gate dcs_debug = DBG_NONE; 2057c478bd9Sstevel@tonic-gate cmdname = basename(argv[0]); 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* open log file with unique prefix */ 2087c478bd9Sstevel@tonic-gate openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * Process command line args 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate opterr = 0; /* disable getopt error messages */ 2147c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, OPT_STR)) != EOF) { 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate switch (opt) { 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate case 'd': { 2197c478bd9Sstevel@tonic-gate int usr_debug; 2207c478bd9Sstevel@tonic-gate char *err_str; 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate usr_debug = strtol(optarg, &err_str, 0); 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * The err_str parameter will be an 2267c478bd9Sstevel@tonic-gate * empty string if successful. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate if (*err_str != '\0') { 2297c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_BAD_OPT_ARG, optopt, 2307c478bd9Sstevel@tonic-gate optarg, "exiting"); 2317c478bd9Sstevel@tonic-gate (void) rdr_reject(dcsfd); 2327c478bd9Sstevel@tonic-gate exit(1); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate dcs_debug = usr_debug; 2367c478bd9Sstevel@tonic-gate break; 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate case 'S': 2407c478bd9Sstevel@tonic-gate standalone++; 2417c478bd9Sstevel@tonic-gate break; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate case 's': { 2447c478bd9Sstevel@tonic-gate int usr_ses; 2457c478bd9Sstevel@tonic-gate char *err_str; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate usr_ses = strtol(optarg, &err_str, 0); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate if (usr_ses >= 1) { 2507c478bd9Sstevel@tonic-gate max_sessions = usr_ses; 2517c478bd9Sstevel@tonic-gate } else { 2527c478bd9Sstevel@tonic-gate char behavior_str[MAX_MSG_LEN]; 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate snprintf(behavior_str, MAX_MSG_LEN, 2557c478bd9Sstevel@tonic-gate "using default value (%d)", max_sessions); 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_OPT_ARG, optopt, 2587c478bd9Sstevel@tonic-gate optarg, behavior_str); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate break; 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2642eaee53eSmb158278 case 'a': 2652eaee53eSmb158278 case 'u': 2662eaee53eSmb158278 if (opt == 'a') 2672eaee53eSmb158278 ah_auth_alg = dcs_get_alg(auth_algs_array, 2682eaee53eSmb158278 optarg, &alg_ec); 2692eaee53eSmb158278 else /* opt == 'u' */ 2702eaee53eSmb158278 esp_auth_alg = dcs_get_alg(auth_algs_array, 2712eaee53eSmb158278 optarg, &alg_ec); 2722eaee53eSmb158278 2732eaee53eSmb158278 if (alg_ec == DCS_BAD_OPT_ARG) { 2742eaee53eSmb158278 dcs_log_bad_alg(optopt, optarg); 2752eaee53eSmb158278 (void) rdr_reject(dcsfd); 2762eaee53eSmb158278 exit(1); 2772eaee53eSmb158278 } 2782eaee53eSmb158278 2792eaee53eSmb158278 break; 2802eaee53eSmb158278 2812eaee53eSmb158278 case 'e': 2822eaee53eSmb158278 esp_encr_alg = dcs_get_alg(esp_algs_array, optarg, 2832eaee53eSmb158278 &alg_ec); 2842eaee53eSmb158278 2852eaee53eSmb158278 if (alg_ec == DCS_BAD_OPT_ARG) { 2862eaee53eSmb158278 dcs_log_bad_alg(optopt, optarg); 2872eaee53eSmb158278 (void) rdr_reject(dcsfd); 2882eaee53eSmb158278 exit(1); 2892eaee53eSmb158278 } 2902eaee53eSmb158278 2912eaee53eSmb158278 break; 2922eaee53eSmb158278 29325cf1a30Sjl139090 case 'l': 29425cf1a30Sjl139090 use_libdscp = 1; 29525cf1a30Sjl139090 use_family = AF_INET; 29625cf1a30Sjl139090 break; 29725cf1a30Sjl139090 2987c478bd9Sstevel@tonic-gate default: 2992eaee53eSmb158278 if (optopt == 'a' || optopt == 'e' || optopt == 'u') 3002eaee53eSmb158278 dcs_log_bad_alg(optopt, optarg); 3012eaee53eSmb158278 else 3027c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_BAD_OPT, optopt); 3037c478bd9Sstevel@tonic-gate (void) rdr_reject(dcsfd); 3047c478bd9Sstevel@tonic-gate exit(1); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3077c478bd9Sstevel@tonic-gate break; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3112eaee53eSmb158278 /* 3122eaee53eSmb158278 * In the future if inetd supports per-socket IPsec dcs can be run 3132eaee53eSmb158278 * under inetd. 3142eaee53eSmb158278 * Daemonize if we were not started by inetd unless running standalone. 3152eaee53eSmb158278 */ 3162eaee53eSmb158278 inetd = is_socket(STDIN_FILENO); 3172eaee53eSmb158278 if (inetd == B_FALSE && standalone == 0) { 3182eaee53eSmb158278 closefrom(0); 3192eaee53eSmb158278 (void) chdir("/"); 3202eaee53eSmb158278 (void) umask(0); 3212eaee53eSmb158278 3222eaee53eSmb158278 if (fork() != 0) 3232eaee53eSmb158278 exit(0); 3242eaee53eSmb158278 3252eaee53eSmb158278 (void) setsid(); 3262eaee53eSmb158278 3272eaee53eSmb158278 /* open log again after all files were closed */ 3282eaee53eSmb158278 openlog(cmdname, LOG_CONS | LOG_NDELAY, LOG_DAEMON); 3292eaee53eSmb158278 } 3302eaee53eSmb158278 3317c478bd9Sstevel@tonic-gate DCS_DBG(DBG_ALL, "initializing %s...", cmdname); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate init_signals(); 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* must be root */ 3367c478bd9Sstevel@tonic-gate if (geteuid() != 0) { 3377c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_PRIV); 3387c478bd9Sstevel@tonic-gate (void) rdr_reject(dcsfd); 3397c478bd9Sstevel@tonic-gate exit(1); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* 3437c478bd9Sstevel@tonic-gate * Seed the random number generator for 3447c478bd9Sstevel@tonic-gate * generating random session identifiers. 3457c478bd9Sstevel@tonic-gate */ 3467c478bd9Sstevel@tonic-gate gettimeofday(&tv, NULL); 3477c478bd9Sstevel@tonic-gate srand48(tv.tv_usec); 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* initialize our transport endpoint */ 3502eaee53eSmb158278 if (init_server(&dcs_rcv, ah_auth_alg, esp_encr_alg, esp_auth_alg) == 3512eaee53eSmb158278 -1) { 3527c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_INIT_ERR); 3537c478bd9Sstevel@tonic-gate (void) rdr_reject(dcsfd); 3547c478bd9Sstevel@tonic-gate exit(1); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate DCS_DBG(DBG_ALL, "%s initialized, debug level = 0x%X, " 3597c478bd9Sstevel@tonic-gate "max sessions = %d", cmdname, dcs_debug, max_sessions); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate /* 3627c478bd9Sstevel@tonic-gate * Main service loop 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate for (;;) { 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate /* wait for a connection request */ 3677c478bd9Sstevel@tonic-gate if (ses_poll(&dcs_rcv, 1, BLOCKFOREVER) == -1) { 3687c478bd9Sstevel@tonic-gate if (errno != EINTR) { 3697c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_INT_ERR, "poll", 3707c478bd9Sstevel@tonic-gate strerror(errno)); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate continue; 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate /* attempt to connect */ 3767c478bd9Sstevel@tonic-gate newfd = rdr_connect_srv(dcs_rcv.fd); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if ((newfd == RDR_ERROR) || (newfd == RDR_NET_ERR)) { 3797c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CONNECT_ERR); 3807c478bd9Sstevel@tonic-gate continue; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* process the session concurrently */ 3857c478bd9Sstevel@tonic-gate if (ses_start(newfd) == -1) { 3867c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_HAND_ERR); 3877c478bd9Sstevel@tonic-gate (void) rdr_close(newfd); 3887c478bd9Sstevel@tonic-gate break; 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate close(dcs_rcv.fd); 3937c478bd9Sstevel@tonic-gate return (1); 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3982eaee53eSmb158278 * dcs_get_alg: 3992eaee53eSmb158278 * 4002eaee53eSmb158278 * Returns the ID of the first algorithm found in the 'algs' array 4012eaee53eSmb158278 * with a name matching 'arg'. If there is no matching algorithm, 4022eaee53eSmb158278 * 'error' is set to DCS_BAD_OPT_ARG, otherwise it is set to DCS_NO_ERR. 4032eaee53eSmb158278 * The 'algs' array must be terminated by an entry containing a NULL 4042eaee53eSmb158278 * 'arg_name' field. The 'error' argument must be a valid pointer. 4052eaee53eSmb158278 */ 4062eaee53eSmb158278 static uint8_t 4072eaee53eSmb158278 dcs_get_alg(dcs_alg_t *algs, char *arg, dcs_err_code *error) 4082eaee53eSmb158278 { 4092eaee53eSmb158278 dcs_alg_t *alg; 4102eaee53eSmb158278 4112eaee53eSmb158278 *error = DCS_NO_ERR; 4122eaee53eSmb158278 4132eaee53eSmb158278 for (alg = algs; alg->arg_name != NULL && arg != NULL; alg++) { 4142eaee53eSmb158278 if (strncmp(alg->arg_name, arg, strlen(alg->arg_name) + 1) 4152eaee53eSmb158278 == 0) { 4162eaee53eSmb158278 return (alg->alg_id); 4172eaee53eSmb158278 } 4182eaee53eSmb158278 } 4192eaee53eSmb158278 4202eaee53eSmb158278 *error = DCS_BAD_OPT_ARG; 4212eaee53eSmb158278 4222eaee53eSmb158278 return (0); 4232eaee53eSmb158278 } 4242eaee53eSmb158278 4252eaee53eSmb158278 4262eaee53eSmb158278 /* 4272eaee53eSmb158278 * dcs_log_bad_alg: 4282eaee53eSmb158278 * 4292eaee53eSmb158278 * Logs an appropriate message when an invalid command line argument 4302eaee53eSmb158278 * was provided. 'optarg' is the invalid argument string for the 4312eaee53eSmb158278 * command line option 'optopt', where 'optopt' = 'a' for the '-a' 4322eaee53eSmb158278 * option. A NULL 'optarg' indicates the required option was not 4332eaee53eSmb158278 * provided. 4342eaee53eSmb158278 */ 4352eaee53eSmb158278 static void 4362eaee53eSmb158278 dcs_log_bad_alg(char optopt, char *optarg) 4372eaee53eSmb158278 { 4382eaee53eSmb158278 if (optarg == NULL) { 4392eaee53eSmb158278 dcs_log_msg(LOG_ERR, DCS_BAD_OPT_ARG, optopt, 4402eaee53eSmb158278 "empty string", "an argument is required, exiting"); 4412eaee53eSmb158278 } else { 4422eaee53eSmb158278 dcs_log_msg(LOG_ERR, DCS_BAD_OPT_ARG, optopt, 4432eaee53eSmb158278 optarg, "exiting"); 4442eaee53eSmb158278 } 4452eaee53eSmb158278 } 4462eaee53eSmb158278 4472eaee53eSmb158278 4482eaee53eSmb158278 /* 4497c478bd9Sstevel@tonic-gate * init_server: 4507c478bd9Sstevel@tonic-gate * 4517c478bd9Sstevel@tonic-gate * Perform all the operations that are required to initialize the 4527c478bd9Sstevel@tonic-gate * transport endpoint used by the DCS. After this routine succeeds, 4537c478bd9Sstevel@tonic-gate * the DCS is ready to accept session requests on its well known 4547c478bd9Sstevel@tonic-gate * port. 4557c478bd9Sstevel@tonic-gate */ 4567c478bd9Sstevel@tonic-gate static int 4572eaee53eSmb158278 init_server(struct pollfd *pfd, uint8_t ah_auth_alg, uint8_t esp_encr_alg, 4582eaee53eSmb158278 uint8_t esp_auth_alg) 4597c478bd9Sstevel@tonic-gate { 4607c478bd9Sstevel@tonic-gate struct servent *se; 4617c478bd9Sstevel@tonic-gate struct sockaddr_storage ss; 4627c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 4637c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 464*c2623971Sscarter struct linger ling; 4652eaee53eSmb158278 ipsec_req_t ipsec_req; 4667c478bd9Sstevel@tonic-gate int req_port; 4677c478bd9Sstevel@tonic-gate int act_port; 4687c478bd9Sstevel@tonic-gate int init_status; 4697c478bd9Sstevel@tonic-gate int num_sock_opts; 4707c478bd9Sstevel@tonic-gate int sock_opts[] = { SO_REUSEADDR }; 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate assert(pfd); 4742eaee53eSmb158278 pfd->fd = dcsfd; 4752eaee53eSmb158278 pfd->events = POLLIN | POLLPRI; 4762eaee53eSmb158278 pfd->revents = 0; 4772eaee53eSmb158278 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate /* 4807c478bd9Sstevel@tonic-gate * In standalone mode, we have to initialize the transport 4817c478bd9Sstevel@tonic-gate * endpoint for our reserved port. In daemon mode, inetd 4827c478bd9Sstevel@tonic-gate * starts the DCS and hands off STDIN_FILENO connected to 4837c478bd9Sstevel@tonic-gate * our reserved port. 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate 4862eaee53eSmb158278 if (inetd == B_FALSE || standalone) { 4877c478bd9Sstevel@tonic-gate /* in standalone mode, init fd for reserved port */ 48825cf1a30Sjl139090 if ((dcsfd = rdr_open(use_family)) == -1) { 4897c478bd9Sstevel@tonic-gate DCS_DBG(DBG_ALL, "rdr_open failed"); 4902eaee53eSmb158278 return (-1); 4917c478bd9Sstevel@tonic-gate } 4922eaee53eSmb158278 pfd->fd = dcsfd; 4932eaee53eSmb158278 4942eaee53eSmb158278 /* 4952eaee53eSmb158278 * Enable per-socket IPsec if the user specified an 4963a3e8d7aSmb158278 * AH or ESP algorithm to use and global policy is not in 4973a3e8d7aSmb158278 * effect. 4982eaee53eSmb158278 */ 4993a3e8d7aSmb158278 if (!dcs_global_policy() && 5003a3e8d7aSmb158278 (ah_auth_alg != SADB_AALG_NONE || 5012eaee53eSmb158278 esp_encr_alg != SADB_EALG_NONE || 5023a3e8d7aSmb158278 esp_auth_alg != SADB_AALG_NONE)) { 5032eaee53eSmb158278 int err; 5042eaee53eSmb158278 5052eaee53eSmb158278 bzero(&ipsec_req, sizeof (ipsec_req)); 5062eaee53eSmb158278 5072eaee53eSmb158278 /* Hardcoded values */ 5082eaee53eSmb158278 ipsec_req.ipsr_self_encap_req = SELF_ENCAP_REQ; 5092eaee53eSmb158278 /* User defined */ 5102eaee53eSmb158278 ipsec_req.ipsr_auth_alg = ah_auth_alg; 5112eaee53eSmb158278 ipsec_req.ipsr_esp_alg = esp_encr_alg; 5122eaee53eSmb158278 if (ah_auth_alg != SADB_AALG_NONE) 5132eaee53eSmb158278 ipsec_req.ipsr_ah_req = AH_REQ; 5142eaee53eSmb158278 if (esp_encr_alg != SADB_EALG_NONE || 5152eaee53eSmb158278 esp_auth_alg != SADB_AALG_NONE) { 5162eaee53eSmb158278 ipsec_req.ipsr_esp_req = ESP_REQ; 5172eaee53eSmb158278 ipsec_req.ipsr_esp_auth_alg = esp_auth_alg; 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5202eaee53eSmb158278 err = rdr_setsockopt(pfd->fd, IPPROTO_IPV6, 5212eaee53eSmb158278 IPV6_SEC_OPT, (void *)&ipsec_req, 5222eaee53eSmb158278 sizeof (ipsec_req)); 5232eaee53eSmb158278 5242eaee53eSmb158278 if (err != RDR_OK) { 5252eaee53eSmb158278 DCS_DBG(DBG_ALL, "rdr_setsockopt failed"); 5262eaee53eSmb158278 return (-1); 5272eaee53eSmb158278 } 5282eaee53eSmb158278 } 5292eaee53eSmb158278 } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * Look up our service to get the reserved port number 5337c478bd9Sstevel@tonic-gate */ 5347c478bd9Sstevel@tonic-gate if ((se = getservbyname(DCS_SERVICE, "tcp")) == NULL) { 5357c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_NO_SERV, DCS_SERVICE); 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate /* use the known port if service wasn't found */ 5387c478bd9Sstevel@tonic-gate req_port = SUN_DR_PORT; 5397c478bd9Sstevel@tonic-gate } else { 5407c478bd9Sstevel@tonic-gate req_port = se->s_port; 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate 54325cf1a30Sjl139090 (void) memset(&ss, 0, sizeof (ss)); 54425cf1a30Sjl139090 if (use_family == AF_INET) { 54525cf1a30Sjl139090 /* initialize our local address */ 54625cf1a30Sjl139090 sin = (struct sockaddr_in *)&ss; 54725cf1a30Sjl139090 sin->sin_family = AF_INET; 54825cf1a30Sjl139090 sin->sin_port = htons(req_port); 54925cf1a30Sjl139090 sin->sin_addr.s_addr = htonl(INADDR_ANY); 55025cf1a30Sjl139090 } else { 5517c478bd9Sstevel@tonic-gate /* initialize our local address */ 5527c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)&ss; 5537c478bd9Sstevel@tonic-gate sin6->sin6_family = AF_INET6; 5547c478bd9Sstevel@tonic-gate sin6->sin6_port = htons(req_port); 5557c478bd9Sstevel@tonic-gate sin6->sin6_addr = in6addr_any; 55625cf1a30Sjl139090 } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate num_sock_opts = sizeof (sock_opts) / sizeof (*sock_opts); 5597c478bd9Sstevel@tonic-gate 56025cf1a30Sjl139090 init_status = rdr_init(pfd->fd, (struct sockaddr *)&ss, 5617c478bd9Sstevel@tonic-gate sock_opts, num_sock_opts, DCS_BACKLOG); 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate if (init_status != RDR_OK) { 5647c478bd9Sstevel@tonic-gate return (-1); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 567*c2623971Sscarter /* 568*c2623971Sscarter * Set the SO_LINGER socket option so that TCP aborts the connection 569*c2623971Sscarter * when the socket is closed. This avoids encountering a TIME_WAIT 570*c2623971Sscarter * state if the daemon ever crashes and is instantly restarted. 571*c2623971Sscarter */ 572*c2623971Sscarter ling.l_onoff = 1; 573*c2623971Sscarter ling.l_linger = 0; 574*c2623971Sscarter if (setsockopt(pfd->fd, SOL_SOCKET, SO_LINGER, &ling, sizeof (ling))) { 575*c2623971Sscarter return (-1); 576*c2623971Sscarter } 577*c2623971Sscarter 5787c478bd9Sstevel@tonic-gate switch (ss.ss_family) { 5797c478bd9Sstevel@tonic-gate case AF_INET: 5807c478bd9Sstevel@tonic-gate DCS_DBG(DBG_ALL, "using AF_INET socket"); 5817c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ss; 5827c478bd9Sstevel@tonic-gate act_port = ntohs(sin->sin_port); 5837c478bd9Sstevel@tonic-gate break; 5847c478bd9Sstevel@tonic-gate case AF_INET6: 5857c478bd9Sstevel@tonic-gate DCS_DBG(DBG_ALL, "using AF_INET6 socket"); 5867c478bd9Sstevel@tonic-gate /* sin6 already set correctly */ 5877c478bd9Sstevel@tonic-gate act_port = ntohs(sin6->sin6_port); 5887c478bd9Sstevel@tonic-gate break; 5897c478bd9Sstevel@tonic-gate default: 5907c478bd9Sstevel@tonic-gate DCS_DBG(DBG_ALL, "unknown socket type"); 5917c478bd9Sstevel@tonic-gate return (-1); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate /* check that we got the requested port */ 5957c478bd9Sstevel@tonic-gate if (req_port != act_port) { 5967c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_PORT, req_port); 5977c478bd9Sstevel@tonic-gate return (-1); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate return (0); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate /* 6057c478bd9Sstevel@tonic-gate * init_signals: 6067c478bd9Sstevel@tonic-gate * 6077c478bd9Sstevel@tonic-gate * Initialize signals for the current session. All signals will be 6087c478bd9Sstevel@tonic-gate * blocked with two possible exceptions. SIGINT is not blocked in 6097c478bd9Sstevel@tonic-gate * standalone mode, and ses_init_signals() is called to selectively 6107c478bd9Sstevel@tonic-gate * unblock any signals required to handle concurrent sessions. 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate static void 6137c478bd9Sstevel@tonic-gate init_signals(void) 6147c478bd9Sstevel@tonic-gate { 6157c478bd9Sstevel@tonic-gate sigset_t mask; 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* block all signals */ 6197c478bd9Sstevel@tonic-gate sigfillset(&mask); 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate /* in standalone, allow user to abort */ 6227c478bd9Sstevel@tonic-gate if (standalone) { 6237c478bd9Sstevel@tonic-gate sigdelset(&mask, SIGINT); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate ses_init_signals(&mask); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &mask, NULL); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate /* 6337c478bd9Sstevel@tonic-gate * dcs_dispatch_message: 6347c478bd9Sstevel@tonic-gate * 6357c478bd9Sstevel@tonic-gate * This function dispatches a message to the correct function. The 6367c478bd9Sstevel@tonic-gate * correct handler is determined by the opcode field of the message 6377c478bd9Sstevel@tonic-gate * header. 6387c478bd9Sstevel@tonic-gate */ 6397c478bd9Sstevel@tonic-gate int 6407c478bd9Sstevel@tonic-gate dcs_dispatch_message(rdr_msg_hdr_t *hdr, cfga_params_t *params) 6417c478bd9Sstevel@tonic-gate { 6427c478bd9Sstevel@tonic-gate session_t *sp; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate assert(hdr); 6467c478bd9Sstevel@tonic-gate assert(params); 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate /* get the current session information */ 6497c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 6507c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 6517c478bd9Sstevel@tonic-gate return (-1); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate /* check the message */ 6557c478bd9Sstevel@tonic-gate if (invalid_msg(hdr)) { 6567c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 6577c478bd9Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 6587c478bd9Sstevel@tonic-gate return (-1); 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate /* save the current message */ 6627c478bd9Sstevel@tonic-gate sp->curr_msg.hdr = hdr; 6637c478bd9Sstevel@tonic-gate sp->curr_msg.params = params; 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* 6667c478bd9Sstevel@tonic-gate * hdr->message_opcode is unsigned so don't need 6677c478bd9Sstevel@tonic-gate * to check for values less than zero 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate if (hdr->message_opcode >= RDR_NUM_OPS) { 6707c478bd9Sstevel@tonic-gate dcs_unknown_op(hdr, params); 6717c478bd9Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 6727c478bd9Sstevel@tonic-gate return (-1); 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_RECEIVE, hdr); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* dispatch the message */ 6787c478bd9Sstevel@tonic-gate if ((*dcs_cmd[hdr->message_opcode])(hdr, params) == -1) { 6797c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_FAILED); 6807c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 6817c478bd9Sstevel@tonic-gate return (-1); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate return (0); 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* 6897c478bd9Sstevel@tonic-gate * init_msg: 6907c478bd9Sstevel@tonic-gate * 6917c478bd9Sstevel@tonic-gate * Initialize the message header with information from the current 6927c478bd9Sstevel@tonic-gate * session. Fields not set directly are initialized to zero. 6937c478bd9Sstevel@tonic-gate */ 6947c478bd9Sstevel@tonic-gate void 6957c478bd9Sstevel@tonic-gate init_msg(rdr_msg_hdr_t *hdr) 6967c478bd9Sstevel@tonic-gate { 6977c478bd9Sstevel@tonic-gate session_t *sp; 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate assert(hdr); 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* get the current session information */ 7037c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 7047c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 7057c478bd9Sstevel@tonic-gate return; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate (void) memset(hdr, 0, sizeof (rdr_msg_hdr_t)); 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate /* set the session information */ 7117c478bd9Sstevel@tonic-gate hdr->random_req = sp->random_req; 7127c478bd9Sstevel@tonic-gate hdr->random_resp = sp->random_resp; 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate /* set the version being used */ 7157c478bd9Sstevel@tonic-gate hdr->major_version = sp->major_version; 7167c478bd9Sstevel@tonic-gate hdr->minor_version = sp->minor_version; 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate /* 7217c478bd9Sstevel@tonic-gate * invalid_msg: 7227c478bd9Sstevel@tonic-gate * 7237c478bd9Sstevel@tonic-gate * Check if the message is valid for the current session. This 7247c478bd9Sstevel@tonic-gate * is accomplished by checking various information in the header 7257c478bd9Sstevel@tonic-gate * against the information for the current session. 7267c478bd9Sstevel@tonic-gate */ 7277c478bd9Sstevel@tonic-gate static int 7287c478bd9Sstevel@tonic-gate invalid_msg(rdr_msg_hdr_t *hdr) 7297c478bd9Sstevel@tonic-gate { 7307c478bd9Sstevel@tonic-gate session_t *sp; 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate assert(hdr); 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate /* get the current session information */ 7367c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 7377c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 7387c478bd9Sstevel@tonic-gate return (-1); 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate /* 7427c478bd9Sstevel@tonic-gate * Only perform the following checks if the message 7437c478bd9Sstevel@tonic-gate * is not a session request. The information to check 7447c478bd9Sstevel@tonic-gate * will not be set at the time a session request is 7457c478bd9Sstevel@tonic-gate * received. 7467c478bd9Sstevel@tonic-gate */ 7477c478bd9Sstevel@tonic-gate if (hdr->message_opcode != RDR_SES_REQ) { 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate /* check major and minor version */ 7507c478bd9Sstevel@tonic-gate if ((sp->major_version != hdr->major_version) || 7517c478bd9Sstevel@tonic-gate (sp->minor_version != hdr->minor_version)) { 7527c478bd9Sstevel@tonic-gate DCS_DBG(DBG_MSG, "unsupported version %d.%d", 7537c478bd9Sstevel@tonic-gate hdr->major_version, hdr->minor_version); 7547c478bd9Sstevel@tonic-gate return (-1); 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate /* check session identifiers */ 7587c478bd9Sstevel@tonic-gate if ((sp->random_req != hdr->random_req) || 7597c478bd9Sstevel@tonic-gate (sp->random_resp != hdr->random_resp)) { 7607c478bd9Sstevel@tonic-gate DCS_DBG(DBG_MSG, "invalid session identifiers: " 7617c478bd9Sstevel@tonic-gate "<%d, %d>", hdr->random_req, hdr->random_resp); 7627c478bd9Sstevel@tonic-gate return (-1); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate return (0); 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate /* 7717c478bd9Sstevel@tonic-gate * dcs_ses_req: 7727c478bd9Sstevel@tonic-gate * 7737c478bd9Sstevel@tonic-gate * Handle a session request message (RDR_SES_REQ). 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate static int 7767c478bd9Sstevel@tonic-gate dcs_ses_req(rdr_msg_hdr_t *hdr, cfga_params_t *param) 7777c478bd9Sstevel@tonic-gate { 7787c478bd9Sstevel@tonic-gate session_t *sp; 7797c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 7807c478bd9Sstevel@tonic-gate cfga_params_t reply_param; 7817c478bd9Sstevel@tonic-gate dcs_ver_t act_ver; 7827c478bd9Sstevel@tonic-gate int snd_status; 7837c478bd9Sstevel@tonic-gate static char *op_name = "session request"; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate assert(hdr); 7877c478bd9Sstevel@tonic-gate assert(param); 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate /* get the current session information */ 7907c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 7917c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 7927c478bd9Sstevel@tonic-gate return (-1); 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* make sure that a session hasn't been requested yet */ 7967c478bd9Sstevel@tonic-gate if (sp->state != DCS_CONNECTED) { 7977c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_SEQ_INVAL); 7987c478bd9Sstevel@tonic-gate ses_close(DCS_SES_SEQ_INVAL); 7997c478bd9Sstevel@tonic-gate return (-1); 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate ses_setlocale(param->req.locale_str); 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate /* get the best matching version supported */ 8057c478bd9Sstevel@tonic-gate act_ver = resolve_version(hdr->major_version, hdr->minor_version); 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate /* initialize session information */ 8087c478bd9Sstevel@tonic-gate sp->random_req = hdr->random_req; 8097c478bd9Sstevel@tonic-gate sp->major_version = act_ver.major; 8107c478bd9Sstevel@tonic-gate sp->minor_version = act_ver.minor; 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* prepare header information */ 8137c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 8147c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_SES_REQ; 8157c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 8167c478bd9Sstevel@tonic-gate reply_hdr.status = DCS_OK; 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate /* prepare session request specific data */ 8197c478bd9Sstevel@tonic-gate (void) memset(&reply_param, 0, sizeof (cfga_params_t)); 8207c478bd9Sstevel@tonic-gate reply_param.req.session_id = sp->id; 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate /* send the message */ 8257c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, &reply_param, 8267c478bd9Sstevel@tonic-gate DCS_SND_TIMEOUT); 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 8297c478bd9Sstevel@tonic-gate abort_handler(); 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 8337c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 8347c478bd9Sstevel@tonic-gate return (-1); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate sp->state = DCS_SES_REQ; 8387c478bd9Sstevel@tonic-gate return (0); 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate /* 8437c478bd9Sstevel@tonic-gate * dcs_ses_estbl: 8447c478bd9Sstevel@tonic-gate * 8457c478bd9Sstevel@tonic-gate * Handle a session establishment message (RDR_SES_ESTBL). 8467c478bd9Sstevel@tonic-gate */ 8477c478bd9Sstevel@tonic-gate /* ARGSUSED */ 8487c478bd9Sstevel@tonic-gate static int 8497c478bd9Sstevel@tonic-gate dcs_ses_estbl(rdr_msg_hdr_t *hdr, cfga_params_t *param) 8507c478bd9Sstevel@tonic-gate { 8517c478bd9Sstevel@tonic-gate session_t *sp; 8527c478bd9Sstevel@tonic-gate dcs_ver_t act_ver; 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate assert(hdr); 8567c478bd9Sstevel@tonic-gate assert(param); 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* get the current session information */ 8597c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 8607c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 8617c478bd9Sstevel@tonic-gate return (-1); 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate /* 8657c478bd9Sstevel@tonic-gate * Make sure that a session has not been 8667c478bd9Sstevel@tonic-gate * established yet, and that a session 8677c478bd9Sstevel@tonic-gate * request has already been processed. 8687c478bd9Sstevel@tonic-gate */ 8697c478bd9Sstevel@tonic-gate if (sp->state != DCS_SES_REQ) { 8707c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_SES_SEQ_INVAL); 8717c478bd9Sstevel@tonic-gate ses_close(DCS_SES_SEQ_INVAL); 8727c478bd9Sstevel@tonic-gate return (-1); 8737c478bd9Sstevel@tonic-gate } 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate /* get the best matching version supported */ 8767c478bd9Sstevel@tonic-gate act_ver = resolve_version(hdr->major_version, hdr->minor_version); 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate if ((act_ver.major != hdr->major_version) || 8797c478bd9Sstevel@tonic-gate (act_ver.minor != hdr->minor_version)) { 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate /* end the session because protocol not supported */ 8827c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_VER_INVAL, hdr->major_version, 8837c478bd9Sstevel@tonic-gate hdr->minor_version); 8847c478bd9Sstevel@tonic-gate ses_close(DCS_VER_INVAL); 8857c478bd9Sstevel@tonic-gate return (-1); 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate DCS_DBG(DBG_SES, "Session Established"); 8897c478bd9Sstevel@tonic-gate sp->state = DCS_SES_ESTBL; 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate return (0); 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate /* 8967c478bd9Sstevel@tonic-gate * dcs_ses_end: 8977c478bd9Sstevel@tonic-gate * 8987c478bd9Sstevel@tonic-gate * Handle a session end message (RDR_SES_END). 8997c478bd9Sstevel@tonic-gate */ 9007c478bd9Sstevel@tonic-gate static int 9017c478bd9Sstevel@tonic-gate dcs_ses_end(rdr_msg_hdr_t *hdr, cfga_params_t *param) 9027c478bd9Sstevel@tonic-gate { 9037c478bd9Sstevel@tonic-gate session_t *sp; 9047c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 9057c478bd9Sstevel@tonic-gate cfga_params_t reply_param; 9067c478bd9Sstevel@tonic-gate int snd_status; 9077c478bd9Sstevel@tonic-gate static char *op_name = "session end"; 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate assert(hdr); 9117c478bd9Sstevel@tonic-gate assert(param); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* get the current session information */ 9147c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 9157c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 9167c478bd9Sstevel@tonic-gate return (-1); 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate /* 9207c478bd9Sstevel@tonic-gate * Session end is valid from any state. However, only 9217c478bd9Sstevel@tonic-gate * send back a reply if the error code is zero. A non-zero 9227c478bd9Sstevel@tonic-gate * error code indicates that the session is being terminated 9237c478bd9Sstevel@tonic-gate * under an error condition, and no acknowledgement is 9247c478bd9Sstevel@tonic-gate * required. 9257c478bd9Sstevel@tonic-gate */ 9267c478bd9Sstevel@tonic-gate if (param->end.error_code == 0) { 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate /* prepare header information */ 9297c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 9307c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_SES_END; 9317c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 9327c478bd9Sstevel@tonic-gate reply_hdr.status = DCS_OK; 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate /* return empty data - no information needed in reply */ 9357c478bd9Sstevel@tonic-gate (void) memset(&reply_param, 0, sizeof (cfga_params_t)); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, &reply_param, 9407c478bd9Sstevel@tonic-gate DCS_SND_TIMEOUT); 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 9437c478bd9Sstevel@tonic-gate abort_handler(); 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 9477c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate sp->state = DCS_SES_END; 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate /* 9587c478bd9Sstevel@tonic-gate * dcs_change_state: 9597c478bd9Sstevel@tonic-gate * 9607c478bd9Sstevel@tonic-gate * Handle a change state request message (RDR_CONF_CHANGE_STATE). 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate static int 9637c478bd9Sstevel@tonic-gate dcs_change_state(rdr_msg_hdr_t *hdr, cfga_params_t *param) 9647c478bd9Sstevel@tonic-gate { 9657c478bd9Sstevel@tonic-gate session_t *sp; 9667c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 9677c478bd9Sstevel@tonic-gate change_state_params_t *op_data; 9687c478bd9Sstevel@tonic-gate struct cfga_confirm local_conf_cb; 9697c478bd9Sstevel@tonic-gate struct cfga_msg local_msg_cb; 9707c478bd9Sstevel@tonic-gate int cfga_status = 0; 9717c478bd9Sstevel@tonic-gate int snd_status; 9727c478bd9Sstevel@tonic-gate char *err_str; 9737c478bd9Sstevel@tonic-gate unsigned int curr_attempt; 9747c478bd9Sstevel@tonic-gate unsigned int num_attempts; 9757c478bd9Sstevel@tonic-gate char retry_msg[MAX_MSG_LEN]; 9767c478bd9Sstevel@tonic-gate static char *op_name = "config_change_state"; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate assert(hdr); 9807c478bd9Sstevel@tonic-gate assert(param); 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate /* get the current session information */ 9837c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 9847c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 9857c478bd9Sstevel@tonic-gate return (-1); 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate op_data = ¶m->change; 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate /* make sure we have a session established */ 9917c478bd9Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 9927c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 9937c478bd9Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 9947c478bd9Sstevel@tonic-gate return (-1); 9957c478bd9Sstevel@tonic-gate } 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate /* initialize local confirm callback */ 9987c478bd9Sstevel@tonic-gate local_conf_cb.confirm = dcs_confirm_callback; 9997c478bd9Sstevel@tonic-gate local_conf_cb.appdata_ptr = (void *)op_data->confp; 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate /* initialize local message callback */ 10027c478bd9Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 10037c478bd9Sstevel@tonic-gate local_msg_cb.appdata_ptr = (void *)op_data->msgp; 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* verify retry value */ 10067c478bd9Sstevel@tonic-gate if (op_data->retries < 0) { 10077c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_RETRY_VAL, op_data->retries); 10087c478bd9Sstevel@tonic-gate op_data->retries = 0; 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate /* verify timeout value */ 10127c478bd9Sstevel@tonic-gate if (op_data->timeval < 0) { 10137c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_BAD_TIME_VAL, op_data->timeval); 10147c478bd9Sstevel@tonic-gate op_data->timeval = 0; 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate num_attempts = 1 + op_data->retries; 10187c478bd9Sstevel@tonic-gate curr_attempt = 0; 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate while (curr_attempt < num_attempts) { 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate /* don't sleep the first time around */ 10237c478bd9Sstevel@tonic-gate if (curr_attempt != 0) { 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate /* log the error message and alert the user */ 10267c478bd9Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 10277c478bd9Sstevel@tonic-gate if (err_str) { 10287c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, 10297c478bd9Sstevel@tonic-gate err_str); 10307c478bd9Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, 10317c478bd9Sstevel@tonic-gate err_str); 10327c478bd9Sstevel@tonic-gate free((void *)err_str); 10337c478bd9Sstevel@tonic-gate } else { 10347c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_UNKNOWN); 10357c478bd9Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, 10367c478bd9Sstevel@tonic-gate dcs_strerror(DCS_CFGA_UNKNOWN)); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 10407c478bd9Sstevel@tonic-gate free((void *)*op_data->errstring); 10417c478bd9Sstevel@tonic-gate *op_data->errstring = NULL; 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate /* sleep with abort enabled */ 10457c478bd9Sstevel@tonic-gate ses_sleep(op_data->timeval); 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate /* log the retry attempt and alert the user */ 10487c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_RETRY, curr_attempt); 10497c478bd9Sstevel@tonic-gate snprintf(retry_msg, MAX_MSG_LEN, 10507c478bd9Sstevel@tonic-gate dcs_strerror(DCS_RETRY), curr_attempt); 10517c478bd9Sstevel@tonic-gate dcs_message_callback((void *)op_data->msgp, retry_msg); 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* 10577c478bd9Sstevel@tonic-gate * Call into libcfgadm 10587c478bd9Sstevel@tonic-gate */ 10597c478bd9Sstevel@tonic-gate ses_abort_enable(); 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate cfga_status = config_change_state(op_data->state_change, 10627c478bd9Sstevel@tonic-gate op_data->num_ap_ids, op_data->ap_ids, op_data->options, 10637c478bd9Sstevel@tonic-gate &local_conf_cb, &local_msg_cb, op_data->errstring, 10647c478bd9Sstevel@tonic-gate op_data->flags); 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate ses_abort_disable(); 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate /* 10697c478bd9Sstevel@tonic-gate * Retry only the operations that have a chance to 10707c478bd9Sstevel@tonic-gate * succeed if retried. All libcfgadm errors not 10717c478bd9Sstevel@tonic-gate * included below will always fail, regardless of 10727c478bd9Sstevel@tonic-gate * a retry. 10737c478bd9Sstevel@tonic-gate */ 10747c478bd9Sstevel@tonic-gate if ((cfga_status != CFGA_BUSY) && 10757c478bd9Sstevel@tonic-gate (cfga_status != CFGA_SYSTEM_BUSY) && 10767c478bd9Sstevel@tonic-gate (cfga_status != CFGA_ERROR)) { 10777c478bd9Sstevel@tonic-gate break; 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate /* prepare for another attempt */ 10817c478bd9Sstevel@tonic-gate ++curr_attempt; 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate /* log any libcfgadm errors */ 10877c478bd9Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 10887c478bd9Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 10897c478bd9Sstevel@tonic-gate if (err_str) { 10907c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 10917c478bd9Sstevel@tonic-gate free((void *)err_str); 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate /* prepare header information */ 10967c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 10977c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_CHANGE_STATE; 10987c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 10997c478bd9Sstevel@tonic-gate reply_hdr.status = cfga_status; 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate /* send the message */ 11047c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 11077c478bd9Sstevel@tonic-gate abort_handler(); 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 11117c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate /* clean up */ 11157c478bd9Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 11167c478bd9Sstevel@tonic-gate free((void *)*op_data->errstring); 11177c478bd9Sstevel@tonic-gate *op_data->errstring = NULL; 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate 11247c478bd9Sstevel@tonic-gate /* 11257c478bd9Sstevel@tonic-gate * dcs_private_func: 11267c478bd9Sstevel@tonic-gate * 11277c478bd9Sstevel@tonic-gate * Handle a private function request message (RDR_CONF_PRIVATE_FUNC). 11287c478bd9Sstevel@tonic-gate */ 11297c478bd9Sstevel@tonic-gate static int 11307c478bd9Sstevel@tonic-gate dcs_private_func(rdr_msg_hdr_t *hdr, cfga_params_t *param) 11317c478bd9Sstevel@tonic-gate { 11327c478bd9Sstevel@tonic-gate session_t *sp; 11337c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 11347c478bd9Sstevel@tonic-gate private_func_params_t *op_data; 11357c478bd9Sstevel@tonic-gate struct cfga_confirm local_conf_cb; 11367c478bd9Sstevel@tonic-gate struct cfga_msg local_msg_cb; 11377c478bd9Sstevel@tonic-gate int cfga_status; 11387c478bd9Sstevel@tonic-gate int snd_status; 11397c478bd9Sstevel@tonic-gate char *err_str; 11407c478bd9Sstevel@tonic-gate static char *op_name = "config_private_func"; 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate assert(hdr); 11447c478bd9Sstevel@tonic-gate assert(param); 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate /* get the current session information */ 11477c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 11487c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 11497c478bd9Sstevel@tonic-gate return (-1); 11507c478bd9Sstevel@tonic-gate } 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate op_data = ¶m->priv; 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate /* make sure we have a session established */ 11557c478bd9Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 11567c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 11577c478bd9Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 11587c478bd9Sstevel@tonic-gate return (-1); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate /* initialize local confirm callback */ 11627c478bd9Sstevel@tonic-gate local_conf_cb.confirm = dcs_confirm_callback; 11637c478bd9Sstevel@tonic-gate local_conf_cb.appdata_ptr = (void *)op_data->confp; 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate /* initialize local message callback */ 11667c478bd9Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 11677c478bd9Sstevel@tonic-gate local_msg_cb.appdata_ptr = (void *)op_data->msgp; 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate /* 11727c478bd9Sstevel@tonic-gate * Call into libcfgadm 11737c478bd9Sstevel@tonic-gate */ 11747c478bd9Sstevel@tonic-gate ses_abort_enable(); 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate cfga_status = config_private_func(op_data->function, 11777c478bd9Sstevel@tonic-gate op_data->num_ap_ids, op_data->ap_ids, op_data->options, 11787c478bd9Sstevel@tonic-gate &local_conf_cb, &local_msg_cb, op_data->errstring, op_data->flags); 11797c478bd9Sstevel@tonic-gate 11807c478bd9Sstevel@tonic-gate ses_abort_disable(); 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate /* log any libcfgadm errors */ 11857c478bd9Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 11867c478bd9Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 11877c478bd9Sstevel@tonic-gate if (err_str) { 11887c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 11897c478bd9Sstevel@tonic-gate free((void *)err_str); 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate /* prepare header information */ 11947c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 11957c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_PRIVATE_FUNC; 11967c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 11977c478bd9Sstevel@tonic-gate reply_hdr.status = cfga_status; 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate /* send the message */ 12027c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 12057c478bd9Sstevel@tonic-gate abort_handler(); 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 12097c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 12137c478bd9Sstevel@tonic-gate free((void *)*op_data->errstring); 12147c478bd9Sstevel@tonic-gate *op_data->errstring = NULL; 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate /* 12227c478bd9Sstevel@tonic-gate * dcs_test: 12237c478bd9Sstevel@tonic-gate * 12247c478bd9Sstevel@tonic-gate * Handle a test request message (RDR_CONF_TEST). 12257c478bd9Sstevel@tonic-gate */ 12267c478bd9Sstevel@tonic-gate static int 12277c478bd9Sstevel@tonic-gate dcs_test(rdr_msg_hdr_t *hdr, cfga_params_t *param) 12287c478bd9Sstevel@tonic-gate { 12297c478bd9Sstevel@tonic-gate session_t *sp; 12307c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 12317c478bd9Sstevel@tonic-gate test_params_t *op_data; 12327c478bd9Sstevel@tonic-gate struct cfga_msg local_msg_cb; 12337c478bd9Sstevel@tonic-gate int cfga_status; 12347c478bd9Sstevel@tonic-gate int snd_status; 12357c478bd9Sstevel@tonic-gate char *err_str; 12367c478bd9Sstevel@tonic-gate static char *op_name = "config_test"; 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate assert(hdr); 12407c478bd9Sstevel@tonic-gate assert(param); 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate /* get the current session information */ 12437c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 12447c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 12457c478bd9Sstevel@tonic-gate return (-1); 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate op_data = ¶m->test; 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate /* make sure we have a session established */ 12517c478bd9Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 12527c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 12537c478bd9Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 12547c478bd9Sstevel@tonic-gate return (-1); 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate 12577c478bd9Sstevel@tonic-gate /* initialize local message callback */ 12587c478bd9Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 12597c478bd9Sstevel@tonic-gate local_msg_cb.appdata_ptr = op_data->msgp; 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate /* 12647c478bd9Sstevel@tonic-gate * Call into libcfgadm 12657c478bd9Sstevel@tonic-gate */ 12667c478bd9Sstevel@tonic-gate ses_abort_enable(); 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate cfga_status = config_test(op_data->num_ap_ids, op_data->ap_ids, 12697c478bd9Sstevel@tonic-gate op_data->options, &local_msg_cb, op_data->errstring, 12707c478bd9Sstevel@tonic-gate op_data->flags); 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate ses_abort_disable(); 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 12757c478bd9Sstevel@tonic-gate 12767c478bd9Sstevel@tonic-gate /* log any libcfgadm errors */ 12777c478bd9Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 12787c478bd9Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 12797c478bd9Sstevel@tonic-gate if (err_str) { 12807c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_CFGA_ERR, op_name, err_str); 12817c478bd9Sstevel@tonic-gate free((void *)err_str); 12827c478bd9Sstevel@tonic-gate } 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate /* prepare header information */ 12867c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 12877c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_TEST; 12887c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 12897c478bd9Sstevel@tonic-gate reply_hdr.status = cfga_status; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate /* send the message */ 12947c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 12977c478bd9Sstevel@tonic-gate abort_handler(); 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 13017c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 13027c478bd9Sstevel@tonic-gate } 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 13057c478bd9Sstevel@tonic-gate free((void *)*op_data->errstring); 13067c478bd9Sstevel@tonic-gate *op_data->errstring = NULL; 13077c478bd9Sstevel@tonic-gate } 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate /* 13147c478bd9Sstevel@tonic-gate * dcs_list_ext: 13157c478bd9Sstevel@tonic-gate * 13167c478bd9Sstevel@tonic-gate * Handle a list request message (RDR_CONF_LIST_EXT). 13177c478bd9Sstevel@tonic-gate */ 13187c478bd9Sstevel@tonic-gate static int 13197c478bd9Sstevel@tonic-gate dcs_list_ext(rdr_msg_hdr_t *hdr, cfga_params_t *param) 13207c478bd9Sstevel@tonic-gate { 13217c478bd9Sstevel@tonic-gate session_t *sp; 13227c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 13237c478bd9Sstevel@tonic-gate list_ext_params_t *op_data; 13247c478bd9Sstevel@tonic-gate int cfga_status; 13257c478bd9Sstevel@tonic-gate int snd_status; 13267c478bd9Sstevel@tonic-gate char *err_str; 13277c478bd9Sstevel@tonic-gate static char *op_name = "config_list_ext"; 13287c478bd9Sstevel@tonic-gate cfga_list_data_t *ap_ids; 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate assert(hdr); 13327c478bd9Sstevel@tonic-gate assert(param); 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate /* get the current session information */ 13357c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 13367c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 13377c478bd9Sstevel@tonic-gate return (-1); 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate op_data = ¶m->list_ext; 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate /* make sure we have a session established */ 13437c478bd9Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 13447c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 13457c478bd9Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 13467c478bd9Sstevel@tonic-gate return (-1); 13477c478bd9Sstevel@tonic-gate } 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate /* 13507c478bd9Sstevel@tonic-gate * Make sure that we can retrieve the data 13517c478bd9Sstevel@tonic-gate * from libcfgadm. If not, report the error. 13527c478bd9Sstevel@tonic-gate */ 13537c478bd9Sstevel@tonic-gate if (op_data->ap_id_list == NULL) { 13547c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 13557c478bd9Sstevel@tonic-gate ses_close(DCS_MSG_INVAL); 13567c478bd9Sstevel@tonic-gate return (-1); 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate /* 13627c478bd9Sstevel@tonic-gate * Call into libcfgadm 13637c478bd9Sstevel@tonic-gate */ 13647c478bd9Sstevel@tonic-gate ses_abort_enable(); 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate cfga_status = config_list_ext(op_data->num_ap_ids, op_data->ap_ids, 13677c478bd9Sstevel@tonic-gate &ap_ids, op_data->nlist, op_data->options, op_data->listopts, 13687c478bd9Sstevel@tonic-gate op_data->errstring, op_data->flags); 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate ses_abort_disable(); 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate /* 13757c478bd9Sstevel@tonic-gate * Log any libcfgadm errors at a low priority level. 13767c478bd9Sstevel@tonic-gate * Since a status request does not modify the system 13777c478bd9Sstevel@tonic-gate * in any way, we do not need to worry about these 13787c478bd9Sstevel@tonic-gate * errors here on the host. 13797c478bd9Sstevel@tonic-gate */ 13807c478bd9Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 13817c478bd9Sstevel@tonic-gate err_str = dcs_cfga_str(op_data->errstring, cfga_status); 13827c478bd9Sstevel@tonic-gate if (err_str) { 13837c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_CFGA_ERR, op_name, err_str); 13847c478bd9Sstevel@tonic-gate free((void *)err_str); 13857c478bd9Sstevel@tonic-gate } 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* 13897c478bd9Sstevel@tonic-gate * Filter ap ids to return only appropriate information 13907c478bd9Sstevel@tonic-gate */ 13917c478bd9Sstevel@tonic-gate filter_list_data(op_data->permissions, op_data->nlist, ap_ids); 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate /* if all aps were filtered out, return an error */ 13947c478bd9Sstevel@tonic-gate if ((cfga_status == CFGA_OK) && (*op_data->nlist == 0)) { 13957c478bd9Sstevel@tonic-gate cfga_status = CFGA_APID_NOEXIST; 13967c478bd9Sstevel@tonic-gate } 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate /* calculate the sort order */ 13997c478bd9Sstevel@tonic-gate if (cfga_status == CFGA_OK) { 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate *op_data->ap_id_list = generate_sort_order(ap_ids, 14027c478bd9Sstevel@tonic-gate *op_data->nlist); 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate if (*op_data->ap_id_list == NULL) { 14057c478bd9Sstevel@tonic-gate cfga_status = CFGA_LIB_ERROR; 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate /* ensure that nlist is 0 for errors */ 14107c478bd9Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 14117c478bd9Sstevel@tonic-gate *op_data->nlist = 0; 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate /* prepare header information */ 14157c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 14167c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_LIST_EXT; 14177c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 14187c478bd9Sstevel@tonic-gate reply_hdr.status = cfga_status; 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate /* send the message */ 14237c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 14267c478bd9Sstevel@tonic-gate abort_handler(); 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 14307c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate if (op_data->errstring && *op_data->errstring) { 14347c478bd9Sstevel@tonic-gate free((void *)*op_data->errstring); 14357c478bd9Sstevel@tonic-gate *op_data->errstring = NULL; 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate if (ap_ids != NULL) { 14397c478bd9Sstevel@tonic-gate free((void *)ap_ids); 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate /* 14477c478bd9Sstevel@tonic-gate * dcs_help: 14487c478bd9Sstevel@tonic-gate * 14497c478bd9Sstevel@tonic-gate * Handle a help request message (RDR_CONF_HELP). 14507c478bd9Sstevel@tonic-gate */ 14517c478bd9Sstevel@tonic-gate static int 14527c478bd9Sstevel@tonic-gate dcs_help(rdr_msg_hdr_t *hdr, cfga_params_t *param) 14537c478bd9Sstevel@tonic-gate { 14547c478bd9Sstevel@tonic-gate session_t *sp; 14557c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 14567c478bd9Sstevel@tonic-gate help_params_t *op_data; 14577c478bd9Sstevel@tonic-gate struct cfga_msg local_msg_cb; 14587c478bd9Sstevel@tonic-gate int cfga_status; 14597c478bd9Sstevel@tonic-gate int snd_status; 14607c478bd9Sstevel@tonic-gate char *err_str; 14617c478bd9Sstevel@tonic-gate static char *op_name = "config_help"; 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate assert(hdr); 14657c478bd9Sstevel@tonic-gate assert(param); 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate /* get the current session information */ 14687c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 14697c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 14707c478bd9Sstevel@tonic-gate return (-1); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate op_data = ¶m->help; 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate /* make sure we have a session established */ 14767c478bd9Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 14777c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 14787c478bd9Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 14797c478bd9Sstevel@tonic-gate return (-1); 14807c478bd9Sstevel@tonic-gate } 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate /* initialize local message callback */ 14837c478bd9Sstevel@tonic-gate local_msg_cb.message_routine = dcs_message_callback; 14847c478bd9Sstevel@tonic-gate local_msg_cb.appdata_ptr = op_data->msgp; 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate /* 14897c478bd9Sstevel@tonic-gate * Call into libcfgadm 14907c478bd9Sstevel@tonic-gate */ 14917c478bd9Sstevel@tonic-gate ses_abort_enable(); 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate cfga_status = config_help(op_data->num_ap_ids, op_data->ap_ids, 14947c478bd9Sstevel@tonic-gate &local_msg_cb, op_data->options, op_data->flags); 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate ses_abort_disable(); 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate /* 15017c478bd9Sstevel@tonic-gate * Log any libcfgadm errors at a low priority level. 15027c478bd9Sstevel@tonic-gate * Since a help request does not modify the system 15037c478bd9Sstevel@tonic-gate * in any way, we do not need to worry about these 15047c478bd9Sstevel@tonic-gate * errors here on the host. 15057c478bd9Sstevel@tonic-gate */ 15067c478bd9Sstevel@tonic-gate if (cfga_status != CFGA_OK) { 15077c478bd9Sstevel@tonic-gate err_str = dcs_cfga_str(NULL, cfga_status); 15087c478bd9Sstevel@tonic-gate if (err_str) { 15097c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_INFO, DCS_CFGA_ERR, op_name, err_str); 15107c478bd9Sstevel@tonic-gate free((void *)err_str); 15117c478bd9Sstevel@tonic-gate } 15127c478bd9Sstevel@tonic-gate } 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate /* prepare header information */ 15157c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 15167c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_HELP; 15177c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 15187c478bd9Sstevel@tonic-gate reply_hdr.status = cfga_status; 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 15217c478bd9Sstevel@tonic-gate 15227c478bd9Sstevel@tonic-gate /* send the message */ 15237c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 15267c478bd9Sstevel@tonic-gate abort_handler(); 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 15307c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate /* 15387c478bd9Sstevel@tonic-gate * dcs_ap_id_cmp: 15397c478bd9Sstevel@tonic-gate * 15407c478bd9Sstevel@tonic-gate * Handle an attachment point comparison request message (RDR_AP_ID_CMP). 15417c478bd9Sstevel@tonic-gate */ 15427c478bd9Sstevel@tonic-gate static int 15437c478bd9Sstevel@tonic-gate dcs_ap_id_cmp(rdr_msg_hdr_t *hdr, cfga_params_t *param) 15447c478bd9Sstevel@tonic-gate { 15457c478bd9Sstevel@tonic-gate session_t *sp; 15467c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 15477c478bd9Sstevel@tonic-gate ap_id_cmp_params_t *op_data; 15487c478bd9Sstevel@tonic-gate int snd_status; 15497c478bd9Sstevel@tonic-gate int cmp_result; 15507c478bd9Sstevel@tonic-gate static char *op_name = "config_ap_id_cmp"; 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate assert(hdr); 15547c478bd9Sstevel@tonic-gate assert(param); 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate /* get the current session information */ 15577c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 15587c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 15597c478bd9Sstevel@tonic-gate return (-1); 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate op_data = ¶m->cmp; 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate /* make sure we have a session established */ 15657c478bd9Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 15667c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 15677c478bd9Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 15687c478bd9Sstevel@tonic-gate return (-1); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate /* 15747c478bd9Sstevel@tonic-gate * Call into libcfgadm 15757c478bd9Sstevel@tonic-gate */ 15767c478bd9Sstevel@tonic-gate ses_abort_enable(); 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate cmp_result = config_ap_id_cmp(op_data->ap_log_id1, op_data->ap_log_id2); 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate ses_abort_disable(); 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate /* prepare header information */ 15857c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 15867c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_AP_ID_CMP; 15877c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate /* 15907c478bd9Sstevel@tonic-gate * Return result of comparison as error code. 15917c478bd9Sstevel@tonic-gate * Since all values are valid, it is impossible 15927c478bd9Sstevel@tonic-gate * to report an error. 15937c478bd9Sstevel@tonic-gate */ 15947c478bd9Sstevel@tonic-gate reply_hdr.status = cmp_result; 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate /* send the message */ 15997c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 16027c478bd9Sstevel@tonic-gate abort_handler(); 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 16067c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate /* 16147c478bd9Sstevel@tonic-gate * dcs_abort_cmd: 16157c478bd9Sstevel@tonic-gate * 16167c478bd9Sstevel@tonic-gate * Handle an abort request message (RDR_CONF_ABORT_CMD). 16177c478bd9Sstevel@tonic-gate */ 16187c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16197c478bd9Sstevel@tonic-gate static int 16207c478bd9Sstevel@tonic-gate dcs_abort_cmd(rdr_msg_hdr_t *hdr, cfga_params_t *param) 16217c478bd9Sstevel@tonic-gate { 16227c478bd9Sstevel@tonic-gate session_t *sp; 16237c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 16247c478bd9Sstevel@tonic-gate abort_cmd_params_t *op_data; 16257c478bd9Sstevel@tonic-gate int op_status = RDR_SUCCESS; 16267c478bd9Sstevel@tonic-gate int snd_status; 16277c478bd9Sstevel@tonic-gate static char *op_name = "abort command"; 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate assert(hdr); 16317c478bd9Sstevel@tonic-gate assert(param); 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate /* get the current session information */ 16347c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 16357c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 16367c478bd9Sstevel@tonic-gate return (-1); 16377c478bd9Sstevel@tonic-gate } 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate op_data = (abort_cmd_params_t *)param; 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate op_status = ses_abort(op_data->session_id); 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate if (op_status == -1) { 16447c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_ABORT_ERR, op_data->session_id); 16457c478bd9Sstevel@tonic-gate } 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate /* prepare header information */ 16487c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 16497c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_CONF_ABORT_CMD; 16507c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 16517c478bd9Sstevel@tonic-gate reply_hdr.status = op_status; 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 16547c478bd9Sstevel@tonic-gate 16557c478bd9Sstevel@tonic-gate /* send the message */ 16567c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 16597c478bd9Sstevel@tonic-gate abort_handler(); 16607c478bd9Sstevel@tonic-gate } 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 16637c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 16647c478bd9Sstevel@tonic-gate } 16657c478bd9Sstevel@tonic-gate 16667c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate /* 16737c478bd9Sstevel@tonic-gate * dcs_rsrc_info: 16747c478bd9Sstevel@tonic-gate * 16757c478bd9Sstevel@tonic-gate * Handle a resource info request message (RDR_RSRC_INFO). 16767c478bd9Sstevel@tonic-gate */ 16777c478bd9Sstevel@tonic-gate static int 16787c478bd9Sstevel@tonic-gate dcs_rsrc_info(rdr_msg_hdr_t *hdr, cfga_params_t *param) 16797c478bd9Sstevel@tonic-gate { 16807c478bd9Sstevel@tonic-gate session_t *sp; 16817c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 16827c478bd9Sstevel@tonic-gate rsrc_info_params_t *op_data; 16837c478bd9Sstevel@tonic-gate int rsrc_status; 16847c478bd9Sstevel@tonic-gate int snd_status; 16857c478bd9Sstevel@tonic-gate static char *op_name = "resource info init"; 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate assert(hdr); 16887c478bd9Sstevel@tonic-gate assert(param); 16897c478bd9Sstevel@tonic-gate 16907c478bd9Sstevel@tonic-gate /* get the current session information */ 16917c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 16927c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 16937c478bd9Sstevel@tonic-gate return (-1); 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate op_data = (rsrc_info_params_t *)¶m->rsrc_info; 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate /* make sure we have a session established */ 16997c478bd9Sstevel@tonic-gate if (sp->state != DCS_SES_ESTBL) { 17007c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_NO_SES_ESTBL, op_name); 17017c478bd9Sstevel@tonic-gate ses_close(DCS_NO_SES_ERR); 17027c478bd9Sstevel@tonic-gate return (-1); 17037c478bd9Sstevel@tonic-gate } 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_PENDING; 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate /* 17087c478bd9Sstevel@tonic-gate * Request resource info data. 17097c478bd9Sstevel@tonic-gate */ 17107c478bd9Sstevel@tonic-gate ses_abort_enable(); 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate rsrc_status = ri_init(op_data->num_ap_ids, op_data->ap_ids, 17137c478bd9Sstevel@tonic-gate op_data->flags, &op_data->hdl); 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate ses_abort_disable(); 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate /* log errors */ 17207c478bd9Sstevel@tonic-gate if (rsrc_status != RI_SUCCESS) { 17217c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_RSRC_ERR, rsrc_status); 17227c478bd9Sstevel@tonic-gate } 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate /* prepare header information */ 17257c478bd9Sstevel@tonic-gate init_msg(&reply_hdr); 17267c478bd9Sstevel@tonic-gate reply_hdr.message_opcode = RDR_RSRC_INFO; 17277c478bd9Sstevel@tonic-gate reply_hdr.data_type = RDR_REPLY; 17287c478bd9Sstevel@tonic-gate reply_hdr.status = rsrc_status; 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &reply_hdr); 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate /* send the message */ 17337c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &reply_hdr, param, DCS_SND_TIMEOUT); 17347c478bd9Sstevel@tonic-gate 17357c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 17367c478bd9Sstevel@tonic-gate abort_handler(); 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 17407c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 17417c478bd9Sstevel@tonic-gate } 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate ri_fini(op_data->hdl); 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate return ((snd_status != RDR_OK) ? -1 : 0); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate /* 17507c478bd9Sstevel@tonic-gate * dcs_unknown_op: 17517c478bd9Sstevel@tonic-gate * 17527c478bd9Sstevel@tonic-gate * Handle all unknown requests. 17537c478bd9Sstevel@tonic-gate */ 17547c478bd9Sstevel@tonic-gate /* ARGSUSED */ 17557c478bd9Sstevel@tonic-gate static int 17567c478bd9Sstevel@tonic-gate dcs_unknown_op(rdr_msg_hdr_t *hdr, cfga_params_t *param) 17577c478bd9Sstevel@tonic-gate { 17587c478bd9Sstevel@tonic-gate session_t *sp; 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate assert(hdr); 17627c478bd9Sstevel@tonic-gate assert(param); 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate assert(hdr); 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate /* get the current session information */ 17677c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 17687c478bd9Sstevel@tonic-gate ses_close(DCS_ERROR); 17697c478bd9Sstevel@tonic-gate return (-1); 17707c478bd9Sstevel@tonic-gate } 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_UNKNOWN_OP, hdr->message_opcode); 17737c478bd9Sstevel@tonic-gate 17747c478bd9Sstevel@tonic-gate sp->state = DCS_CONF_DONE; 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate return (-1); 17777c478bd9Sstevel@tonic-gate } 17787c478bd9Sstevel@tonic-gate 17797c478bd9Sstevel@tonic-gate 17807c478bd9Sstevel@tonic-gate /* 17817c478bd9Sstevel@tonic-gate * dcs_confirm_callback: 17827c478bd9Sstevel@tonic-gate * 17837c478bd9Sstevel@tonic-gate * Perform a confirm callback and wait for the reply. As defined 17847c478bd9Sstevel@tonic-gate * in the config_admin(3CFGADM) man page, 1 is returned if the 17857c478bd9Sstevel@tonic-gate * operation should be allowed to continue and 0 otherwise. 17867c478bd9Sstevel@tonic-gate */ 17877c478bd9Sstevel@tonic-gate static int 17887c478bd9Sstevel@tonic-gate dcs_confirm_callback(void *appdata_ptr, const char *message) 17897c478bd9Sstevel@tonic-gate { 17907c478bd9Sstevel@tonic-gate session_t *sp; 17917c478bd9Sstevel@tonic-gate rdr_msg_hdr_t req_hdr; 17927c478bd9Sstevel@tonic-gate cfga_params_t req_data; 17937c478bd9Sstevel@tonic-gate struct cfga_confirm *cb_data; 17947c478bd9Sstevel@tonic-gate rdr_msg_hdr_t reply_hdr; 17957c478bd9Sstevel@tonic-gate cfga_params_t reply_data; 17967c478bd9Sstevel@tonic-gate int snd_status; 17977c478bd9Sstevel@tonic-gate int rcv_status; 17987c478bd9Sstevel@tonic-gate static char *op_name = "confirm callback"; 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate /* sanity check */ 18027c478bd9Sstevel@tonic-gate if (appdata_ptr == NULL) { 18037c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18047c478bd9Sstevel@tonic-gate return (0); 18057c478bd9Sstevel@tonic-gate } 18067c478bd9Sstevel@tonic-gate 18077c478bd9Sstevel@tonic-gate /* get the current session information */ 18087c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 18097c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18107c478bd9Sstevel@tonic-gate return (0); 18117c478bd9Sstevel@tonic-gate } 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate cb_data = (struct cfga_confirm *)appdata_ptr; 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate /* prepare header information */ 18167c478bd9Sstevel@tonic-gate init_msg(&req_hdr); 18177c478bd9Sstevel@tonic-gate req_hdr.message_opcode = RDR_CONF_CONFIRM_CALLBACK; 18187c478bd9Sstevel@tonic-gate req_hdr.data_type = RDR_REQUEST; 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate /* prepare confirm callback specific data */ 18217c478bd9Sstevel@tonic-gate (void) memset(&req_data, 0, sizeof (req_data)); 18227c478bd9Sstevel@tonic-gate req_data.conf_cb.confp = cb_data; 18237c478bd9Sstevel@tonic-gate req_data.conf_cb.message = (char *)message; 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &req_hdr); 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate /* send the message */ 18287c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &req_hdr, &req_data, DCS_SND_TIMEOUT); 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 18317c478bd9Sstevel@tonic-gate abort_handler(); 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 18357c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18367c478bd9Sstevel@tonic-gate return (0); 18377c478bd9Sstevel@tonic-gate } 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate /* 18407c478bd9Sstevel@tonic-gate * Wait for response 18417c478bd9Sstevel@tonic-gate */ 18427c478bd9Sstevel@tonic-gate rcv_status = rdr_rcv_msg(sp->fd, &reply_hdr, &reply_data, 18437c478bd9Sstevel@tonic-gate DCS_RCV_CB_TIMEOUT); 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate if (rcv_status != RDR_OK) { 18467c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 18477c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18487c478bd9Sstevel@tonic-gate return (0); 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate /* 18527c478bd9Sstevel@tonic-gate * Perform several checks to see if we have a 18537c478bd9Sstevel@tonic-gate * valid response to the confirm callback. 18547c478bd9Sstevel@tonic-gate */ 18557c478bd9Sstevel@tonic-gate if (invalid_msg(&reply_hdr)) { 18567c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 18577c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18587c478bd9Sstevel@tonic-gate return (0); 18597c478bd9Sstevel@tonic-gate } 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate /* check the opcode and type */ 18627c478bd9Sstevel@tonic-gate if ((reply_hdr.message_opcode != RDR_CONF_CONFIRM_CALLBACK) || 18637c478bd9Sstevel@tonic-gate (reply_hdr.data_type != RDR_REPLY)) { 18647c478bd9Sstevel@tonic-gate DCS_DBG(DBG_MSG, "bad opcode or message type"); 18657c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 18667c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18677c478bd9Sstevel@tonic-gate return (0); 18687c478bd9Sstevel@tonic-gate } 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_RECEIVE, &reply_hdr); 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate /* check for incorrect callback id */ 18737c478bd9Sstevel@tonic-gate if (reply_data.conf_cb.confp->confirm != cb_data->confirm) { 18747c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_MSG_INVAL); 18757c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_CONF_CB_ERR); 18767c478bd9Sstevel@tonic-gate return (0); 18777c478bd9Sstevel@tonic-gate } 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate /* 18807c478bd9Sstevel@tonic-gate * Got back valid response: return the user's answer 18817c478bd9Sstevel@tonic-gate */ 18827c478bd9Sstevel@tonic-gate return (reply_data.conf_cb.response); 18837c478bd9Sstevel@tonic-gate } 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate /* 18877c478bd9Sstevel@tonic-gate * dcs_message_callback: 18887c478bd9Sstevel@tonic-gate * 18897c478bd9Sstevel@tonic-gate * Perform a message callback to display a string to the user. 18907c478bd9Sstevel@tonic-gate * 18917c478bd9Sstevel@tonic-gate * Note: There is no documentation about possible return values 18927c478bd9Sstevel@tonic-gate * for the message callback. It is assumed that the value returned 18937c478bd9Sstevel@tonic-gate * is ignored, so 0 is returned for all cases. 18947c478bd9Sstevel@tonic-gate */ 18957c478bd9Sstevel@tonic-gate static int 18967c478bd9Sstevel@tonic-gate dcs_message_callback(void *appdata_ptr, const char *message) 18977c478bd9Sstevel@tonic-gate { 18987c478bd9Sstevel@tonic-gate session_t *sp; 18997c478bd9Sstevel@tonic-gate rdr_msg_hdr_t req_hdr; 19007c478bd9Sstevel@tonic-gate cfga_params_t req_data; 19017c478bd9Sstevel@tonic-gate struct cfga_msg *cb_data; 19027c478bd9Sstevel@tonic-gate int snd_status; 19037c478bd9Sstevel@tonic-gate static char *op_name = "message callback"; 19047c478bd9Sstevel@tonic-gate 19057c478bd9Sstevel@tonic-gate 19067c478bd9Sstevel@tonic-gate /* sanity check */ 19077c478bd9Sstevel@tonic-gate if (appdata_ptr == NULL) { 19087c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 19097c478bd9Sstevel@tonic-gate return (0); 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate /* get the current session information */ 19137c478bd9Sstevel@tonic-gate if ((sp = curr_ses()) == NULL) { 19147c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 19157c478bd9Sstevel@tonic-gate return (0); 19167c478bd9Sstevel@tonic-gate } 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate cb_data = (struct cfga_msg *)appdata_ptr; 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate /* prepare header information */ 19217c478bd9Sstevel@tonic-gate init_msg(&req_hdr); 19227c478bd9Sstevel@tonic-gate req_hdr.message_opcode = RDR_CONF_MSG_CALLBACK; 19237c478bd9Sstevel@tonic-gate req_hdr.data_type = RDR_REQUEST; 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate /* prepare message callback specific data */ 19267c478bd9Sstevel@tonic-gate (void) memset(&req_data, 0, sizeof (req_data)); 19277c478bd9Sstevel@tonic-gate req_data.msg_cb.msgp = cb_data; 19287c478bd9Sstevel@tonic-gate req_data.msg_cb.message = (char *)message; 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate PRINT_MSG_DBG(DCS_SEND, &req_hdr); 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate /* send the message */ 19337c478bd9Sstevel@tonic-gate snd_status = rdr_snd_msg(sp->fd, &req_hdr, (cfga_params_t *)&req_data, 19347c478bd9Sstevel@tonic-gate DCS_SND_TIMEOUT); 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate if (snd_status == RDR_ABORTED) { 19377c478bd9Sstevel@tonic-gate abort_handler(); 19387c478bd9Sstevel@tonic-gate } 19397c478bd9Sstevel@tonic-gate 19407c478bd9Sstevel@tonic-gate if (snd_status != RDR_OK) { 19417c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_ERR, DCS_OP_REPLY_ERR, op_name); 19427c478bd9Sstevel@tonic-gate dcs_log_msg(LOG_NOTICE, DCS_MSG_CB_ERR); 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate return (0); 19467c478bd9Sstevel@tonic-gate } 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate 19497c478bd9Sstevel@tonic-gate /* 19507c478bd9Sstevel@tonic-gate * resolve_version: 19517c478bd9Sstevel@tonic-gate * 19527c478bd9Sstevel@tonic-gate * Consult the list of supported versions and find the highest supported 19537c478bd9Sstevel@tonic-gate * version that is less than or equal to the version requested in the 19547c478bd9Sstevel@tonic-gate * parameters. This assumes that the list of supported versions is ordered 19557c478bd9Sstevel@tonic-gate * so that the highest supported version is the first element, and that 19567c478bd9Sstevel@tonic-gate * the versions are strictly decreasing. 19577c478bd9Sstevel@tonic-gate */ 19587c478bd9Sstevel@tonic-gate static dcs_ver_t 19597c478bd9Sstevel@tonic-gate resolve_version(ushort_t req_major, ushort_t req_minor) 19607c478bd9Sstevel@tonic-gate { 19617c478bd9Sstevel@tonic-gate int i; 19627c478bd9Sstevel@tonic-gate dcs_ver_t act_ver; 19637c478bd9Sstevel@tonic-gate int num_vers; 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate num_vers = sizeof (ver_supp) / sizeof (*ver_supp); 19677c478bd9Sstevel@tonic-gate 19687c478bd9Sstevel@tonic-gate /* default to the lowest version */ 19697c478bd9Sstevel@tonic-gate act_ver = ver_supp[num_vers - 1]; 19707c478bd9Sstevel@tonic-gate 19717c478bd9Sstevel@tonic-gate for (i = 0; i < num_vers; i++) { 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate if (req_major == ver_supp[i].major) { 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate if (req_minor >= ver_supp[i].minor) { 19767c478bd9Sstevel@tonic-gate /* 19777c478bd9Sstevel@tonic-gate * The major version matches and the 19787c478bd9Sstevel@tonic-gate * minor version either matches, or 19797c478bd9Sstevel@tonic-gate * is the best match that we have. 19807c478bd9Sstevel@tonic-gate */ 19817c478bd9Sstevel@tonic-gate act_ver = ver_supp[i]; 19827c478bd9Sstevel@tonic-gate break; 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate 19857c478bd9Sstevel@tonic-gate } else if (req_major > ver_supp[i].major) { 19867c478bd9Sstevel@tonic-gate /* 19877c478bd9Sstevel@tonic-gate * The requested major version is larger than 19887c478bd9Sstevel@tonic-gate * the current version we are checking. There 19897c478bd9Sstevel@tonic-gate * is not going to be a better match. 19907c478bd9Sstevel@tonic-gate */ 19917c478bd9Sstevel@tonic-gate act_ver = ver_supp[i]; 19927c478bd9Sstevel@tonic-gate break; 19937c478bd9Sstevel@tonic-gate } 19947c478bd9Sstevel@tonic-gate } 19957c478bd9Sstevel@tonic-gate 19967c478bd9Sstevel@tonic-gate DCS_DBG(DBG_SES, "requested ver: %d.%d, closest match: %d.%d", 19977c478bd9Sstevel@tonic-gate req_major, req_minor, act_ver.major, act_ver.minor); 19987c478bd9Sstevel@tonic-gate 19997c478bd9Sstevel@tonic-gate return (act_ver); 20007c478bd9Sstevel@tonic-gate } 20017c478bd9Sstevel@tonic-gate 20027c478bd9Sstevel@tonic-gate 20037c478bd9Sstevel@tonic-gate /* 20047c478bd9Sstevel@tonic-gate * filter_list_data: 20057c478bd9Sstevel@tonic-gate * 20067c478bd9Sstevel@tonic-gate * Check a list of cfga_list_data_t structures to filter out the ones 20077c478bd9Sstevel@tonic-gate * that don't have other-read permissions. All valid entries are placed 20087c478bd9Sstevel@tonic-gate * at the beginning of the array and the count of entries is updated. 20097c478bd9Sstevel@tonic-gate */ 20107c478bd9Sstevel@tonic-gate static void 20117c478bd9Sstevel@tonic-gate filter_list_data(int perm, int *nlistp, cfga_list_data_t *linfo) 20127c478bd9Sstevel@tonic-gate { 20137c478bd9Sstevel@tonic-gate int num_aps; 20147c478bd9Sstevel@tonic-gate int num_aps_ret; 20157c478bd9Sstevel@tonic-gate int curr_ap; 20167c478bd9Sstevel@tonic-gate int next_aval; 20177c478bd9Sstevel@tonic-gate int end_block; 20187c478bd9Sstevel@tonic-gate int block_size; 20197c478bd9Sstevel@tonic-gate struct stat ap_info; 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate DCS_DBG(DBG_MSG, "list access = %s", (perm == RDR_PRIVILEGED) ? 20237c478bd9Sstevel@tonic-gate "RDR_PRIVILEGED" : "RDR_NOT_PRIVILEGED"); 20247c478bd9Sstevel@tonic-gate 20257c478bd9Sstevel@tonic-gate /* 20267c478bd9Sstevel@tonic-gate * Check if the user has priviledged access 20277c478bd9Sstevel@tonic-gate * to view all attachment points 20287c478bd9Sstevel@tonic-gate */ 20297c478bd9Sstevel@tonic-gate if (perm == RDR_PRIVILEGED) { 20307c478bd9Sstevel@tonic-gate return; 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate 20337c478bd9Sstevel@tonic-gate if (*nlistp < 0) { 20347c478bd9Sstevel@tonic-gate *nlistp = 0; 20357c478bd9Sstevel@tonic-gate } 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate /* 20387c478bd9Sstevel@tonic-gate * No priviledged access, check each attachment point to 20397c478bd9Sstevel@tonic-gate * see if the user has access (other:read) to view it. 20407c478bd9Sstevel@tonic-gate */ 20417c478bd9Sstevel@tonic-gate num_aps = *nlistp; 20427c478bd9Sstevel@tonic-gate next_aval = 0; 20437c478bd9Sstevel@tonic-gate num_aps_ret = 0; 20447c478bd9Sstevel@tonic-gate curr_ap = 0; 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate /* 20477c478bd9Sstevel@tonic-gate * Use a simple algorithm to compact the array so that 20487c478bd9Sstevel@tonic-gate * all attachment points that can be viewed are at the 20497c478bd9Sstevel@tonic-gate * beginning of the array. Adjust the count of the 20507c478bd9Sstevel@tonic-gate * attachment points accordingly. 20517c478bd9Sstevel@tonic-gate */ 20527c478bd9Sstevel@tonic-gate while (curr_ap < num_aps) { 20537c478bd9Sstevel@tonic-gate 20547c478bd9Sstevel@tonic-gate stat(linfo[curr_ap].ap_phys_id, &ap_info); 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate /* check for unrestricted read permission */ 20577c478bd9Sstevel@tonic-gate if (ap_info.st_mode & S_IROTH) { 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate end_block = curr_ap + 1; 20607c478bd9Sstevel@tonic-gate 20617c478bd9Sstevel@tonic-gate /* 20627c478bd9Sstevel@tonic-gate * Check if this is the beginning of a 20637c478bd9Sstevel@tonic-gate * block of consecutive ap ids that can 20647c478bd9Sstevel@tonic-gate * be returned. 20657c478bd9Sstevel@tonic-gate */ 20667c478bd9Sstevel@tonic-gate while (end_block < num_aps) { 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate stat(linfo[end_block].ap_phys_id, &ap_info); 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate /* search until the end of the block */ 20717c478bd9Sstevel@tonic-gate if (ap_info.st_mode & S_IROTH) { 20727c478bd9Sstevel@tonic-gate end_block++; 20737c478bd9Sstevel@tonic-gate } else { 20747c478bd9Sstevel@tonic-gate break; 20757c478bd9Sstevel@tonic-gate } 20767c478bd9Sstevel@tonic-gate } 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate block_size = end_block - curr_ap; 20797c478bd9Sstevel@tonic-gate 20807c478bd9Sstevel@tonic-gate /* make sure a copy is necessary */ 20817c478bd9Sstevel@tonic-gate if (curr_ap != next_aval) { 20827c478bd9Sstevel@tonic-gate 20837c478bd9Sstevel@tonic-gate /* copy the block of ap ids all at once */ 20847c478bd9Sstevel@tonic-gate (void) memmove(&linfo[next_aval], 20857c478bd9Sstevel@tonic-gate &linfo[curr_ap], 20867c478bd9Sstevel@tonic-gate block_size * sizeof (cfga_list_data_t)); 20877c478bd9Sstevel@tonic-gate } 20887c478bd9Sstevel@tonic-gate 20897c478bd9Sstevel@tonic-gate /* move past the copied block */ 20907c478bd9Sstevel@tonic-gate next_aval += block_size; 20917c478bd9Sstevel@tonic-gate curr_ap = end_block; 20927c478bd9Sstevel@tonic-gate 20937c478bd9Sstevel@tonic-gate num_aps_ret += block_size; 20947c478bd9Sstevel@tonic-gate } else { 20957c478bd9Sstevel@tonic-gate curr_ap++; 20967c478bd9Sstevel@tonic-gate } 20977c478bd9Sstevel@tonic-gate } 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate DCS_DBG(DBG_ALL, "filtered %d of %d ap ids", (*nlistp - num_aps_ret), 21007c478bd9Sstevel@tonic-gate *nlistp); 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate /* 21037c478bd9Sstevel@tonic-gate * return the number of aps that have the correct 21047c478bd9Sstevel@tonic-gate * access permissions. 21057c478bd9Sstevel@tonic-gate */ 21067c478bd9Sstevel@tonic-gate *nlistp = num_aps_ret; 21077c478bd9Sstevel@tonic-gate } 21087c478bd9Sstevel@tonic-gate 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate /* 21117c478bd9Sstevel@tonic-gate * generate_sort_order: 21127c478bd9Sstevel@tonic-gate * 21137c478bd9Sstevel@tonic-gate * Determine the sort order of an array of cfga_list_data_t structures 21147c478bd9Sstevel@tonic-gate * and create an array of rdr_list_t structures that contain the original 21157c478bd9Sstevel@tonic-gate * elements tagged with the sort order. 21167c478bd9Sstevel@tonic-gate * 21177c478bd9Sstevel@tonic-gate * This function is used to eliminate unnecessary network traffic that 21187c478bd9Sstevel@tonic-gate * might occur if the client needs the output of config_list_ext(3CFGADM) 21197c478bd9Sstevel@tonic-gate * sorted. Since a comparison is performed in a platform specific manner 21207c478bd9Sstevel@tonic-gate * using config_ap_id_cmp(3CFGADM), a client must establish a new session 21217c478bd9Sstevel@tonic-gate * for each comparison. For a long lists of attachment points, this can 21227c478bd9Sstevel@tonic-gate * slow down a simple list_ext operation significantly. With the sort 21237c478bd9Sstevel@tonic-gate * information included in the array of rdr_list_t structures, the client 21247c478bd9Sstevel@tonic-gate * can perform the sort operation locally, thus eliminating a great deal 21257c478bd9Sstevel@tonic-gate * of network traffic. 21267c478bd9Sstevel@tonic-gate */ 21277c478bd9Sstevel@tonic-gate static rdr_list_t * 21287c478bd9Sstevel@tonic-gate generate_sort_order(cfga_list_data_t *listp, int nlist) 21297c478bd9Sstevel@tonic-gate { 21307c478bd9Sstevel@tonic-gate int curr_ap; 21317c478bd9Sstevel@tonic-gate rdr_list_t *datalp; 21327c478bd9Sstevel@tonic-gate cfga_list_data_t *sortlp; 21337c478bd9Sstevel@tonic-gate cfga_list_data_t *match; 21347c478bd9Sstevel@tonic-gate 21357c478bd9Sstevel@tonic-gate 21367c478bd9Sstevel@tonic-gate assert(listp); 21377c478bd9Sstevel@tonic-gate 21387c478bd9Sstevel@tonic-gate if (nlist <= 0) { 21397c478bd9Sstevel@tonic-gate return (NULL); 21407c478bd9Sstevel@tonic-gate } 21417c478bd9Sstevel@tonic-gate 21427c478bd9Sstevel@tonic-gate /* create our new array */ 21437c478bd9Sstevel@tonic-gate datalp = (rdr_list_t *)malloc(nlist * sizeof (rdr_list_t)); 21447c478bd9Sstevel@tonic-gate 21457c478bd9Sstevel@tonic-gate if (datalp == NULL) { 21467c478bd9Sstevel@tonic-gate return (NULL); 21477c478bd9Sstevel@tonic-gate } 21487c478bd9Sstevel@tonic-gate 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate /* copy over the elements, preserving the original order */ 21517c478bd9Sstevel@tonic-gate for (curr_ap = 0; curr_ap < nlist; curr_ap++) { 21527c478bd9Sstevel@tonic-gate datalp[curr_ap].ap_id_info = listp[curr_ap]; 21537c478bd9Sstevel@tonic-gate } 21547c478bd9Sstevel@tonic-gate 21557c478bd9Sstevel@tonic-gate /* handle a one element list */ 21567c478bd9Sstevel@tonic-gate if (nlist == 1) { 21577c478bd9Sstevel@tonic-gate datalp[0].sort_order = 0; 21587c478bd9Sstevel@tonic-gate return (datalp); 21597c478bd9Sstevel@tonic-gate } 21607c478bd9Sstevel@tonic-gate 21617c478bd9Sstevel@tonic-gate /* sort the cfga_list_data_t array */ 21627c478bd9Sstevel@tonic-gate qsort(listp, nlist, sizeof (listp[0]), ldata_compare); 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate sortlp = listp; 21657c478bd9Sstevel@tonic-gate 21667c478bd9Sstevel@tonic-gate /* process each item in the original list */ 21677c478bd9Sstevel@tonic-gate for (curr_ap = 0; curr_ap < nlist; curr_ap++) { 21687c478bd9Sstevel@tonic-gate 21697c478bd9Sstevel@tonic-gate /* look up the sort order in the sorted list */ 21707c478bd9Sstevel@tonic-gate match = bsearch(&datalp[curr_ap].ap_id_info, sortlp, 21717c478bd9Sstevel@tonic-gate nlist, sizeof (cfga_list_data_t), ldata_compare); 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate /* found a match */ 21747c478bd9Sstevel@tonic-gate if (match != NULL) { 21757c478bd9Sstevel@tonic-gate datalp[curr_ap].sort_order = match - sortlp; 21767c478bd9Sstevel@tonic-gate } else { 21777c478bd9Sstevel@tonic-gate /* 21787c478bd9Sstevel@tonic-gate * Should never get here. Since we did a 21797c478bd9Sstevel@tonic-gate * direct copy of the array, we should always 21807c478bd9Sstevel@tonic-gate * be able to find the ap id that we were 21817c478bd9Sstevel@tonic-gate * looking for. 21827c478bd9Sstevel@tonic-gate */ 21837c478bd9Sstevel@tonic-gate DCS_DBG(DBG_ALL, "could not find a matching " 21847c478bd9Sstevel@tonic-gate "ap id in the sorted list"); 21857c478bd9Sstevel@tonic-gate datalp[curr_ap].sort_order = 0; 21867c478bd9Sstevel@tonic-gate } 21877c478bd9Sstevel@tonic-gate } 21887c478bd9Sstevel@tonic-gate 21897c478bd9Sstevel@tonic-gate return (datalp); 21907c478bd9Sstevel@tonic-gate } 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate 21937c478bd9Sstevel@tonic-gate /* 21947c478bd9Sstevel@tonic-gate * ldata_compare: 21957c478bd9Sstevel@tonic-gate * 21967c478bd9Sstevel@tonic-gate * Compare the two inputs to produce a strcmp(3C) style result. It uses 21977c478bd9Sstevel@tonic-gate * config_ap_id_cmp(3CFGADM) to perform the comparison. 21987c478bd9Sstevel@tonic-gate * 21997c478bd9Sstevel@tonic-gate * This function is passed to qsort(3C) in generate_sort_order() to sort a 22007c478bd9Sstevel@tonic-gate * list of attachment points. 22017c478bd9Sstevel@tonic-gate */ 22027c478bd9Sstevel@tonic-gate static int 22037c478bd9Sstevel@tonic-gate ldata_compare(const void *ap1, const void *ap2) 22047c478bd9Sstevel@tonic-gate { 22057c478bd9Sstevel@tonic-gate cfga_list_data_t *ap_id1; 22067c478bd9Sstevel@tonic-gate cfga_list_data_t *ap_id2; 22077c478bd9Sstevel@tonic-gate 22087c478bd9Sstevel@tonic-gate ap_id1 = (cfga_list_data_t *)ap1; 22097c478bd9Sstevel@tonic-gate ap_id2 = (cfga_list_data_t *)ap2; 22107c478bd9Sstevel@tonic-gate 22117c478bd9Sstevel@tonic-gate return (config_ap_id_cmp(ap_id1->ap_log_id, ap_id2->ap_log_id)); 22127c478bd9Sstevel@tonic-gate } 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate 22157c478bd9Sstevel@tonic-gate /* 22167c478bd9Sstevel@tonic-gate * basename: 22177c478bd9Sstevel@tonic-gate * 22187c478bd9Sstevel@tonic-gate * Find short path name of a full path name. If a short path name 22197c478bd9Sstevel@tonic-gate * is passed in, the original pointer is returned. 22207c478bd9Sstevel@tonic-gate */ 22217c478bd9Sstevel@tonic-gate static char * 22227c478bd9Sstevel@tonic-gate basename(char *cp) 22237c478bd9Sstevel@tonic-gate { 22247c478bd9Sstevel@tonic-gate char *sp; 22257c478bd9Sstevel@tonic-gate 22267c478bd9Sstevel@tonic-gate if ((sp = strrchr(cp, '/')) != NULL) { 22277c478bd9Sstevel@tonic-gate return (sp + 1); 22287c478bd9Sstevel@tonic-gate } 22297c478bd9Sstevel@tonic-gate 22307c478bd9Sstevel@tonic-gate return (cp); 22317c478bd9Sstevel@tonic-gate } 22322eaee53eSmb158278 22332eaee53eSmb158278 /* 22342eaee53eSmb158278 * is_socket: 22352eaee53eSmb158278 * 22362eaee53eSmb158278 * determine if fd represents a socket file type. 22372eaee53eSmb158278 */ 22382eaee53eSmb158278 static boolean_t 22392eaee53eSmb158278 is_socket(int fd) 22402eaee53eSmb158278 { 22412eaee53eSmb158278 struct stat statb; 22422eaee53eSmb158278 if (fstat(fd, &statb) < 0) { 22432eaee53eSmb158278 return (B_FALSE); 22442eaee53eSmb158278 } 22452eaee53eSmb158278 return (S_ISSOCK(statb.st_mode)); 22462eaee53eSmb158278 } 22473a3e8d7aSmb158278 22483a3e8d7aSmb158278 /* 22493a3e8d7aSmb158278 * has_dcs_token 22503a3e8d7aSmb158278 * 22513a3e8d7aSmb158278 * Look for "?port [sun-dr|665]" in input buf. 22523a3e8d7aSmb158278 * Assume only a single thread calls here. 22533a3e8d7aSmb158278 */ 22543a3e8d7aSmb158278 static boolean_t 22553a3e8d7aSmb158278 has_dcs_token(char *buf) 22563a3e8d7aSmb158278 { 22573a3e8d7aSmb158278 char *token; 22583a3e8d7aSmb158278 char *delims = "{} \t\n"; 22593a3e8d7aSmb158278 boolean_t port = B_FALSE; 22603a3e8d7aSmb158278 22613a3e8d7aSmb158278 while ((token = strtok(buf, delims)) != NULL) { 22623a3e8d7aSmb158278 buf = NULL; 22633a3e8d7aSmb158278 if (port == B_TRUE) { 22643a3e8d7aSmb158278 if (strcmp(token, "sun-dr") == 0 || 22653a3e8d7aSmb158278 strcmp(token, "665") == 0) { 22663a3e8d7aSmb158278 return (B_TRUE); 22673a3e8d7aSmb158278 } else { 22683a3e8d7aSmb158278 return (B_FALSE); 22693a3e8d7aSmb158278 } 22703a3e8d7aSmb158278 } 22713a3e8d7aSmb158278 if (strlen(token) == 5) { 22723a3e8d7aSmb158278 token++; 22733a3e8d7aSmb158278 if (strcmp(token, "port") == 0) { 22743a3e8d7aSmb158278 port = B_TRUE; 22753a3e8d7aSmb158278 continue; 22763a3e8d7aSmb158278 } 22773a3e8d7aSmb158278 } 22783a3e8d7aSmb158278 } 22793a3e8d7aSmb158278 return (B_FALSE); 22803a3e8d7aSmb158278 } 22813a3e8d7aSmb158278 22823a3e8d7aSmb158278 /* 22833a3e8d7aSmb158278 * dcs_global_policy 22843a3e8d7aSmb158278 * 22853a3e8d7aSmb158278 * Check global policy file for dcs entry. Just covers common cases. 22863a3e8d7aSmb158278 */ 22873a3e8d7aSmb158278 static boolean_t 22883a3e8d7aSmb158278 dcs_global_policy() 22893a3e8d7aSmb158278 { 22903a3e8d7aSmb158278 FILE *fp; 22913a3e8d7aSmb158278 char buf[256]; 22923a3e8d7aSmb158278 boolean_t rv = B_FALSE; 22933a3e8d7aSmb158278 22943a3e8d7aSmb158278 fp = fopen("/etc/inet/ipsecinit.conf", "r"); 22953a3e8d7aSmb158278 if (fp == NULL) 22963a3e8d7aSmb158278 return (B_FALSE); 22973a3e8d7aSmb158278 while (fgets(buf, sizeof (buf), fp) != NULL) { 22983a3e8d7aSmb158278 if (buf[0] == '#') 22993a3e8d7aSmb158278 continue; 23003a3e8d7aSmb158278 if (has_dcs_token(buf)) { 23013a3e8d7aSmb158278 rv = B_TRUE; 23023a3e8d7aSmb158278 syslog(LOG_NOTICE, "dcs using global policy"); 23033a3e8d7aSmb158278 break; 23043a3e8d7aSmb158278 } 23053a3e8d7aSmb158278 } 23063a3e8d7aSmb158278 (void) fclose(fp); 23073a3e8d7aSmb158278 return (rv); 23083a3e8d7aSmb158278 } 2309