#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <libnwam.h>
#include <libtecla.h>
#include <locale.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>
#include "nwamcfg.h"
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
struct help {
uint_t cmd_num;
const char *cmd_name;
const char *cmd_usage;
};
extern int yyparse(void);
extern int lex_lineno;
#define MAX_LINE_LEN 1024
#define MAX_CMD_HIST 1024
#define SHELP_CANCEL "cancel"
#define SHELP_CLEAR "clear <prop-name>"
#define SHELP_COMMIT "commit"
#define SHELP_CREATE "create [-t <template>] <object-type> [<class>] " \
"<object-name>"
#define SHELP_DESTROY "destroy {-a | <object-type> [<class>] <object-name>}"
#define SHELP_END "end"
#define SHELP_EXIT "exit"
#define SHELP_EXPORT "export [-d] [-f <output-file>] " \
"[<object-type> [<class>] <object-name>]"
#define SHELP_GET "get [-V] <prop-name>"
#define SHELP_HELP "help [command-name]"
#define SHELP_LIST "list [-a] [<object-type> [<class>] <object-name>]"
#define SHELP_REVERT "revert"
#define SHELP_SELECT "select <object-type> [<class>] <object-name>"
#define SHELP_SET "set <prop-name>=<value1>[,<value2>...]"
#define SHELP_VERIFY "verify"
#define SHELP_WALK "walkprop [-a]"
#define NWAM_SCOPE_GBL 0
#define NWAM_SCOPE_LOC 1
#define NWAM_SCOPE_ENM 2
#define NWAM_SCOPE_WLAN 3
#define NWAM_SCOPE_NCP 4
#define NWAM_SCOPE_NCU 5
#define NWAM_VALUE_DELIMITER_CHAR ','
#define NWAM_VALUE_DELIMITER_STR ","
static struct help helptab[] = {
{ CMD_CANCEL, "cancel", SHELP_CANCEL },
{ CMD_CLEAR, "clear", SHELP_CLEAR },
{ CMD_COMMIT, "commit", SHELP_COMMIT },
{ CMD_CREATE, "create", SHELP_CREATE },
{ CMD_DESTROY, "destroy", SHELP_DESTROY },
{ CMD_END, "end", SHELP_END },
{ CMD_EXIT, "exit", SHELP_EXIT },
{ CMD_EXPORT, "export", SHELP_EXPORT },
{ CMD_GET, "get", SHELP_GET },
{ CMD_HELP, "help", SHELP_HELP },
{ CMD_LIST, "list", SHELP_LIST },
{ CMD_REVERT, "revert", SHELP_REVERT },
{ CMD_SELECT, "select", SHELP_SELECT },
{ CMD_SET, "set", SHELP_SET },
{ CMD_VERIFY, "verify", SHELP_VERIFY },
{ CMD_WALKPROP, "walkprop", SHELP_WALK },
{ 0, NULL, NULL }
};
static char *res1_types[] = {
"unknown",
"loc",
"ncp",
"enm",
"wlan",
NULL
};
static char *res2_types[] = {
"unknown",
"ncu",
NULL
};
static char *pt_types[] = {
"unknown",
NWAM_NCU_PROP_ACTIVATION_MODE,
NWAM_NCU_PROP_ENABLED,
NWAM_NCU_PROP_TYPE,
NWAM_NCU_PROP_CLASS,
NWAM_NCU_PROP_PARENT_NCP,
NWAM_NCU_PROP_PRIORITY_GROUP,
NWAM_NCU_PROP_PRIORITY_MODE,
NWAM_NCU_PROP_LINK_MAC_ADDR,
NWAM_NCU_PROP_LINK_AUTOPUSH,
NWAM_NCU_PROP_LINK_MTU,
NWAM_NCU_PROP_IP_VERSION,
NWAM_NCU_PROP_IPV4_ADDRSRC,
NWAM_NCU_PROP_IPV4_ADDR,
NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE,
NWAM_NCU_PROP_IPV6_ADDRSRC,
NWAM_NCU_PROP_IPV6_ADDR,
NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE,
NWAM_LOC_PROP_CONDITIONS,
NWAM_ENM_PROP_FMRI,
NWAM_ENM_PROP_START,
NWAM_ENM_PROP_STOP,
NWAM_LOC_PROP_NAMESERVICES,
NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE,
NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN,
NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS,
NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH,
NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS,
NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS,
NWAM_LOC_PROP_DEFAULT_DOMAIN,
NWAM_LOC_PROP_NFSV4_DOMAIN,
NWAM_LOC_PROP_IPFILTER_CONFIG_FILE,
NWAM_LOC_PROP_IPFILTER_V6_CONFIG_FILE,
NWAM_LOC_PROP_IPNAT_CONFIG_FILE,
NWAM_LOC_PROP_IPPOOL_CONFIG_FILE,
NWAM_LOC_PROP_IKE_CONFIG_FILE,
NWAM_LOC_PROP_IPSECPOLICY_CONFIG_FILE,
NWAM_KNOWN_WLAN_PROP_BSSIDS,
NWAM_KNOWN_WLAN_PROP_PRIORITY,
NWAM_KNOWN_WLAN_PROP_KEYNAME,
NWAM_KNOWN_WLAN_PROP_KEYSLOT,
NWAM_KNOWN_WLAN_PROP_SECURITY_MODE,
NWAM_NCU_PROP_IP_PRIMARY,
NWAM_NCU_PROP_IP_REQHOST
};
typedef struct prop_table_entry {
int pte_type;
const char *pte_name;
} prop_table_entry_t;
static prop_table_entry_t ncu_prop_table[] = {
{ PT_TYPE, NWAM_NCU_PROP_TYPE },
{ PT_CLASS, NWAM_NCU_PROP_CLASS },
{ PT_PARENT, NWAM_NCU_PROP_PARENT_NCP },
{ PT_ACTIVATION_MODE, NWAM_NCU_PROP_ACTIVATION_MODE },
{ PT_ENABLED, NWAM_NCU_PROP_ENABLED },
{ PT_PRIORITY_GROUP, NWAM_NCU_PROP_PRIORITY_GROUP },
{ PT_PRIORITY_MODE, NWAM_NCU_PROP_PRIORITY_MODE },
{ PT_LINK_MACADDR, NWAM_NCU_PROP_LINK_MAC_ADDR },
{ PT_LINK_AUTOPUSH, NWAM_NCU_PROP_LINK_AUTOPUSH },
{ PT_LINK_MTU, NWAM_NCU_PROP_LINK_MTU },
{ PT_IP_VERSION, NWAM_NCU_PROP_IP_VERSION },
{ PT_IPV4_ADDRSRC, NWAM_NCU_PROP_IPV4_ADDRSRC },
{ PT_IPV4_ADDR, NWAM_NCU_PROP_IPV4_ADDR },
{ PT_IPV4_DEFAULT_ROUTE, NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE },
{ PT_IPV6_ADDRSRC, NWAM_NCU_PROP_IPV6_ADDRSRC },
{ PT_IPV6_ADDR, NWAM_NCU_PROP_IPV6_ADDR },
{ PT_IPV6_DEFAULT_ROUTE, NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE },
{ PT_IP_PRIMARY, NWAM_NCU_PROP_IP_PRIMARY },
{ PT_IP_REQHOST, NWAM_NCU_PROP_IP_REQHOST },
{ 0, NULL }
};
static prop_table_entry_t enm_prop_table[] = {
{ PT_ENM_FMRI, NWAM_ENM_PROP_FMRI },
{ PT_ENM_START, NWAM_ENM_PROP_START },
{ PT_ENM_STOP, NWAM_ENM_PROP_STOP },
{ PT_ACTIVATION_MODE, NWAM_ENM_PROP_ACTIVATION_MODE },
{ PT_CONDITIONS, NWAM_ENM_PROP_CONDITIONS },
{ PT_ENABLED, NWAM_ENM_PROP_ENABLED },
{ 0, NULL }
};
static prop_table_entry_t loc_prop_table[] = {
{ PT_ACTIVATION_MODE, NWAM_LOC_PROP_ACTIVATION_MODE },
{ PT_CONDITIONS, NWAM_LOC_PROP_CONDITIONS },
{ PT_ENABLED, NWAM_LOC_PROP_ENABLED },
{ PT_LOC_NAMESERVICES, NWAM_LOC_PROP_NAMESERVICES },
{ PT_LOC_NAMESERVICES_CONFIG, NWAM_LOC_PROP_NAMESERVICES_CONFIG_FILE },
{ PT_LOC_DNS_CONFIGSRC, NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC },
{ PT_LOC_DNS_DOMAIN, NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN },
{ PT_LOC_DNS_SERVERS, NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS },
{ PT_LOC_DNS_SEARCH, NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH },
{ PT_LOC_NIS_CONFIGSRC, NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC },
{ PT_LOC_NIS_SERVERS, NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS },
{ PT_LOC_LDAP_CONFIGSRC, NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC },
{ PT_LOC_LDAP_SERVERS, NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS },
{ PT_LOC_DEFAULT_DOMAIN, NWAM_LOC_PROP_DEFAULT_DOMAIN },
{ PT_LOC_NFSV4_DOMAIN, NWAM_LOC_PROP_NFSV4_DOMAIN },
{ PT_LOC_IPF_CONFIG, NWAM_LOC_PROP_IPFILTER_CONFIG_FILE },
{ PT_LOC_IPF_V6_CONFIG, NWAM_LOC_PROP_IPFILTER_V6_CONFIG_FILE },
{ PT_LOC_IPNAT_CONFIG, NWAM_LOC_PROP_IPNAT_CONFIG_FILE },
{ PT_LOC_IPPOOL_CONFIG, NWAM_LOC_PROP_IPPOOL_CONFIG_FILE },
{ PT_LOC_IKE_CONFIG, NWAM_LOC_PROP_IKE_CONFIG_FILE },
{ PT_LOC_IPSECPOL_CONFIG, NWAM_LOC_PROP_IPSECPOLICY_CONFIG_FILE },
{ 0, NULL }
};
static prop_table_entry_t wlan_prop_table[] = {
{ PT_WLAN_BSSIDS, NWAM_KNOWN_WLAN_PROP_BSSIDS },
{ PT_WLAN_PRIORITY, NWAM_KNOWN_WLAN_PROP_PRIORITY },
{ PT_WLAN_KEYNAME, NWAM_KNOWN_WLAN_PROP_KEYNAME },
{ PT_WLAN_KEYSLOT, NWAM_KNOWN_WLAN_PROP_KEYSLOT },
{ PT_WLAN_SECURITY_MODE, NWAM_KNOWN_WLAN_PROP_SECURITY_MODE },
{ 0, NULL }
};
static prop_table_entry_t *
get_prop_table(nwam_object_type_t object_type)
{
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
return (ncu_prop_table);
case NWAM_OBJECT_TYPE_LOC:
return (loc_prop_table);
case NWAM_OBJECT_TYPE_ENM:
return (enm_prop_table);
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
return (wlan_prop_table);
}
return (NULL);
}
static char *execname;
boolean_t saw_error = B_FALSE;
boolean_t newline_terminated;
boolean_t cmd_file_mode = B_FALSE;
static boolean_t time_to_exit = B_FALSE;
static char *cmd_file_name = NULL;
static boolean_t remove_all_configurations = B_FALSE;
static boolean_t ok_to_prompt = B_FALSE;
static boolean_t interactive_mode;
static boolean_t need_to_commit = B_FALSE;
static GetLine *gl;
static nwam_loc_handle_t loc_h = NULL;
static nwam_enm_handle_t enm_h = NULL;
static nwam_known_wlan_handle_t wlan_h = NULL;
static nwam_ncu_handle_t ncu_h = NULL;
static nwam_ncp_handle_t ncp_h = NULL;
static int current_scope = NWAM_SCOPE_GBL;
static int obj1_type;
static char obj1_name[NWAM_MAX_NAME_LEN + 1];
static int obj2_type;
static char obj2_name[NWAM_MAX_NAME_LEN + 1];
static const char *global_scope_cmds[] = {
"create ",
"destroy ",
"end ",
"exit ",
"export ",
"help ",
"list ",
"select ",
NULL
};
static const char *global_create_cmds[] = {
"create loc ",
"create enm ",
"create ncp ",
"create wlan ",
"create -t ",
NULL
};
static const char *global_destroy_cmds[] = {
"destroy -a ",
"destroy loc ",
"destroy enm ",
"destroy ncp ",
"destroy wlan ",
NULL
};
static const char *global_export_cmds[] = {
"export ",
"export -d ",
"export -f ",
"export -d -f ",
"export loc ",
"export enm ",
"export ncp ",
"export wlan ",
NULL
};
static const char *global_list_cmds[] = {
"list ",
"list loc ",
"list enm ",
"list ncp ",
"list wlan ",
"list -a loc ",
"list -a enm ",
"list -a wlan ",
NULL
};
static const char *global_select_cmds[] = {
"select loc ",
"select enm ",
"select ncp ",
"select wlan ",
NULL
};
static const char *non_ncp_scope_cmds[] = {
"cancel ",
"clear ",
"commit ",
"end ",
"exit ",
"export ",
"export -f ",
"get ",
"get -V ",
"help ",
"list ",
"list -a ",
"revert ",
"set ",
"verify ",
"walkprop ",
"walkprop -a ",
NULL
};
static const char *ncp_scope_cmds[] = {
"cancel ",
"create ",
"destroy ",
"end ",
"exit ",
"export ",
"help ",
"list ",
"select ",
NULL
};
static const char *ncp_create_cmds[] = {
"create ncu ip ",
"create ncu phys ",
"create -t ",
NULL
};
static const char *ncp_destroy_cmds[] = {
"destroy ncu ",
"destroy ncu ip ",
"destroy ncu phys ",
NULL
};
static const char *ncp_export_cmds[] = {
"export ",
"export -f ",
"export ncu ",
"export ncu ip ",
"export ncu phys ",
NULL
};
static const char *ncp_list_cmds[] = {
"list ",
"list ncu ",
"list ncu ip ",
"list ncu phys ",
"list -a ncu ",
"list -a ncu ip ",
"list -a ncu phys ",
NULL
};
static const char *ncp_select_cmds[] = {
"select ncu ",
"select ncu ip ",
"select ncu phys ",
NULL
};
cmd_t *
alloc_cmd(void)
{
cmd_t *cmd = calloc(1, sizeof (cmd_t));
if (cmd == NULL) {
nerr("Out of memory");
return (NULL);
}
cmd->cmd_argc = 0;
cmd->cmd_argv[0] = NULL;
return (cmd);
}
void
free_cmd(cmd_t *cmd)
{
int i;
for (i = 0; i < cmd->cmd_argc; i++)
free(cmd->cmd_argv[i]);
free(cmd);
}
void
array_free(void **array, int nelem)
{
int i;
for (i = 0; i < nelem; i++)
free(array[i]);
free(array);
}
static boolean_t
initial_match(const char *line1, const char *line2, int word_end)
{
if (word_end <= 0)
return (B_TRUE);
return (strncmp(line1, line2, word_end) == 0);
}
static int
add_stuff(WordCompletion *cpl, const char *line1, const char **list,
int word_end)
{
int i, err;
for (i = 0; list[i] != NULL; i++) {
if (initial_match(line1, list[i], word_end)) {
err = cpl_add_completion(cpl, line1, 0, word_end,
list[i] + word_end, "", "");
if (err != 0)
return (err);
}
}
return (0);
}
#define MINI_STR(l, s, m, n) strncmp(l, s, MAX(MIN(sizeof (s) - 1, m), n))
static
CPL_MATCH_FN(cmd_cpl_fn)
{
switch (current_scope) {
case NWAM_SCOPE_GBL:
if (MINI_STR(line, "create ", word_end, 2) == 0)
return (add_stuff(cpl, line, global_create_cmds,
word_end));
if (MINI_STR(line, "destroy ", word_end, 1) == 0)
return (add_stuff(cpl, line, global_destroy_cmds,
word_end));
if (MINI_STR(line, "export ", word_end, 3) == 0)
return (add_stuff(cpl, line, global_export_cmds,
word_end));
if (MINI_STR(line, "list ", word_end, 1) == 0)
return (add_stuff(cpl, line, global_list_cmds,
word_end));
if (MINI_STR(line, "select ", word_end, 1) == 0)
return (add_stuff(cpl, line, global_select_cmds,
word_end));
return (add_stuff(cpl, line, global_scope_cmds, word_end));
case NWAM_SCOPE_LOC:
case NWAM_SCOPE_ENM:
case NWAM_SCOPE_WLAN:
case NWAM_SCOPE_NCU:
return (add_stuff(cpl, line, non_ncp_scope_cmds, word_end));
case NWAM_SCOPE_NCP:
if (MINI_STR(line, "create ", word_end, 2) == 0)
return (add_stuff(cpl, line, ncp_create_cmds,
word_end));
if (MINI_STR(line, "destroy ", word_end, 1) == 0)
return (add_stuff(cpl, line, ncp_destroy_cmds,
word_end));
if (MINI_STR(line, "export ", word_end, 3) == 0)
return (add_stuff(cpl, line, ncp_export_cmds,
word_end));
if (MINI_STR(line, "list ", word_end, 1) == 0)
return (add_stuff(cpl, line, ncp_list_cmds, word_end));
if (MINI_STR(line, "select ", word_end, 1) == 0)
return (add_stuff(cpl, line, ncp_select_cmds,
word_end));
return (add_stuff(cpl, line, ncp_scope_cmds, word_end));
}
return (0);
}
const char *
cmd_to_str(int cmd_num)
{
assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
return (helptab[cmd_num].cmd_name);
}
static const char *
rt1_to_str(int res_type)
{
assert(res_type >= RT1_MIN && res_type <= RT1_MAX);
return (res1_types[res_type]);
}
static const char *
rt2_to_str(int res_type)
{
assert(res_type >= RT2_MIN && res_type <= RT2_MAX);
return (res2_types[res_type]);
}
static const char *
scope_to_str(int scope)
{
switch (scope) {
case NWAM_SCOPE_GBL:
return ("global");
case NWAM_SCOPE_NCP:
return ("ncp");
case NWAM_SCOPE_NCU:
return ("ncu");
case NWAM_SCOPE_LOC:
return ("loc");
case NWAM_SCOPE_ENM:
return ("enm");
case NWAM_SCOPE_WLAN:
return ("wlan");
default:
return ("invalid");
}
}
static const char *
propval_to_str(const char *propname, uint64_t value)
{
const char *str;
if (nwam_uint64_get_value_string(propname, value, &str) == NWAM_SUCCESS)
return (str);
return (NULL);
}
static const char *
pt_to_str(int prop_type)
{
assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
return (pt_types[prop_type]);
}
static boolean_t
str_to_boolean(const char *str)
{
if (strncasecmp(str, "t", 1) == 0 || strncasecmp(str, "on", 2) == 0 ||
atoi(str) == 1)
return (B_TRUE);
else
return (B_FALSE);
}
static const char *
long_help(int cmd_num)
{
assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
switch (cmd_num) {
case CMD_CANCEL:
return (gettext("Cancels the current configuration "
"changes."));
case CMD_CLEAR:
return (gettext("Clears the value for the specified "
"property."));
case CMD_COMMIT:
return (gettext("Commits the current configuration."));
case CMD_CREATE:
return (gettext("Creates a new profile or resource."));
case CMD_DESTROY:
return (gettext("Destroys the specified profile or "
"resource."));
case CMD_END:
return (gettext("Ends specification of a resource."));
case CMD_EXIT:
return (gettext("Exits the program."));
case CMD_EXPORT:
return (gettext("Exports the configuration."));
case CMD_GET:
return (gettext("Gets the value of the specified "
"property."));
case CMD_HELP:
return (gettext("Prints help message."));
case CMD_LIST:
return (gettext("Lists existing objects."));
case CMD_REVERT:
return (gettext("Reverts to the previous "
"configuration."));
case CMD_SELECT:
return (gettext("Selects a resource to modify."));
case CMD_SET:
return (gettext("Sets the value of the specified "
"property."));
case CMD_VERIFY:
return (gettext("Verifies an object."));
case CMD_WALKPROP:
return (gettext("Iterates over properties."));
default:
return (gettext("Unknown command."));
}
}
void
command_usage(int command)
{
if (command < CMD_MIN || command > CMD_MAX) {
nerr("Unknown command");
} else {
nerr("%s: %s: %s", gettext("Error"), gettext("usage"),
helptab[command].cmd_usage);
}
}
static void
long_usage(uint_t cmd_num)
{
(void) printf("%s: %s\n", gettext("usage"),
helptab[cmd_num].cmd_usage);
(void) printf("\t%s\n", long_help(cmd_num));
}
static void
cmd_line_usage()
{
(void) printf("%s:\t%s\t\t\t\t(%s)\n", gettext("usage"), execname,
gettext("interactive-mode"));
(void) printf("\t%s <%s> [%s...]\n", execname, gettext("command"),
gettext("options"));
(void) printf("\t%s [-d] -f <%s>\n", execname, gettext("command-file"));
(void) printf("\t%s %s [<%s>]\n", execname, cmd_to_str(CMD_HELP),
gettext("command"));
}
static void
print_lineno()
{
static int last_lineno;
if (cmd_file_mode && lex_lineno > last_lineno) {
if (strcmp(cmd_file_name, "-") == 0)
(void) fprintf(stderr, gettext("On line %d:\n"),
lex_lineno - 1);
else
(void) fprintf(stderr, gettext("On line %d of %s:\n"),
lex_lineno - 1, cmd_file_name);
last_lineno = lex_lineno;
}
}
void
nerr(const char *format, ...)
{
va_list alist;
print_lineno();
format = gettext(format);
va_start(alist, format);
(void) vfprintf(stderr, format, alist);
va_end(alist);
(void) fprintf(stderr, "\n");
saw_error = B_TRUE;
}
static void
nwamerr(nwam_error_t err, const char *format, ...)
{
va_list alist;
print_lineno();
format = gettext(format);
va_start(alist, format);
(void) vfprintf(stderr, format, alist);
va_end(alist);
(void) fprintf(stderr, ": %s\n", nwam_strerror(err));
saw_error = B_TRUE;
}
void
properr(const char *prop)
{
nerr("Invalid property: '%s'", prop);
}
static void
free_handle(boolean_t free_ncu_only)
{
if (ncp_h != NULL) {
if (!free_ncu_only) {
nwam_ncp_free(ncp_h);
ncp_h = NULL;
ncu_h = NULL;
} else if (ncu_h != NULL) {
nwam_ncu_free(ncu_h);
ncu_h = NULL;
}
}
if (enm_h != NULL) {
nwam_enm_free(enm_h);
enm_h = NULL;
}
if (loc_h != NULL) {
nwam_loc_free(loc_h);
loc_h = NULL;
}
if (wlan_h != NULL) {
nwam_known_wlan_free(wlan_h);
wlan_h = NULL;
}
}
static int
ask_yesno(boolean_t default_answer, const char *question)
{
char line[64];
if (!ok_to_prompt) {
saw_error = B_TRUE;
return (-1);
}
for (;;) {
if (printf("%s (%s)? ", gettext(question),
default_answer ? "[y]/n" : "y/[n]") < 0)
return (-1);
if (fgets(line, sizeof (line), stdin) == NULL)
return (-1);
if (line[0] == '\n')
return (default_answer ? 1 : 0);
if (tolower(line[0]) == 'y')
return (1);
if (tolower(line[0]) == 'n')
return (0);
}
}
static int
cleanup()
{
int answer;
if (!interactive_mode && !cmd_file_mode) {
ok_to_prompt = B_FALSE;
}
if (need_to_commit) {
answer = ask_yesno(B_FALSE,
"Configuration not saved; really quit");
switch (answer) {
case -1:
return (NWAM_ERR);
case 1:
return (NWAM_OK);
default:
time_to_exit = B_FALSE;
yyin = stdin;
return (NWAM_REPEAT);
}
}
return (saw_error ? NWAM_ERR : NWAM_OK);
}
static int
string_to_yyin(char *string)
{
if ((yyin = tmpfile()) == NULL)
goto error;
if (fwrite(string, strlen(string), 1, yyin) != 1)
goto error;
if (fseek(yyin, 0, SEEK_SET) != 0)
goto error;
return (NWAM_OK);
error:
nerr("problem creating temporary file");
return (NWAM_ERR);
}
static int
read_input(void)
{
boolean_t yyin_is_a_tty = isatty(fileno(yyin));
char prompt[MAXPATHLEN + (2 * (NWAM_MAX_TYPE_LEN + NWAM_MAX_NAME_LEN))
+ sizeof ("::::> ")];
char *line;
newline_terminated = B_TRUE;
for (;;) {
if (yyin_is_a_tty) {
if (newline_terminated) {
switch (current_scope) {
case NWAM_SCOPE_GBL:
(void) snprintf(prompt, sizeof (prompt),
"%s> ", execname);
break;
case NWAM_SCOPE_LOC:
case NWAM_SCOPE_ENM:
case NWAM_SCOPE_WLAN:
case NWAM_SCOPE_NCP:
(void) snprintf(prompt, sizeof (prompt),
"%s:%s:%s> ", execname,
rt1_to_str(obj1_type), obj1_name);
break;
case NWAM_SCOPE_NCU:
(void) snprintf(prompt, sizeof (prompt),
"%s:%s:%s:%s:%s> ", execname,
rt1_to_str(obj1_type), obj1_name,
rt2_to_str(obj2_type), obj2_name);
}
}
line = gl_get_line(gl, prompt, NULL, -1);
if (gl_return_status(gl) == GLR_SIGNAL) {
gl_abandon_line(gl);
continue;
}
if (line == NULL)
break;
if (string_to_yyin(line) != NWAM_OK)
break;
while (!feof(yyin)) {
yyparse();
if (saw_error || time_to_exit)
break;
}
} else {
yyparse();
}
if (saw_error && cmd_file_mode && !interactive_mode)
time_to_exit = B_TRUE;
if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
break;
}
return (cleanup());
}
static int
do_interactive(void)
{
int err;
interactive_mode = B_TRUE;
do {
err = read_input();
} while (err == NWAM_REPEAT);
return (err);
}
void
help_wrap()
{
cmd_t *help_cmd;
if ((help_cmd = alloc_cmd()) == NULL)
exit(NWAM_ERR);
help_func(help_cmd);
free_cmd(help_cmd);
}
boolean_t
check_scope(int cmd)
{
switch (cmd) {
case CMD_END:
case CMD_EXIT:
case CMD_HELP:
case CMD_LIST:
case CMD_EXPORT:
return (B_TRUE);
}
switch (current_scope) {
case NWAM_SCOPE_GBL:
switch (cmd) {
case CMD_CREATE:
case CMD_DESTROY:
case CMD_SELECT:
return (B_TRUE);
}
break;
case NWAM_SCOPE_LOC:
case NWAM_SCOPE_ENM:
case NWAM_SCOPE_WLAN:
case NWAM_SCOPE_NCU:
switch (cmd) {
case CMD_CANCEL:
case CMD_CLEAR:
case CMD_COMMIT:
case CMD_GET:
case CMD_REVERT:
case CMD_SET:
case CMD_VERIFY:
case CMD_WALKPROP:
return (B_TRUE);
}
break;
case NWAM_SCOPE_NCP:
switch (cmd) {
case CMD_CANCEL:
case CMD_CREATE:
case CMD_DESTROY:
case CMD_SELECT:
return (B_TRUE);
}
break;
default:
nerr("Invalid scope");
}
nerr("'%s' is not allowed at this scope", cmd_to_str(cmd));
return (B_FALSE);
}
static nwam_object_type_t
active_object_type(void)
{
if (ncu_h != NULL)
return (NWAM_OBJECT_TYPE_NCU);
else if (ncp_h != NULL)
return (NWAM_OBJECT_TYPE_NCP);
else if (loc_h != NULL)
return (NWAM_OBJECT_TYPE_LOC);
else if (enm_h != NULL)
return (NWAM_OBJECT_TYPE_ENM);
else if (wlan_h != NULL)
return (NWAM_OBJECT_TYPE_KNOWN_WLAN);
else
return (NWAM_OBJECT_TYPE_UNKNOWN);
}
static nwam_error_t
object_name_from_handle(nwam_object_type_t object_type, void *handle,
char **namep)
{
switch (object_type) {
case NWAM_OBJECT_TYPE_NCP:
return (nwam_ncp_get_name(handle, namep));
case NWAM_OBJECT_TYPE_NCU:
return (nwam_ncu_get_name(handle, namep));
case NWAM_OBJECT_TYPE_LOC:
return (nwam_loc_get_name(handle, namep));
case NWAM_OBJECT_TYPE_ENM:
return (nwam_enm_get_name(handle, namep));
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
return (nwam_known_wlan_get_name(handle, namep));
}
return (NWAM_INVALID_ARG);
}
static void
do_commit()
{
nwam_error_t ret = NWAM_SUCCESS;
const char *errprop;
if (!need_to_commit)
return;
switch (active_object_type()) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_commit(ncu_h, 0);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_commit(enm_h, 0);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_commit(loc_h, 0);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_commit(wlan_h, 0);
break;
}
if (ret == NWAM_SUCCESS) {
need_to_commit = B_FALSE;
if (interactive_mode)
(void) printf(gettext("Committed changes\n"));
} else {
nwam_error_t verr;
switch (active_object_type()) {
case NWAM_OBJECT_TYPE_NCU:
verr = nwam_ncu_validate(ncu_h, &errprop);
break;
case NWAM_OBJECT_TYPE_ENM:
verr = nwam_enm_validate(enm_h, &errprop);
break;
case NWAM_OBJECT_TYPE_LOC:
verr = nwam_loc_validate(loc_h, &errprop);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
verr = nwam_known_wlan_validate(wlan_h, &errprop);
break;
default:
verr = NWAM_INVALID_HANDLE;
nwamerr(ret, "Unknown object type");
return;
}
if (verr != NWAM_SUCCESS)
nwamerr(ret, "Commit error on property '%s'", errprop);
else
nwamerr(ret, "Commit error");
}
}
void
commit_func(cmd_t *cmd)
{
if (!need_to_commit) {
if (interactive_mode)
(void) printf(gettext("Nothing to commit\n"));
} else {
do_commit();
}
}
static void
do_cancel()
{
switch (current_scope) {
case NWAM_SCOPE_NCU:
current_scope = NWAM_SCOPE_NCP;
obj2_type = 0;
free_handle(B_TRUE);
break;
case NWAM_SCOPE_NCP:
case NWAM_SCOPE_ENM:
case NWAM_SCOPE_WLAN:
case NWAM_SCOPE_LOC:
current_scope = NWAM_SCOPE_GBL;
obj1_type = 0;
free_handle(B_FALSE);
break;
case NWAM_SCOPE_GBL:
free_handle(B_FALSE);
break;
default:
nerr("Invalid scope");
return;
}
need_to_commit = B_FALSE;
}
void
cancel_func(cmd_t *cmd)
{
do_cancel();
}
static char *
trim_quotes(const char *quoted_str)
{
char *str;
int end;
if (quoted_str == NULL)
return (NULL);
if (quoted_str[0] == '"')
str = strdup(quoted_str + 1);
else
str = strdup(quoted_str);
if (str == NULL)
return (NULL);
end = strlen(str) - 1;
while (end >= 0 && (str[end] == '"' || str[end] == '\n'))
end--;
str[end+1] = 0;
return (str);
}
void
create_func(cmd_t *cmd)
{
nwam_error_t ret = NWAM_SUCCESS;
int c;
boolean_t template = B_FALSE;
char *newname = NULL, *oldname = NULL;
cmd_t *walkprop_cmd;
if (current_scope == NWAM_SCOPE_GBL &&
cmd->cmd_res2_type == RT2_NCU) {
nerr("cannot create ncu at global scope");
return;
}
if (current_scope == NWAM_SCOPE_NCP &&
cmd->cmd_res2_type != RT2_NCU) {
nerr("Cannot create given object at this scope");
return;
}
assert(cmd->cmd_argc > 0);
optind = 0;
while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "t:")) != EOF) {
switch (c) {
case 't':
template = B_TRUE;
break;
default:
command_usage(CMD_CREATE);
return;
}
}
if (!template) {
newname = trim_quotes(cmd->cmd_argv[0]);
if (cmd->cmd_res1_type == RT1_ENM) {
ret = nwam_enm_create(newname, NULL, &enm_h);
} else if (cmd->cmd_res1_type == RT1_LOC) {
ret = nwam_loc_create(newname, &loc_h);
} else if (cmd->cmd_res1_type == RT1_WLAN) {
ret = nwam_known_wlan_create(newname, &wlan_h);
} else if (cmd->cmd_res1_type == RT1_NCP &&
current_scope == NWAM_SCOPE_GBL) {
ret = nwam_ncp_create(newname, 0, &ncp_h);
} else if (cmd->cmd_res2_type == RT2_NCU) {
nwam_ncu_type_t ncu_type;
nwam_ncu_class_t ncu_class;
if (ncp_h == NULL) {
nerr("Create error: NCP has not been read");
goto done;
}
ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
ncu_type = nwam_ncu_class_to_type(ncu_class);
ret = nwam_ncu_create(ncp_h, newname, ncu_type,
ncu_class, &ncu_h);
}
if (ret != NWAM_SUCCESS) {
nwamerr(ret, "Create error");
goto done;
}
} else {
oldname = trim_quotes(cmd->cmd_argv[1]);
newname = trim_quotes(cmd->cmd_argv[2]);
if (cmd->cmd_res1_type == RT1_ENM) {
nwam_enm_handle_t oldenm_h;
ret = nwam_enm_read(oldname, 0, &oldenm_h);
if (ret != NWAM_SUCCESS)
goto read_error;
ret = nwam_enm_copy(oldenm_h, newname, &enm_h);
nwam_enm_free(oldenm_h);
} else if (cmd->cmd_res1_type == RT1_LOC) {
nwam_loc_handle_t oldloc_h;
ret = nwam_loc_read(oldname, 0, &oldloc_h);
if (ret != NWAM_SUCCESS)
goto read_error;
ret = nwam_loc_copy(oldloc_h, newname, &loc_h);
nwam_loc_free(oldloc_h);
} else if (cmd->cmd_res1_type == RT1_WLAN) {
nwam_known_wlan_handle_t oldwlan_h;
ret = nwam_known_wlan_read(oldname, 0, &oldwlan_h);
if (ret != NWAM_SUCCESS)
goto read_error;
ret = nwam_known_wlan_copy(oldwlan_h, newname, &wlan_h);
nwam_known_wlan_free(oldwlan_h);
} else if (cmd->cmd_res1_type == RT1_NCP &&
current_scope == NWAM_SCOPE_GBL) {
nwam_ncp_handle_t oldncp_h;
ret = nwam_ncp_read(oldname, 0, &oldncp_h);
if (ret != NWAM_SUCCESS)
goto read_error;
ret = nwam_ncp_copy(oldncp_h, newname, &ncp_h);
nwam_ncp_free(oldncp_h);
} else if (cmd->cmd_res2_type == RT2_NCU) {
nwam_ncu_handle_t oldncu_h;
nwam_ncu_type_t ncu_type;
nwam_ncu_class_t ncu_class;
if (ncp_h == NULL) {
nerr("Copy error: NCP has not been read");
goto done;
}
ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
ncu_type = nwam_ncu_class_to_type(ncu_class);
ret = nwam_ncu_read(ncp_h, oldname, ncu_type, 0,
&oldncu_h);
if (ret != NWAM_SUCCESS)
goto read_error;
ret = nwam_ncu_copy(oldncu_h, newname, &ncu_h);
nwam_ncu_free(oldncu_h);
}
if (ret != NWAM_SUCCESS) {
nwamerr(ret, "Copy error");
goto done;
}
}
if (current_scope == NWAM_SCOPE_GBL) {
(void) strlcpy(obj1_name, newname, sizeof (obj1_name));
obj1_type = cmd->cmd_res1_type;
if (obj1_type == RT1_ENM)
current_scope = NWAM_SCOPE_ENM;
else if (obj1_type == RT1_LOC)
current_scope = NWAM_SCOPE_LOC;
else if (obj1_type == RT1_WLAN)
current_scope = NWAM_SCOPE_WLAN;
else if (obj1_type == RT1_NCP)
current_scope = NWAM_SCOPE_NCP;
} else {
(void) strlcpy(obj2_name, newname, sizeof (obj2_name));
current_scope = NWAM_SCOPE_NCU;
obj2_type = cmd->cmd_res2_type;
}
if (current_scope != NWAM_SCOPE_NCP)
need_to_commit = B_TRUE;
if (interactive_mode && current_scope != NWAM_SCOPE_NCP) {
(void) printf(gettext("Created %s '%s'. "
"Walking properties ...\n"),
scope_to_str(current_scope), newname);
if ((walkprop_cmd = alloc_cmd()) == NULL)
goto done;
walkprop_func(walkprop_cmd);
free(walkprop_cmd);
}
read_error:
if (ret != NWAM_SUCCESS)
nwamerr(ret, "Copy error reading '%s'", oldname);
done:
free(oldname);
free(newname);
}
static int
destroy_ret(nwam_object_type_t object_type, nwam_error_t ret, void *handle)
{
if (ret == NWAM_ENTITY_NOT_DESTROYABLE) {
char *name;
if (object_name_from_handle(object_type, handle, &name)
== NWAM_SUCCESS) {
(void) fprintf(stderr,
gettext("%s '%s' cannot be removed\n"),
nwam_object_type_to_string(object_type), name);
free(name);
}
return (0);
}
if (ret == NWAM_SUCCESS || ret == NWAM_ENTITY_IN_USE)
return (0);
return (1);
}
static int
destroy_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
{
nwam_error_t ret = nwam_ncp_destroy(ncp, NWAM_FLAG_DO_NOT_FREE);
return (destroy_ret(NWAM_OBJECT_TYPE_NCP, ret, ncp));
}
static int
destroy_loc_callback(nwam_loc_handle_t loc, void *arg)
{
nwam_error_t ret = nwam_loc_destroy(loc, NWAM_FLAG_DO_NOT_FREE);
return (destroy_ret(NWAM_OBJECT_TYPE_LOC, ret, loc));
}
static int
destroy_enm_callback(nwam_enm_handle_t enm, void *arg)
{
nwam_error_t ret = nwam_enm_destroy(enm, NWAM_FLAG_DO_NOT_FREE);
return (destroy_ret(NWAM_OBJECT_TYPE_ENM, ret, enm));
}
static int
destroy_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
{
nwam_error_t ret = nwam_known_wlan_destroy(wlan, NWAM_FLAG_DO_NOT_FREE);
return (destroy_ret(NWAM_OBJECT_TYPE_KNOWN_WLAN, ret, wlan));
}
static nwam_error_t
destroy_all(void)
{
nwam_error_t ret;
assert(remove_all_configurations);
ret = nwam_walk_ncps(destroy_ncp_callback, NULL, 0, NULL);
if (ret != NWAM_SUCCESS)
goto done;
ret = nwam_walk_enms(destroy_enm_callback, NULL,
NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
if (ret != NWAM_SUCCESS)
goto done;
ret = nwam_walk_locs(destroy_loc_callback, NULL,
NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
if (ret != NWAM_SUCCESS)
goto done;
ret = nwam_walk_known_wlans(destroy_wlan_callback, NULL, 0, NULL);
if (ret != NWAM_SUCCESS)
goto done;
if (interactive_mode)
(void) printf(gettext("All user-defined entities destroyed\n"));
remove_all_configurations = B_FALSE;
done:
if (ret != NWAM_SUCCESS) {
nwamerr(ret, "Destroy error: "
"could not destroy all configurations");
}
return (ret);
}
void
destroy_func(cmd_t *cmd)
{
nwam_error_t ret;
char *name, *realname = NULL;
if (current_scope == NWAM_SCOPE_NCP &&
(cmd->cmd_res1_type == RT1_ENM || cmd->cmd_res1_type == RT1_LOC ||
cmd->cmd_res1_type == RT1_WLAN)) {
nerr("Destroy error: only NCUs can be destroyed in NCP scope");
return;
}
assert(cmd->cmd_argc > 0);
if (cmd->cmd_res1_type == -1) {
int c;
if (current_scope != NWAM_SCOPE_GBL) {
nerr("Cannot destroy all configurations in a "
"non-global scope");
return;
}
optind = 0;
while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "a")) != EOF) {
switch (c) {
case 'a':
remove_all_configurations = B_TRUE;
break;
default:
command_usage(CMD_DESTROY);
return;
}
}
if (remove_all_configurations) {
(void) destroy_all();
return;
}
}
name = trim_quotes(cmd->cmd_argv[0]);
if (cmd->cmd_res2_type == RT2_NCU) {
nwam_ncu_type_t ncu_type;
nwam_ncu_class_t ncu_class;
if (ncp_h == NULL) {
nerr("Destroy ncu error: NCP has not been read");
return;
}
ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
ncu_type = nwam_ncu_class_to_type(ncu_class);
ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
if (ret != NWAM_SUCCESS)
goto done;
(void) object_name_from_handle(NWAM_OBJECT_TYPE_NCU, ncu_h,
&realname);
ret = nwam_ncu_destroy(ncu_h, 0);
ncu_h = NULL;
} else if (cmd->cmd_res1_type == RT1_ENM) {
if ((ret = nwam_enm_read(name, 0, &enm_h)) != NWAM_SUCCESS)
goto done;
(void) object_name_from_handle(NWAM_OBJECT_TYPE_ENM, enm_h,
&realname);
ret = nwam_enm_destroy(enm_h, 0);
enm_h = NULL;
} else if (cmd->cmd_res1_type == RT1_LOC) {
if ((ret = nwam_loc_read(name, 0, &loc_h)) != NWAM_SUCCESS)
goto done;
(void) object_name_from_handle(NWAM_OBJECT_TYPE_LOC, loc_h,
&realname);
ret = nwam_loc_destroy(loc_h, 0);
loc_h = NULL;
} else if (cmd->cmd_res1_type == RT1_WLAN) {
if ((ret = nwam_known_wlan_read(name, 0, &wlan_h))
!= NWAM_SUCCESS)
goto done;
(void) object_name_from_handle(NWAM_OBJECT_TYPE_KNOWN_WLAN,
wlan_h, &realname);
ret = nwam_known_wlan_destroy(wlan_h, 0);
wlan_h = NULL;
} else if (cmd->cmd_res1_type == RT1_NCP) {
if ((ret = nwam_ncp_read(name, 0, &ncp_h)) != NWAM_SUCCESS)
goto done;
(void) object_name_from_handle(NWAM_OBJECT_TYPE_NCP, ncp_h,
&realname);
ret = nwam_ncp_destroy(ncp_h, 0);
ncp_h = NULL;
} else {
nerr("Destroy error: unknown object-type");
ret = NWAM_INVALID_HANDLE;
}
done:
if (ret == NWAM_ENTITY_IN_USE) {
nerr("Destroy error: active entity cannot be destroyed");
} else if (ret != NWAM_SUCCESS) {
nwamerr(ret, "Destroy error");
} else if (interactive_mode) {
(void) printf(gettext("Destroyed %s '%s'\n"),
(cmd->cmd_res2_type == RT2_NCU ?
rt2_to_str(cmd->cmd_res2_type) :
rt1_to_str(cmd->cmd_res1_type)),
realname != NULL ? realname : name);
}
free(name);
free(realname);
}
void
end_func(cmd_t *cmd)
{
if (need_to_commit)
do_commit();
if (!need_to_commit ||
(need_to_commit && (ask_yesno(B_FALSE,
"Configuration not saved; really end")) == 1)) {
if (current_scope == NWAM_SCOPE_GBL)
time_to_exit = B_TRUE;
do_cancel();
}
}
void
exit_func(cmd_t *cmd)
{
cmd_t *end_cmd;
if (need_to_commit) {
if ((end_cmd = alloc_cmd()) == NULL) {
nerr("Exit error");
return;
}
end_func(end_cmd);
free_cmd(end_cmd);
}
if (!need_to_commit)
time_to_exit = B_TRUE;
}
void
help_func(cmd_t *cmd)
{
int i;
if (cmd->cmd_argc == 0) {
(void) printf(gettext("commands:\n"));
for (i = CMD_MIN; i <= CMD_MAX; i++)
(void) printf("\t%s\n", helptab[i].cmd_usage);
return;
}
for (i = CMD_MIN; i <= CMD_MAX; i++) {
if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
long_usage(i);
return;
}
}
(void) fprintf(stderr, gettext("Unknown command: '%s'\n"),
cmd->cmd_argv[0]);
help_wrap();
}
void
revert_func(cmd_t *cmd)
{
nwam_error_t ret;
char *name = NULL;
nwam_ncu_type_t ncu_type;
nwam_object_type_t object_type = active_object_type();
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
if ((ret = nwam_ncu_get_ncu_type(ncu_h, &ncu_type))
!= NWAM_SUCCESS) {
nwamerr(ret, "Revert error: Get ncu type error");
return;
}
if ((ret = nwam_ncu_get_name(ncu_h, &name)) != NWAM_SUCCESS)
goto name_error;
nwam_ncu_free(ncu_h);
ncu_h = NULL;
ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
break;
case NWAM_OBJECT_TYPE_ENM:
if ((ret = nwam_enm_get_name(enm_h, &name)) != NWAM_SUCCESS)
goto name_error;
nwam_enm_free(enm_h);
enm_h = NULL;
ret = nwam_enm_read(name, 0, &enm_h);
break;
case NWAM_OBJECT_TYPE_LOC:
if ((ret = nwam_loc_get_name(loc_h, &name)) != NWAM_SUCCESS)
goto name_error;
nwam_loc_free(loc_h);
loc_h = NULL;
ret = nwam_loc_read(name, 0, &loc_h);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
if ((ret = nwam_known_wlan_get_name(wlan_h, &name))
!= NWAM_SUCCESS)
goto name_error;
nwam_known_wlan_free(wlan_h);
wlan_h = NULL;
ret = nwam_known_wlan_read(name, 0, &wlan_h);
break;
default:
ret = NWAM_INVALID_HANDLE;
break;
}
need_to_commit = B_FALSE;
if (ret != NWAM_SUCCESS) {
if (ret == NWAM_ENTITY_NOT_FOUND) {
nerr("%s '%s' does not exist to revert to, removing it",
nwam_object_type_to_string(object_type), name);
} else {
nwamerr(ret, "Revert error");
}
do_cancel();
}
free(name);
return;
name_error:
if (ret != NWAM_SUCCESS)
nwamerr(ret, "Revert error: get name error");
}
void
select_func(cmd_t *cmd)
{
nwam_error_t ret;
char *name, *realname = NULL;
assert(cmd->cmd_argc > 0);
if (current_scope == NWAM_SCOPE_NCP && cmd->cmd_res2_type != RT2_NCU) {
nerr("cannot select '%s' at this scope",
rt1_to_str(cmd->cmd_res1_type));
return;
}
name = trim_quotes(cmd->cmd_argv[0]);
switch (cmd->cmd_res1_type) {
case RT1_LOC:
ret = nwam_loc_read(name, 0, &loc_h);
if (ret == NWAM_SUCCESS) {
current_scope = NWAM_SCOPE_LOC;
(void) object_name_from_handle(NWAM_OBJECT_TYPE_LOC,
loc_h, &realname);
}
break;
case RT1_ENM:
ret = nwam_enm_read(name, 0, &enm_h);
if (ret == NWAM_SUCCESS) {
current_scope = NWAM_SCOPE_ENM;
(void) object_name_from_handle(NWAM_OBJECT_TYPE_ENM,
enm_h, &realname);
}
break;
case RT1_WLAN:
ret = nwam_known_wlan_read(name, 0, &wlan_h);
if (ret == NWAM_SUCCESS) {
current_scope = NWAM_SCOPE_WLAN;
(void) object_name_from_handle
(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan_h, &realname);
}
break;
case RT1_NCP:
if (cmd->cmd_res2_type == RT2_NCU) {
nwam_ncu_type_t ncu_type;
nwam_ncu_class_t ncu_class;
if (ncp_h == NULL) {
nerr("Select error: NCP has not been read");
free(name);
return;
}
ncu_class = (nwam_ncu_class_t)cmd->cmd_ncu_class_type;
ncu_type = nwam_ncu_class_to_type(ncu_class);
ret = nwam_ncu_read(ncp_h, name, ncu_type, 0, &ncu_h);
if (ret == NWAM_SUCCESS) {
current_scope = NWAM_SCOPE_NCU;
(void) object_name_from_handle
(NWAM_OBJECT_TYPE_NCU, ncu_h, &realname);
}
} else {
ret = nwam_ncp_read(name, 0, &ncp_h);
if (ret == NWAM_SUCCESS) {
current_scope = NWAM_SCOPE_NCP;
(void) object_name_from_handle
(NWAM_OBJECT_TYPE_NCP, ncp_h, &realname);
}
}
break;
default:
nerr("Select error: unknown object-type");
free(name);
return;
}
if (ret != NWAM_SUCCESS) {
nwamerr(ret, "Select error");
} else {
if (current_scope == NWAM_SCOPE_NCU) {
obj2_type = RT2_NCU;
(void) strlcpy(obj2_name,
realname != NULL ? realname : name,
sizeof (obj2_name));
} else {
(void) strlcpy(obj1_name,
realname != NULL ? realname : name,
sizeof (obj1_name));
obj1_type = cmd->cmd_res1_type;
}
}
free(name);
free(realname);
}
static const char *
pt_to_prop_name(nwam_object_type_t object_type, int pt_type)
{
int i;
prop_table_entry_t *prop_table = get_prop_table(object_type);
for (i = 0; prop_table[i].pte_name != NULL; i++) {
if (pt_type == prop_table[i].pte_type)
return (prop_table[i].pte_name);
}
return (NULL);
}
static int
prop_to_pt(nwam_object_type_t object_type, const char *prop)
{
int i;
prop_table_entry_t *prop_table = get_prop_table(object_type);
for (i = 0; prop_table[i].pte_name != NULL; i++) {
if (strcmp(prop, prop_table[i].pte_name) == 0)
return (prop_table[i].pte_type);
}
return (-1);
}
static nwam_value_type_t
prop_value_type(nwam_object_type_t object_type, const char *prop)
{
nwam_error_t ret;
nwam_value_type_t value_type;
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_get_prop_type(prop, &value_type);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_get_prop_type(prop, &value_type);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_get_prop_type(prop, &value_type);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_get_prop_type(prop, &value_type);
break;
default:
ret = NWAM_INVALID_HANDLE;
break;
}
if (ret != NWAM_SUCCESS)
value_type = NWAM_VALUE_TYPE_UNKNOWN;
return (value_type);
}
static nwam_value_t
str_to_nwam_value(nwam_object_type_t object_type, char *input_str, int pt_type,
boolean_t is_list_prop)
{
int i, n = 0, ret;
nwam_value_t data;
char **val;
int max_str_num;
nwam_value_type_t value_type;
int64_t *int_vals = NULL;
uint64_t *uint_vals = NULL;
boolean_t *boolean_vals = NULL;
max_str_num = strlen(input_str) / 2 + 1;
val = calloc(max_str_num, sizeof (char *));
if (val == NULL) {
nerr("Out of memory");
return (NULL);
}
if (is_list_prop) {
char *tmp, *next;
tmp = (char *)input_str;
while ((tmp = nwam_tokenize_by_unescaped_delim(tmp,
NWAM_VALUE_DELIMITER_CHAR, &next)) != NULL) {
val[n++] = trim_quotes(tmp);
tmp = next;
}
} else {
val[n++] = trim_quotes(input_str);
}
value_type = prop_value_type(object_type,
pt_to_prop_name(object_type, pt_type));
if (value_type == NWAM_VALUE_TYPE_INT64) {
int_vals = calloc(n, sizeof (int64_t));
if (int_vals == NULL) {
nerr("Out of memory");
array_free((void **)val, max_str_num);
return (NULL);
}
} else if (value_type == NWAM_VALUE_TYPE_UINT64) {
uint_vals = calloc(n, sizeof (uint64_t));
if (uint_vals == NULL) {
nerr("Out of memory");
array_free((void **)val, max_str_num);
return (NULL);
}
} else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
boolean_vals = calloc(n, sizeof (boolean_t));
if (boolean_vals == NULL) {
nerr("Out of memory");
array_free((void **)val, max_str_num);
return (NULL);
}
}
for (i = 0; i < n; i++) {
switch (value_type) {
case NWAM_VALUE_TYPE_STRING:
break;
case NWAM_VALUE_TYPE_INT64:
{
int_vals[i] = (int64_t)atoi(val[i]);
break;
}
case NWAM_VALUE_TYPE_UINT64:
{
uint64_t str_as_enum;
char *endptr;
ret = nwam_value_string_get_uint64(
pt_to_prop_name(object_type, pt_type),
val[i], &str_as_enum);
if (ret == NWAM_SUCCESS) {
uint_vals[i] = str_as_enum;
} else if (ret == NWAM_INVALID_ARG) {
uint_vals[i] = strtoul(val[i], &endptr, 10);
if (endptr == val[i]) {
free(uint_vals);
array_free((void **)val, max_str_num);
return (NULL);
}
} else {
free(uint_vals);
array_free((void **)val, max_str_num);
return (NULL);
}
break;
}
case NWAM_VALUE_TYPE_BOOLEAN:
boolean_vals[i] = str_to_boolean(val[i]);
break;
default:
array_free((void **)val, max_str_num);
return (NULL);
}
}
if (value_type == NWAM_VALUE_TYPE_STRING) {
ret = nwam_value_create_string_array(val, n, &data);
} else if (value_type == NWAM_VALUE_TYPE_INT64) {
ret = nwam_value_create_int64_array(int_vals, n, &data);
free(int_vals);
} else if (value_type == NWAM_VALUE_TYPE_UINT64) {
ret = nwam_value_create_uint64_array(uint_vals, n, &data);
free(uint_vals);
} else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
ret = nwam_value_create_boolean_array(boolean_vals, n, &data);
free(boolean_vals);
} else {
ret = NWAM_INVALID_HANDLE;
}
array_free((void **)val, max_str_num);
if (ret != NWAM_SUCCESS) {
nwamerr(ret, "Failed creating nwam_value");
return (NULL);
}
return (data);
}
#define NWAM_CHECKVALS_MAX 5
typedef struct prop_display_entry {
const char *pde_name;
const char *pde_checkname;
int64_t pde_checkvals[NWAM_CHECKVALS_MAX];
} prop_display_entry_t;
static prop_display_entry_t ncu_prop_display_entry_table[] = {
{ NWAM_NCU_PROP_PRIORITY_GROUP, NWAM_NCU_PROP_ACTIVATION_MODE,
{ NWAM_ACTIVATION_MODE_PRIORITIZED, -1 } },
{ NWAM_NCU_PROP_PRIORITY_MODE, NWAM_NCU_PROP_ACTIVATION_MODE,
{ NWAM_ACTIVATION_MODE_PRIORITIZED, -1 } },
{ NWAM_NCU_PROP_IPV4_ADDRSRC, NWAM_NCU_PROP_IP_VERSION,
{ IPV4_VERSION, -1 } },
{ NWAM_NCU_PROP_IPV4_ADDR, NWAM_NCU_PROP_IPV4_ADDRSRC,
{ NWAM_ADDRSRC_STATIC, -1 } },
{ NWAM_NCU_PROP_IPV4_DEFAULT_ROUTE, NWAM_NCU_PROP_IP_VERSION,
{ IPV4_VERSION, -1 } },
{ NWAM_NCU_PROP_IPV6_ADDRSRC, NWAM_NCU_PROP_IP_VERSION,
{ IPV6_VERSION, -1 } },
{ NWAM_NCU_PROP_IPV6_ADDR, NWAM_NCU_PROP_IPV6_ADDRSRC,
{ NWAM_ADDRSRC_STATIC, -1 } },
{ NWAM_NCU_PROP_IPV6_DEFAULT_ROUTE, NWAM_NCU_PROP_IP_VERSION,
{ IPV6_VERSION, -1 } },
{ NWAM_NCU_PROP_IP_PRIMARY, NWAM_NCU_PROP_IPV4_ADDRSRC,
{ NWAM_ADDRSRC_DHCP, -1 } },
{ NWAM_NCU_PROP_IP_REQHOST, NWAM_NCU_PROP_IPV4_ADDRSRC,
{ NWAM_ADDRSRC_DHCP, -1 } },
{ NULL, NULL, { -1 } }
};
static prop_display_entry_t enm_prop_display_entry_table[] = {
{ NWAM_ENM_PROP_CONDITIONS, NWAM_ENM_PROP_ACTIVATION_MODE,
{ NWAM_ACTIVATION_MODE_CONDITIONAL_ALL,
NWAM_ACTIVATION_MODE_CONDITIONAL_ANY, -1 } },
{ NULL, NULL, { -1 } }
};
static prop_display_entry_t loc_prop_display_entry_table[] = {
{ NWAM_LOC_PROP_CONDITIONS, NWAM_LOC_PROP_ACTIVATION_MODE,
{ NWAM_ACTIVATION_MODE_CONDITIONAL_ALL,
NWAM_ACTIVATION_MODE_CONDITIONAL_ANY, -1 } },
{ NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
{ NWAM_NAMESERVICES_DNS, -1 } },
{ NWAM_LOC_PROP_DNS_NAMESERVICE_DOMAIN,
NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
{ NWAM_CONFIGSRC_MANUAL, -1 } },
{ NWAM_LOC_PROP_DNS_NAMESERVICE_SERVERS,
NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
{ NWAM_CONFIGSRC_MANUAL, -1 } },
{ NWAM_LOC_PROP_DNS_NAMESERVICE_SEARCH,
NWAM_LOC_PROP_DNS_NAMESERVICE_CONFIGSRC,
{ NWAM_CONFIGSRC_MANUAL, -1 } },
{ NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
{ NWAM_NAMESERVICES_NIS, -1 } },
{ NWAM_LOC_PROP_NIS_NAMESERVICE_SERVERS,
NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
{ NWAM_CONFIGSRC_MANUAL, -1 } },
{ NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC, NWAM_LOC_PROP_NAMESERVICES,
{ NWAM_NAMESERVICES_LDAP, -1 } },
{ NWAM_LOC_PROP_LDAP_NAMESERVICE_SERVERS,
NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
{ NWAM_CONFIGSRC_MANUAL, -1 } },
{ NWAM_LOC_PROP_DEFAULT_DOMAIN, NWAM_LOC_PROP_NIS_NAMESERVICE_CONFIGSRC,
{ NWAM_CONFIGSRC_MANUAL, -1 } },
{ NWAM_LOC_PROP_DEFAULT_DOMAIN,
NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
{ NWAM_CONFIGSRC_MANUAL, -1 } },
{ NULL, NULL, { -1 } }
};
static prop_display_entry_t wlan_prop_display_entry_table[] = {
{ NULL, NULL, { -1 } }
};
static prop_display_entry_t *
get_prop_display_table(nwam_object_type_t object_type)
{
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
return (ncu_prop_display_entry_table);
case NWAM_OBJECT_TYPE_LOC:
return (loc_prop_display_entry_table);
case NWAM_OBJECT_TYPE_ENM:
return (enm_prop_display_entry_table);
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
return (wlan_prop_display_entry_table);
}
return (NULL);
}
static boolean_t
show_prop_test(nwam_object_type_t object_type, const char *prop,
prop_display_entry_t *display_list, char **checked_props, int num_checked)
{
nwam_error_t ret;
nwam_value_t prop_val;
nwam_value_type_t prop_type;
int i, j, k;
boolean_t prop_found = B_FALSE, show_prop = B_FALSE;
for (i = 0; i < num_checked; i++) {
if (strcmp(prop, checked_props[i]) == 0) {
free(checked_props);
return (B_FALSE);
}
}
for (i = 0; display_list[i].pde_name != NULL; i++) {
if (strcmp(prop, display_list[i].pde_name) != 0)
continue;
prop_found = B_TRUE;
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_get_prop_value(ncu_h,
display_list[i].pde_checkname, &prop_val);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_get_prop_value(loc_h,
display_list[i].pde_checkname, &prop_val);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_get_prop_value(enm_h,
display_list[i].pde_checkname, &prop_val);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
return (B_TRUE);
default:
ret = NWAM_INVALID_HANDLE;
break;
}
if (ret != NWAM_SUCCESS)
continue;
if (nwam_value_get_type(prop_val, &prop_type) != NWAM_SUCCESS)
continue;
if (prop_type == NWAM_VALUE_TYPE_UINT64) {
uint64_t *prop_uvals;
int64_t *check_uvals;
uint_t numvals;
if (nwam_value_get_uint64_array(prop_val, &prop_uvals,
&numvals) != NWAM_SUCCESS) {
nwam_value_free(prop_val);
continue;
}
for (j = 0; j < numvals; j++) {
check_uvals = display_list[i].pde_checkvals;
for (k = 0; check_uvals[k] != -1; k++) {
if (prop_uvals[j] ==
(uint64_t)check_uvals[k]) {
show_prop = B_TRUE;
goto next_rule;
}
}
}
} else if (prop_type == NWAM_VALUE_TYPE_BOOLEAN) {
boolean_t bval;
if (nwam_value_get_boolean(prop_val, &bval) !=
NWAM_SUCCESS) {
nwam_value_free(prop_val);
continue;
}
for (k = 0;
display_list[i].pde_checkvals[k] != -1;
k++) {
if (bval == (boolean_t)
display_list[i].pde_checkvals[k]) {
show_prop = B_TRUE;
goto next_rule;
}
}
}
next_rule:
nwam_value_free(prop_val);
if (show_prop) {
char **newprops = realloc(checked_props,
++num_checked * sizeof (char *));
if (newprops == NULL) {
free(checked_props);
return (B_FALSE);
}
checked_props = newprops;
checked_props[num_checked - 1] = (char *)prop;
return (show_prop_test(object_type,
display_list[i].pde_checkname, display_list,
checked_props, num_checked));
}
}
free(checked_props);
if (prop_found)
return (B_FALSE);
else
return (B_TRUE);
}
static boolean_t
is_prop_read_only(nwam_object_type_t object_type, const char *prop)
{
boolean_t ro;
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
if (nwam_ncu_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
return (B_TRUE);
break;
case NWAM_OBJECT_TYPE_ENM:
if (nwam_enm_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
return (B_TRUE);
break;
case NWAM_OBJECT_TYPE_LOC:
if (nwam_loc_prop_read_only(prop, &ro) == NWAM_SUCCESS && ro)
return (B_TRUE);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
return (B_FALSE);
}
return (B_FALSE);
}
static boolean_t
is_prop_multivalued(nwam_object_type_t object_type, const char *prop)
{
nwam_error_t ret;
boolean_t multi;
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_prop_multivalued(prop, &multi);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_prop_multivalued(prop, &multi);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_prop_multivalued(prop, &multi);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_prop_multivalued(prop, &multi);
break;
default:
ret = NWAM_INVALID_HANDLE;
break;
}
if (ret != NWAM_SUCCESS)
multi = B_FALSE;
return (multi);
}
static void
invalid_set_prop_msg(const char *prop, nwam_error_t err)
{
const char *description;
if (err == NWAM_SUCCESS)
return;
if (err != NWAM_ENTITY_INVALID_VALUE) {
nwamerr(err, "Set error");
return;
}
switch (active_object_type()) {
case NWAM_OBJECT_TYPE_NCU:
(void) nwam_ncu_get_prop_description(prop, &description);
break;
case NWAM_OBJECT_TYPE_LOC:
(void) nwam_loc_get_prop_description(prop, &description);
break;
case NWAM_OBJECT_TYPE_ENM:
(void) nwam_enm_get_prop_description(prop, &description);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
(void) nwam_known_wlan_get_prop_description(prop,
&description);
break;
}
nerr("Set error: invalid value\n'%s' %s", prop, description);
}
void
set_func(cmd_t *cmd)
{
int pt_type = cmd->cmd_prop_type;
nwam_error_t ret = NWAM_SUCCESS;
nwam_value_t prop_value;
const char *prop;
boolean_t is_listprop = B_FALSE;
nwam_object_type_t object_type;
prop_display_entry_t *prop_table;
char **checked = NULL;
assert(cmd->cmd_argc > 0);
object_type = active_object_type();
prop_table = get_prop_display_table(object_type);
if ((prop = pt_to_prop_name(object_type, pt_type)) == NULL) {
nerr("Set error: invalid %s property: '%s'",
scope_to_str(current_scope), pt_to_str(pt_type));
return;
}
if (is_prop_read_only(object_type, prop)) {
nerr("Set error: property '%s' is read-only", prop);
return;
}
if (!show_prop_test(object_type, prop, prop_table, checked, 0)) {
if (interactive_mode) {
(void) printf(gettext("setting property '%s' "
"has no effect\n"), prop);
}
}
is_listprop = is_prop_multivalued(object_type, prop);
prop_value = str_to_nwam_value(object_type, cmd->cmd_argv[0], pt_type,
is_listprop);
if (prop_value == NULL) {
invalid_set_prop_msg(prop, NWAM_ENTITY_INVALID_VALUE);
return;
}
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_set_prop_value(ncu_h, prop, prop_value);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_set_prop_value(loc_h, prop, prop_value);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_set_prop_value(enm_h, prop, prop_value);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_set_prop_value(wlan_h, prop, prop_value);
break;
}
nwam_value_free(prop_value);
if (ret == NWAM_SUCCESS)
need_to_commit = B_TRUE;
else
invalid_set_prop_msg(prop, ret);
}
static int
list_callback(nwam_object_type_t object_type, void *handle,
boolean_t *list_msgp, const char *msg)
{
nwam_error_t ret;
char *name;
nwam_ncu_class_t class;
if (*list_msgp) {
(void) printf("%s:\n", msg);
*list_msgp = B_FALSE;
}
ret = object_name_from_handle(object_type, handle, &name);
if (ret != NWAM_SUCCESS) {
nwamerr(ret, "List error: failed to get name");
return (1);
}
if (object_type == NWAM_OBJECT_TYPE_NCU) {
if ((ret = nwam_ncu_get_ncu_class(handle, &class))
!= NWAM_SUCCESS) {
nwamerr(ret, "List error: failed to get ncu class");
free(name);
return (1);
} else {
(void) printf("\t%s",
propval_to_str(NWAM_NCU_PROP_CLASS, class));
}
}
(void) printf("\t%s\n", name);
free(name);
return (0);
}
static int
list_loc_callback(nwam_loc_handle_t loc, void *arg)
{
return (list_callback(NWAM_OBJECT_TYPE_LOC, loc, arg, "Locations"));
}
static int
list_enm_callback(nwam_enm_handle_t enm, void *arg)
{
return (list_callback(NWAM_OBJECT_TYPE_ENM, enm, arg, "ENMs"));
}
static int
list_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
{
return (list_callback(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan, arg, "WLANs"));
}
static int
list_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
{
return (list_callback(NWAM_OBJECT_TYPE_NCP, ncp, arg, "NCPs"));
}
static int
list_ncu_callback(nwam_ncu_handle_t ncu, void *arg)
{
return (list_callback(NWAM_OBJECT_TYPE_NCU, ncu, arg, "NCUs"));
}
static const char *
str2str(void *s, const char *prop, char *str)
{
(void) snprintf(str, NWAM_MAX_VALUE_LEN, "%s", s);
return (str);
}
static const char *
str2qstr(void *s, const char *prop, char *qstr)
{
(void) snprintf(qstr, NWAM_MAX_VALUE_LEN, "\"%s\"", s);
return (qstr);
}
static const char *
int2str(void *in, const char *prop, char *instr)
{
(void) snprintf(instr, NWAM_MAX_VALUE_LEN, "%lld", *((int64_t *)in));
return (instr);
}
static const char *
uint2str(void *uin, const char *prop, char *uintstr)
{
if (nwam_uint64_get_value_string(prop, *((uint64_t *)uin),
(const char **)&uintstr) != NWAM_SUCCESS) {
(void) snprintf(uintstr, NWAM_MAX_VALUE_LEN, "%lld",
*((uint64_t *)uin));
}
return (uintstr);
}
static const char *
bool2str(void *bool, const char *prop, char *boolstr)
{
(void) snprintf(boolstr, NWAM_MAX_VALUE_LEN, "%s",
*((boolean_t *)bool) ? "true" : "false");
return (boolstr);
}
static void
output_prop_val(const char *prop_name, nwam_value_t value, FILE *wf,
boolean_t quoted_strings)
{
nwam_value_type_t value_type;
uint_t num;
char **svals;
uint64_t *uvals;
int64_t *ivals;
boolean_t *bvals;
const char *(*tostr)(void *, const char *, char *);
char str[NWAM_MAX_VALUE_LEN];
int i;
if (nwam_value_get_type(value, &value_type) != NWAM_SUCCESS) {
nerr("Get value type error");
return;
}
if (value_type == NWAM_VALUE_TYPE_STRING) {
if (nwam_value_get_string_array(value, &svals, &num) !=
NWAM_SUCCESS) {
nerr("Get string array error");
return;
}
tostr = quoted_strings ? str2qstr : str2str;
} else if (value_type == NWAM_VALUE_TYPE_INT64) {
if (nwam_value_get_int64_array(value, &ivals, &num) !=
NWAM_SUCCESS) {
nerr("Get int64 array error");
return;
}
tostr = int2str;
} else if (value_type == NWAM_VALUE_TYPE_UINT64) {
if (nwam_value_get_uint64_array(value, &uvals, &num) !=
NWAM_SUCCESS) {
nerr("Get uint64 array error");
return;
}
tostr = uint2str;
} else if (value_type == NWAM_VALUE_TYPE_BOOLEAN) {
if (nwam_value_get_boolean_array(value, &bvals, &num) !=
NWAM_SUCCESS) {
nerr("Get boolean array error");
return;
}
tostr = bool2str;
} else {
nerr("Unknown value type");
return;
}
for (i = 0; i < num; i++) {
void *val = NULL;
if (value_type == NWAM_VALUE_TYPE_STRING)
val = svals[i];
else if (value_type == NWAM_VALUE_TYPE_UINT64)
val = &(uvals[i]);
else if (value_type == NWAM_VALUE_TYPE_INT64)
val = &(ivals[i]);
else if (value_type == NWAM_VALUE_TYPE_BOOLEAN)
val = &(bvals[i]);
(void) fprintf(wf, "%s%s", tostr(val, prop_name, str),
i != num-1 ? NWAM_VALUE_DELIMITER_STR : "");
}
}
static int
output_propname_common(const char *prop, nwam_value_t values, void *arg,
int width)
{
FILE *of = (arg == NULL) ? stdout : arg;
if (arg == NULL)
(void) fprintf(of, "\t%-*s\t", width, prop);
else
(void) fprintf(of, "%s=", prop);
if (values != NULL)
output_prop_val(prop, values, of, B_TRUE);
(void) fprintf(of, "\n");
return (0);
}
static int
output_propname(const char *prop, nwam_value_t values, void *arg)
{
return (output_propname_common(prop, values, arg, 16));
}
static int
output_loc_propname(const char *prop, nwam_value_t values, void *arg)
{
return (output_propname_common(prop, values, arg, 25));
}
static nwam_error_t
listprop(nwam_object_type_t object_type, void *handle, const char *name,
boolean_t all_props, nwam_ncp_handle_t ncp, nwam_ncu_type_t ncu_type)
{
nwam_error_t ret;
char *lname = NULL, *realname = NULL;
boolean_t lhandle = B_FALSE;
const char **props = NULL;
uint_t prop_num;
int i;
nwam_value_t vals;
if (handle == NULL) {
lname = trim_quotes(name);
switch (object_type) {
case NWAM_OBJECT_TYPE_NCP:
if ((ret = nwam_ncp_read(lname, 0,
(nwam_ncp_handle_t *)&handle)) != NWAM_SUCCESS)
goto readfail;
break;
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_read(ncp, lname, ncu_type, 0,
(nwam_ncu_handle_t *)&handle);
if (ret == NWAM_ENTITY_MULTIPLE_VALUES) {
if ((ret = listprop(object_type, NULL, lname,
all_props, ncp, NWAM_NCU_TYPE_LINK))
!= NWAM_SUCCESS)
goto done;
ret = listprop(object_type, NULL, lname,
all_props, ncp, NWAM_NCU_TYPE_INTERFACE);
goto done;
} else if (ret != NWAM_SUCCESS) {
goto readfail;
}
break;
case NWAM_OBJECT_TYPE_LOC:
if ((ret = nwam_loc_read(lname, 0,
(nwam_loc_handle_t *)&handle)) != NWAM_SUCCESS)
goto readfail;
break;
case NWAM_OBJECT_TYPE_ENM:
if ((ret = nwam_enm_read(lname, 0,
(nwam_enm_handle_t *)&handle)) != NWAM_SUCCESS)
goto readfail;
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
if ((ret = nwam_known_wlan_read(lname, 0,
(nwam_known_wlan_handle_t *)&handle))
!= NWAM_SUCCESS)
goto readfail;
break;
}
lhandle = B_TRUE;
}
if ((ret = object_name_from_handle(object_type, handle, &realname))
!= NWAM_SUCCESS)
goto done;
switch (object_type) {
case NWAM_OBJECT_TYPE_NCP:
{
boolean_t list_msg = B_TRUE;
ret = nwam_ncp_walk_ncus(handle, list_ncu_callback, &list_msg,
NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
goto done;
}
case NWAM_OBJECT_TYPE_NCU:
{
nwam_ncu_type_t ncu_type;
nwam_ncu_class_t ncu_class;
if ((ret = nwam_ncu_get_ncu_type(handle, &ncu_type))
!= NWAM_SUCCESS)
goto done;
if ((ret = nwam_ncu_get_ncu_class(handle, &ncu_class))
!= NWAM_SUCCESS)
goto done;
ret = nwam_ncu_get_default_proplist(ncu_type, ncu_class, &props,
&prop_num);
break;
}
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_get_default_proplist(&props, &prop_num);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_get_default_proplist(&props, &prop_num);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_get_default_proplist(&props, &prop_num);
break;
}
if (ret != NWAM_SUCCESS)
goto done;
(void) printf("%s:%s\n", nwam_object_type_to_string(object_type),
realname);
for (i = 0; i < prop_num; i++) {
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_get_prop_value(handle, props[i], &vals);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_get_prop_value(handle, props[i], &vals);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_get_prop_value(handle, props[i], &vals);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_get_prop_value(handle, props[i],
&vals);
break;
}
if (ret != NWAM_SUCCESS) {
if (!all_props)
continue;
else if (ret != NWAM_ENTITY_NOT_FOUND)
continue;
}
if (object_type == NWAM_OBJECT_TYPE_LOC)
output_loc_propname(props[i], vals, NULL);
else
output_propname(props[i], vals, NULL);
nwam_value_free(vals);
}
done:
free(lname);
free(realname);
if (props != NULL)
free(props);
if (lhandle) {
switch (object_type) {
case NWAM_OBJECT_TYPE_NCP:
nwam_ncp_free(handle);
break;
case NWAM_OBJECT_TYPE_NCU:
nwam_ncu_free(handle);
break;
case NWAM_OBJECT_TYPE_LOC:
nwam_loc_free(handle);
break;
case NWAM_OBJECT_TYPE_ENM:
nwam_enm_free(handle);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
nwam_known_wlan_free(handle);
break;
}
}
if (ret == NWAM_ENTITY_NOT_FOUND)
ret = NWAM_SUCCESS;
return (ret);
readfail:
free(lname);
return (ret);
}
void
list_func(cmd_t *cmd)
{
nwam_error_t ret = NWAM_SUCCESS;
boolean_t list_msg = B_TRUE;
boolean_t list_loc = B_FALSE, list_enm = B_FALSE;
boolean_t list_ncp = B_FALSE, list_ncu = B_FALSE;
boolean_t list_wlan = B_FALSE;
boolean_t all_props = B_FALSE;
boolean_t list_props = B_FALSE;
if (current_scope == NWAM_SCOPE_GBL) {
if (cmd->cmd_res1_type == -1) {
nerr("'list' requires an object to be specified with "
"the -a option in the global scope");
return;
}
if (cmd->cmd_res1_type == RT1_LOC) {
list_props = B_TRUE;
list_loc = B_TRUE;
} else if (cmd->cmd_res1_type == RT1_ENM) {
list_props = B_TRUE;
list_enm = B_TRUE;
} else if (cmd->cmd_res1_type == RT1_WLAN) {
list_props = B_TRUE;
list_wlan = B_TRUE;
} else if (cmd->cmd_res1_type == RT1_NCP) {
list_ncp = B_TRUE;
list_props = B_TRUE;
} else {
list_loc = B_TRUE;
list_enm = B_TRUE;
list_wlan = B_TRUE;
list_ncp = B_TRUE;
}
}
if ((current_scope == NWAM_SCOPE_LOC ||
current_scope == NWAM_SCOPE_ENM ||
current_scope == NWAM_SCOPE_WLAN ||
current_scope == NWAM_SCOPE_NCU) &&
(cmd->cmd_argc >= 1 && cmd->cmd_res1_type != -1)) {
nerr("Additional options are not allowed with the -a option "
"at this scope");
return;
}
if (current_scope == NWAM_SCOPE_LOC) {
list_loc = B_TRUE;
list_props = B_TRUE;
}
if (current_scope == NWAM_SCOPE_ENM) {
list_enm = B_TRUE;
list_props = B_TRUE;
}
if (current_scope == NWAM_SCOPE_WLAN) {
list_wlan = B_TRUE;
list_props = B_TRUE;
}
if (current_scope == NWAM_SCOPE_NCP) {
if (cmd->cmd_res1_type == RT1_ENM ||
cmd->cmd_res1_type == RT1_LOC ||
cmd->cmd_res1_type == RT1_WLAN) {
nerr("only ncu can be listed at this scope");
return;
}
if (cmd->cmd_res2_type == RT2_NCU) {
list_ncu = B_TRUE;
list_props = B_TRUE;
} else {
list_ncp = B_TRUE;
list_props = B_TRUE;
}
}
if (current_scope == NWAM_SCOPE_NCU) {
list_ncu = B_TRUE;
list_props = B_TRUE;
}
if (cmd->cmd_res1_type == -1 || cmd->cmd_argc == 2) {
int c, argc = 1;
char **argv;
optind = 0;
if (cmd->cmd_res1_type == -1)
argv = cmd->cmd_argv;
else
argv = &(cmd->cmd_argv[1]);
while ((c = getopt(argc, argv, "a")) != EOF) {
switch (c) {
case 'a':
all_props = B_TRUE;
break;
default:
command_usage(CMD_LIST);
return;
}
}
if (cmd->cmd_res1_type == -1)
cmd->cmd_argv[0] = NULL;
}
if (list_ncp) {
list_msg = B_TRUE;
if (list_props) {
ret = listprop(NWAM_OBJECT_TYPE_NCP, ncp_h,
cmd->cmd_argv[0], all_props, NULL, -1);
} else {
ret = nwam_walk_ncps(list_ncp_callback, &list_msg, 0,
NULL);
}
if (ret != NWAM_SUCCESS)
goto done;
}
if (list_ncu) {
list_msg = B_TRUE;
if (ncp_h == NULL) {
nerr("NCP has not been read");
return;
}
if (list_props) {
nwam_ncu_class_t ncu_class;
nwam_ncu_type_t ncu_type;
if (ncu_h == NULL) {
ncu_class = (nwam_ncu_class_t)
cmd->cmd_ncu_class_type;
ncu_type = nwam_ncu_class_to_type(ncu_class);
} else {
if ((ret = nwam_ncu_get_ncu_type(ncu_h,
&ncu_type)) != NWAM_SUCCESS)
goto done;
}
ret = listprop(NWAM_OBJECT_TYPE_NCU, ncu_h,
cmd->cmd_argv[0], all_props, ncp_h, ncu_type);
if (ret != NWAM_SUCCESS)
goto done;
}
}
if (list_loc) {
list_msg = B_TRUE;
if (list_props) {
ret = listprop(NWAM_OBJECT_TYPE_LOC, loc_h,
cmd->cmd_argv[0], all_props, NULL, -1);
} else {
ret = nwam_walk_locs(list_loc_callback, &list_msg,
NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
}
if (ret != NWAM_SUCCESS)
goto done;
}
if (list_enm) {
list_msg = B_TRUE;
if (list_props) {
ret = listprop(NWAM_OBJECT_TYPE_ENM, enm_h,
cmd->cmd_argv[0], all_props, NULL, -1);
} else {
ret = nwam_walk_enms(list_enm_callback, &list_msg,
NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
}
if (ret != NWAM_SUCCESS)
goto done;
}
if (list_wlan) {
list_msg = B_TRUE;
if (list_props) {
ret = listprop(NWAM_OBJECT_TYPE_KNOWN_WLAN, wlan_h,
cmd->cmd_argv[0], all_props, NULL, -1);
} else {
ret = nwam_walk_known_wlans(list_wlan_callback,
&list_msg, NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER,
NULL);
}
if (ret != NWAM_SUCCESS)
goto done;
}
done:
if (ret != NWAM_SUCCESS)
nwamerr(ret, "List error");
}
static int
write_export_command(nwam_object_type_t object_type, const char *prop,
nwam_value_t values, FILE *of)
{
if (is_prop_read_only(object_type, prop))
return (0);
(void) fprintf(of, "set ");
output_propname(prop, values, of);
return (0);
}
static int
export_ncu_callback(nwam_ncu_handle_t ncu, void *arg)
{
char *name;
const char **props;
nwam_ncu_type_t type;
nwam_ncu_class_t class;
nwam_value_t vals;
nwam_error_t ret;
uint_t num;
int i;
FILE *of = arg;
assert(of != NULL);
if ((ret = nwam_ncu_get_ncu_type(ncu, &type)) != NWAM_SUCCESS)
return (ret);
if ((ret = nwam_ncu_get_ncu_class(ncu, &class)) != NWAM_SUCCESS)
return (ret);
if ((ret = nwam_ncu_get_name(ncu, &name)) != NWAM_SUCCESS)
return (ret);
(void) fprintf(of, "create ncu %s \"%s\"\n",
propval_to_str(NWAM_NCU_PROP_CLASS, class), name);
free(name);
if ((ret = nwam_ncu_get_default_proplist(type, class, &props, &num))
!= NWAM_SUCCESS)
return (ret);
for (i = 0; i < num; i++) {
ret = nwam_ncu_get_prop_value(ncu, props[i], &vals);
if (ret == NWAM_SUCCESS) {
write_export_command(NWAM_OBJECT_TYPE_NCU, props[i],
vals, of);
nwam_value_free(vals);
}
}
(void) fprintf(of, "end\n");
free(props);
return (0);
}
static int
export_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
{
char *name;
nwam_error_t ret;
FILE *of = arg;
assert(of != NULL);
if ((ret = nwam_ncp_get_name(ncp, &name)) != NWAM_SUCCESS)
return (ret);
if (NWAM_NCP_AUTOMATIC(name)) {
free(name);
return (0);
}
(void) fprintf(of, "create ncp \"%s\"\n", name);
free(name);
ret = nwam_ncp_walk_ncus(ncp, export_ncu_callback, of,
NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
if (ret != NWAM_SUCCESS) {
nwamerr(ret, "Export ncp error: failed to walk ncus");
return (ret);
}
(void) fprintf(of, "end\n");
return (0);
}
static int
export_enm_callback(nwam_enm_handle_t enm, void *arg)
{
char *name;
const char **props;
nwam_value_t vals;
nwam_error_t ret;
uint_t num;
int i;
FILE *of = arg;
assert(of != NULL);
if ((ret = nwam_enm_get_name(enm, &name)) != NWAM_SUCCESS)
return (ret);
(void) fprintf(of, "create enm \"%s\"\n", name);
free(name);
if ((ret = nwam_enm_get_default_proplist(&props, &num)) != NWAM_SUCCESS)
return (ret);
for (i = 0; i < num; i++) {
ret = nwam_enm_get_prop_value(enm, props[i], &vals);
if (ret == NWAM_SUCCESS) {
write_export_command(NWAM_OBJECT_TYPE_ENM, props[i],
vals, of);
nwam_value_free(vals);
}
}
(void) fprintf(of, "end\n");
free(props);
return (0);
}
static int
export_loc_callback(nwam_loc_handle_t loc, void *arg)
{
char *name;
const char **props;
nwam_value_t vals;
nwam_error_t ret;
uint_t num;
int i;
FILE *of = arg;
assert(of != NULL);
if ((ret = nwam_loc_get_name(loc, &name)) != NWAM_SUCCESS)
return (ret);
if (NWAM_LOC_NAME_PRE_DEFINED(name)) {
free(name);
return (0);
}
(void) fprintf(of, "create loc \"%s\"\n", name);
free(name);
if ((ret = nwam_loc_get_default_proplist(&props, &num)) != NWAM_SUCCESS)
return (ret);
for (i = 0; i < num; i++) {
ret = nwam_loc_get_prop_value(loc, props[i], &vals);
if (ret == NWAM_SUCCESS) {
write_export_command(NWAM_OBJECT_TYPE_LOC, props[i],
vals, of);
nwam_value_free(vals);
}
}
(void) fprintf(of, "end\n");
free(props);
return (0);
}
static int
export_wlan_callback(nwam_known_wlan_handle_t wlan, void *arg)
{
char *name;
const char **props;
nwam_value_t vals;
nwam_error_t ret;
uint_t num;
int i;
FILE *of = arg;
assert(of != NULL);
if ((ret = nwam_known_wlan_get_name(wlan, &name)) != NWAM_SUCCESS)
return (ret);
(void) fprintf(of, "create wlan \"%s\"\n", name);
free(name);
if ((ret = nwam_known_wlan_get_default_proplist(&props, &num))
!= NWAM_SUCCESS)
return (ret);
for (i = 0; i < num; i++) {
ret = nwam_known_wlan_get_prop_value(wlan, props[i], &vals);
if (ret == NWAM_SUCCESS) {
write_export_command(NWAM_OBJECT_TYPE_KNOWN_WLAN,
props[i], vals, of);
nwam_value_free(vals);
}
}
(void) fprintf(of, "end\n");
free(props);
return (0);
}
void
export_func(cmd_t *cmd)
{
int c;
boolean_t need_to_close = B_FALSE, write_to_file = B_FALSE;
boolean_t add_destroy = B_FALSE, lhandle = B_FALSE;
char filepath[MAXPATHLEN];
nwam_error_t ret = NWAM_SUCCESS;
FILE *of = NULL;
boolean_t export_ncp = B_FALSE, export_ncu = B_FALSE;
boolean_t export_loc = B_FALSE, export_enm = B_FALSE;
boolean_t export_wlan = B_FALSE;
char *name = NULL;
filepath[0] = '\0';
optind = 0;
while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "df:")) != EOF) {
switch (c) {
case 'f':
write_to_file = B_TRUE;
break;
case 'd':
add_destroy = B_TRUE;
break;
default:
command_usage(CMD_EXPORT);
return;
}
}
if (!write_to_file) {
of = stdout;
} else {
(void) strlcpy(filepath,
(add_destroy ? cmd->cmd_argv[2] : cmd->cmd_argv[1]),
sizeof (filepath));
if ((of = fopen(filepath, "w")) == NULL) {
nerr(gettext("opening file '%s': %s"), filepath,
strerror(errno));
goto done;
}
setbuf(of, NULL);
need_to_close = B_TRUE;
}
if (add_destroy) {
if (current_scope == NWAM_SCOPE_GBL) {
(void) fprintf(of, "destroy -a\n");
} else {
nerr("Option -d is not allowed in non-global scope");
goto done;
}
}
if (((current_scope == NWAM_SCOPE_LOC ||
current_scope == NWAM_SCOPE_ENM ||
current_scope == NWAM_SCOPE_WLAN ||
current_scope == NWAM_SCOPE_NCU) &&
cmd->cmd_argc != 0 && !write_to_file)) {
nerr("'export' does not take arguments at this scope");
goto done;
}
if (current_scope == NWAM_SCOPE_NCP) {
if (cmd->cmd_res1_type == RT1_ENM ||
cmd->cmd_res1_type == RT1_LOC ||
cmd->cmd_res1_type == RT1_WLAN) {
nerr("only ncu can be exported at this scope");
goto done;
}
}
switch (current_scope) {
case NWAM_SCOPE_GBL:
name = (write_to_file ? trim_quotes(cmd->cmd_argv[2]) :
trim_quotes(cmd->cmd_argv[0]));
switch (cmd->cmd_res1_type) {
case RT1_LOC:
export_loc = B_TRUE;
break;
case RT1_ENM:
export_enm = B_TRUE;
break;
case RT1_WLAN:
export_wlan = B_TRUE;
break;
case RT1_NCP:
export_ncp = B_TRUE;
if (cmd->cmd_res2_type == RT2_NCU) {
nerr("cannot export ncu at from global scope");
goto done;
}
break;
default:
export_loc = B_TRUE;
export_enm = B_TRUE;
export_wlan = B_TRUE;
export_ncp = B_TRUE;
free(name);
name = NULL;
break;
}
break;
case NWAM_SCOPE_LOC:
export_loc = B_TRUE;
ret = nwam_loc_get_name(loc_h, &name);
if (ret != NWAM_SUCCESS)
goto fail;
break;
case NWAM_SCOPE_ENM:
export_enm = B_TRUE;
ret = nwam_enm_get_name(enm_h, &name);
if (ret != NWAM_SUCCESS)
goto fail;
break;
case NWAM_SCOPE_WLAN:
export_wlan = B_TRUE;
ret = nwam_known_wlan_get_name(wlan_h, &name);
if (ret != NWAM_SUCCESS)
goto fail;
break;
case NWAM_SCOPE_NCP:
if (cmd->cmd_res2_type == RT2_NCU) {
export_ncu = B_TRUE;
name = (write_to_file ? trim_quotes(cmd->cmd_argv[2]) :
trim_quotes(cmd->cmd_argv[0]));
} else {
export_ncp = B_TRUE;
ret = nwam_ncp_get_name(ncp_h, &name);
if (ret != NWAM_SUCCESS)
goto fail;
}
break;
case NWAM_SCOPE_NCU:
export_ncu = B_TRUE;
ret = nwam_ncu_get_name(ncu_h, &name);
if (ret != NWAM_SUCCESS)
goto fail;
break;
default:
nerr("Invalid scope");
goto done;
}
if (export_ncp) {
lhandle = B_FALSE;
if (name == NULL) {
ret = nwam_walk_ncps(export_ncp_callback, of, 0, NULL);
} else if (NWAM_NCP_AUTOMATIC(name)) {
nerr("'%s' ncp cannot be exported", name);
goto fail;
} else {
if (ncp_h == NULL) {
ret = nwam_ncp_read(name, 0, &ncp_h);
if (ret != NWAM_SUCCESS)
goto fail;
lhandle = B_TRUE;
}
ret = export_ncp_callback(ncp_h, of);
if (lhandle) {
nwam_ncp_free(ncp_h);
ncp_h = NULL;
}
}
if (ret != NWAM_SUCCESS)
goto fail;
}
if (export_ncu) {
if (name == NULL) {
ret = nwam_ncp_walk_ncus(ncp_h, export_ncu_callback, of,
NWAM_FLAG_NCU_TYPE_CLASS_ALL, NULL);
} else {
if (ncu_h == NULL) {
nwam_ncu_type_t ncu_type;
nwam_ncu_class_t ncu_class;
ncu_class = (nwam_ncu_class_t)
cmd->cmd_ncu_class_type;
ncu_type = nwam_ncu_class_to_type(ncu_class);
ret = nwam_ncu_read(ncp_h, name,
ncu_type, 0, &ncu_h);
if (ret == NWAM_SUCCESS) {
ret = export_ncu_callback(ncu_h, of);
nwam_ncu_free(ncu_h);
ncu_h = NULL;
} else if (ret == NWAM_ENTITY_MULTIPLE_VALUES) {
ret = nwam_ncu_read(ncp_h, name,
NWAM_NCU_TYPE_LINK, 0, &ncu_h);
if (ret != NWAM_SUCCESS)
goto fail;
ret = export_ncu_callback(ncu_h, of);
nwam_ncu_free(ncu_h);
ncu_h = NULL;
ret = nwam_ncu_read(ncp_h, name,
NWAM_NCU_TYPE_INTERFACE, 0, &ncu_h);
if (ret != NWAM_SUCCESS)
goto fail;
ret = export_ncu_callback(ncu_h, of);
nwam_ncu_free(ncu_h);
ncu_h = NULL;
} else {
goto fail;
}
} else {
ret = export_ncu_callback(ncu_h, of);
}
}
if (ret != NWAM_SUCCESS)
goto fail;
}
if (export_loc) {
lhandle = B_FALSE;
if (name == NULL) {
ret = nwam_walk_locs(export_loc_callback, of,
NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
} else if (NWAM_LOC_NAME_PRE_DEFINED(name)) {
nerr("'%s' loc cannot be exported", name);
goto fail;
} else {
if (loc_h == NULL) {
ret = nwam_loc_read(name, 0, &loc_h);
if (ret != NWAM_SUCCESS)
goto fail;
lhandle = B_TRUE;
}
ret = export_loc_callback(loc_h, of);
if (lhandle) {
nwam_loc_free(loc_h);
loc_h = NULL;
}
}
if (ret != NWAM_SUCCESS)
goto fail;
}
if (export_enm) {
lhandle = B_FALSE;
if (name == NULL) {
ret = nwam_walk_enms(export_enm_callback, of,
NWAM_FLAG_ACTIVATION_MODE_ALL, NULL);
} else {
if (enm_h == NULL) {
ret = nwam_enm_read(name, 0, &enm_h);
if (ret != NWAM_SUCCESS)
goto fail;
lhandle = B_TRUE;
}
ret = export_enm_callback(enm_h, of);
if (lhandle) {
nwam_enm_free(enm_h);
enm_h = NULL;
}
}
if (ret != NWAM_SUCCESS)
goto fail;
}
if (export_wlan) {
lhandle = B_FALSE;
if (name == NULL) {
ret = nwam_walk_known_wlans(export_wlan_callback, of,
NWAM_FLAG_KNOWN_WLAN_WALK_PRIORITY_ORDER, NULL);
} else {
if (wlan_h == NULL) {
ret = nwam_known_wlan_read(name, 0,
&wlan_h);
if (ret != NWAM_SUCCESS)
goto fail;
lhandle = B_TRUE;
}
ret = export_wlan_callback(wlan_h, of);
if (lhandle) {
nwam_known_wlan_free(wlan_h);
wlan_h = NULL;
}
}
if (ret != NWAM_SUCCESS)
goto fail;
}
fail:
free(name);
if (ret != NWAM_SUCCESS)
nwamerr(ret, "Export error");
done:
if (need_to_close)
(void) fclose(of);
}
void
get_func(cmd_t *cmd)
{
nwam_error_t ret = NWAM_SUCCESS;
nwam_value_t prop_value;
const char *prop;
boolean_t value_only = B_FALSE;
nwam_object_type_t object_type = active_object_type();
if (cmd->cmd_argc == 1) {
int c;
optind = 0;
while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "V")) != EOF) {
switch (c) {
case 'V':
value_only = B_TRUE;
break;
default:
command_usage(CMD_GET);
return;
}
}
}
if ((prop = pt_to_prop_name(object_type, cmd->cmd_prop_type)) == NULL) {
nerr("Get error: invalid %s property: '%s'",
scope_to_str(current_scope), pt_to_str(cmd->cmd_prop_type));
return;
}
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_get_prop_value(ncu_h, prop, &prop_value);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_get_prop_value(loc_h, prop, &prop_value);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_get_prop_value(enm_h, prop, &prop_value);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_get_prop_value(wlan_h, prop, &prop_value);
break;
}
if (ret != NWAM_SUCCESS) {
if (ret == NWAM_ENTITY_NOT_FOUND)
nerr("Get error: property '%s' has not been set", prop);
else
nwamerr(ret, "Get error");
return;
}
if (value_only) {
output_prop_val(prop, prop_value, stdout, B_FALSE);
(void) printf("\n");
} else {
output_propname(prop, prop_value, NULL);
}
nwam_value_free(prop_value);
}
void
clear_func(cmd_t *cmd)
{
nwam_error_t ret;
const char *prop;
nwam_object_type_t object_type = active_object_type();
if ((prop = pt_to_prop_name(object_type, cmd->cmd_prop_type)) == NULL) {
nerr("Clear error: invalid %s property: '%s'",
scope_to_str(current_scope), pt_to_str(cmd->cmd_prop_type));
return;
}
if (is_prop_read_only(object_type, prop)) {
nerr("Clear error: property '%s' is read-only", prop);
return;
}
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_delete_prop(ncu_h, prop);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_delete_prop(loc_h, prop);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_delete_prop(enm_h, prop);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_delete_prop(wlan_h, prop);
break;
default:
ret = NWAM_INVALID_HANDLE;
break;
}
if (ret != NWAM_SUCCESS) {
if (ret == NWAM_INVALID_ARG || ret == NWAM_ENTITY_NOT_FOUND) {
nerr("Clear error: property '%s' has not been set",
prop);
} else {
nwamerr(ret, "Clear error");
}
return;
}
need_to_commit = B_TRUE;
}
static void
print_all_prop_choices(nwam_object_type_t object_type, const char *prop)
{
uint64_t i = 0;
const char *str;
boolean_t choices = B_FALSE;
nwam_value_type_t value_type;
nwam_error_t ret;
if (strcmp(prop, NWAM_NCU_PROP_ACTIVATION_MODE) == 0) {
(void) printf(" [%s|",
propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
NWAM_ACTIVATION_MODE_MANUAL));
if (object_type == NWAM_OBJECT_TYPE_NCU) {
(void) printf("%s]",
propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
NWAM_ACTIVATION_MODE_PRIORITIZED));
} else {
(void) printf("%s|%s]",
propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
NWAM_ACTIVATION_MODE_CONDITIONAL_ANY),
propval_to_str(NWAM_NCU_PROP_ACTIVATION_MODE,
NWAM_ACTIVATION_MODE_CONDITIONAL_ALL));
}
return;
}
if (strcmp(prop, NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC) == 0) {
(void) printf(" [%s]",
propval_to_str(NWAM_LOC_PROP_LDAP_NAMESERVICE_CONFIGSRC,
NWAM_CONFIGSRC_MANUAL));
return;
}
value_type = prop_value_type(object_type, prop);
switch (value_type) {
case NWAM_VALUE_TYPE_UINT64:
while ((ret = nwam_uint64_get_value_string(prop, i++, &str))
== NWAM_SUCCESS || ret == NWAM_ENTITY_INVALID_VALUE) {
if (ret == NWAM_ENTITY_INVALID_VALUE)
continue;
if (!choices)
(void) printf("%s", " [");
(void) printf("%s%s", choices ? "|" : "", str);
choices = B_TRUE;
}
if (choices)
(void) putchar(']');
break;
case NWAM_VALUE_TYPE_BOOLEAN:
(void) printf(" [%s|%s]", "true", "false");
break;
case NWAM_VALUE_TYPE_STRING:
break;
}
}
void
walkprop_func(cmd_t *cmd)
{
nwam_error_t ret = NWAM_SUCCESS;
nwam_value_t vals = NULL;
int i;
uint_t prop_num;
const char **props;
boolean_t read_only = B_FALSE, all_props = B_FALSE;
nwam_object_type_t object_type;
prop_display_entry_t *prop_table;
if (!interactive_mode) {
nerr("'walkprop' is only allowed in interactive mode");
return;
}
if (cmd->cmd_argc == 1) {
int c;
optind = 0;
while ((c = getopt(cmd->cmd_argc, cmd->cmd_argv, "a")) != EOF) {
switch (c) {
case 'a':
all_props = B_TRUE;
break;
default:
command_usage(CMD_WALKPROP);
return;
}
}
}
if (obj1_type == RT1_NCP) {
(void) nwam_ncu_get_read_only(ncu_h, &read_only);
}
if (read_only) {
nerr("'walkprop' cannot be used in read-only objects");
return;
}
object_type = active_object_type();
prop_table = get_prop_display_table(object_type);
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
{
nwam_ncu_type_t ncu_type;
nwam_ncu_class_t ncu_class;
if ((ret = nwam_ncu_get_ncu_type(ncu_h, &ncu_type))
!= NWAM_SUCCESS)
break;
if ((ret = nwam_ncu_get_ncu_class(ncu_h, &ncu_class))
!= NWAM_SUCCESS)
break;
ret = nwam_ncu_get_default_proplist(ncu_type, ncu_class, &props,
&prop_num);
break;
}
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_get_default_proplist(&props, &prop_num);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_get_default_proplist(&props, &prop_num);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_get_default_proplist(&props, &prop_num);
break;
}
if (ret != NWAM_SUCCESS) {
nwamerr(ret, "Walkprop error: could not get property list");
return;
}
if (all_props)
(void) printf(gettext("Walking all properties ...\n"));
for (i = 0; i < prop_num; i++) {
char line[NWAM_MAX_VALUE_LEN];
char **checked = NULL;
if (is_prop_read_only(object_type, props[i]))
continue;
if (!all_props &&
!show_prop_test(object_type, props[i], prop_table,
checked, 0))
continue;
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_get_prop_value(ncu_h, props[i], &vals);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_get_prop_value(loc_h, props[i], &vals);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_get_prop_value(enm_h, props[i], &vals);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_get_prop_value(wlan_h, props[i],
&vals);
break;
}
if (ret != NWAM_SUCCESS && ret != NWAM_ENTITY_NOT_FOUND)
continue;
(void) printf("%s", props[i]);
if (ret == NWAM_SUCCESS) {
(void) printf(" (");
output_prop_val(props[i], vals, stdout, B_TRUE);
(void) putchar(')');
nwam_value_free(vals);
}
print_all_prop_choices(object_type, props[i]);
(void) printf("> ");
if (fgets(line, sizeof (line), stdin) == NULL)
continue;
if (line[0] != '\n') {
boolean_t is_listprop;
int pt_type = prop_to_pt(object_type, props[i]);
is_listprop = is_prop_multivalued(object_type,
props[i]);
vals = str_to_nwam_value(object_type, line, pt_type,
is_listprop);
if (vals == NULL) {
ret = NWAM_ENTITY_INVALID_VALUE;
goto repeat;
}
switch (object_type) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_set_prop_value(ncu_h, props[i],
vals);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_set_prop_value(loc_h, props[i],
vals);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_set_prop_value(enm_h, props[i],
vals);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_set_prop_value(wlan_h,
props[i], vals);
break;
}
nwam_value_free(vals);
if (ret != NWAM_SUCCESS)
goto repeat;
need_to_commit = B_TRUE;
continue;
repeat:
invalid_set_prop_msg(props[i], ret);
i--;
}
}
free(props);
}
void
verify_func(cmd_t *cmd)
{
nwam_error_t ret;
const char *errprop;
switch (active_object_type()) {
case NWAM_OBJECT_TYPE_NCU:
ret = nwam_ncu_validate(ncu_h, &errprop);
break;
case NWAM_OBJECT_TYPE_LOC:
ret = nwam_loc_validate(loc_h, &errprop);
break;
case NWAM_OBJECT_TYPE_ENM:
ret = nwam_enm_validate(enm_h, &errprop);
break;
case NWAM_OBJECT_TYPE_KNOWN_WLAN:
ret = nwam_known_wlan_validate(wlan_h, &errprop);
break;
default:
ret = NWAM_INVALID_HANDLE;
nwamerr(ret, "Unknown object type");
return;
}
if (ret != NWAM_SUCCESS)
nwamerr(ret, "Verify error on property '%s'", errprop);
else if (interactive_mode)
(void) printf(gettext("All properties verified\n"));
}
static int
one_command_at_a_time(int argc, char *argv[])
{
char *command;
size_t len = 2;
int i, err;
for (i = 0; i < argc; i++)
len += strlen(argv[i]) + 1;
if ((command = malloc(len)) == NULL) {
nerr("Out of memory");
return (NWAM_ERR);
}
(void) strlcpy(command, argv[0], len);
for (i = 1; i < argc; i++) {
(void) strlcat(command, " ", len);
(void) strlcat(command, argv[i], len);
}
(void) strlcat(command, "\n", len);
err = string_to_yyin(command);
free(command);
if (err != NWAM_OK)
return (err);
while (!feof(yyin)) {
yyparse();
if (saw_error || time_to_exit)
return (cleanup());
}
if (need_to_commit) {
do_commit();
if (need_to_commit)
return (NWAM_ERR);
}
if (!interactive_mode)
return (cleanup());
else {
yyin = stdin;
return (read_input());
}
}
static int
cmd_file(char *file)
{
FILE *infile = NULL;
int err;
struct stat statbuf;
boolean_t using_real_file = (strcmp(file, "-") != 0);
if (using_real_file) {
cmd_file_mode = B_FALSE;
if ((infile = fopen(file, "r")) == NULL) {
nerr(gettext("could not open file '%s': %s"),
file, strerror(errno));
return (1);
}
if ((err = fstat(fileno(infile), &statbuf)) != 0) {
nerr(gettext("could not stat file '%s': %s"),
file, strerror(errno));
err = 1;
goto done;
}
if (!S_ISREG(statbuf.st_mode)) {
nerr(gettext("'%s' is not a regular file."), file);
err = 1;
goto done;
}
if (remove_all_configurations && destroy_all() != NWAM_SUCCESS)
goto done;
yyin = infile;
cmd_file_mode = B_TRUE;
ok_to_prompt = B_FALSE;
} else {
interactive_mode = B_TRUE;
}
if ((err = read_input()) == NWAM_REPEAT)
err = NWAM_ERR;
if (err == NWAM_OK)
(void) printf(gettext("Configuration read.\n"));
done:
if (using_real_file)
(void) fclose(infile);
return (err);
}
int
main(int argc, char *argv[])
{
int err;
int c;
setbuf(stdout, NULL);
if ((execname = strrchr(argv[0], '/')) == NULL)
execname = argv[0];
else
execname++;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
while ((c = getopt(argc, argv, "?hf:d")) != EOF) {
switch (c) {
case 'f':
cmd_file_name = optarg;
cmd_file_mode = B_TRUE;
break;
case '?':
case 'h':
cmd_line_usage();
return (NWAM_OK);
case 'd':
remove_all_configurations = B_TRUE;
break;
default:
cmd_line_usage();
return (NWAM_ERR);
}
}
if (remove_all_configurations && !cmd_file_mode) {
nerr("Option -d can only be used with -f");
return (NWAM_ERR);
}
if (isatty(STDIN_FILENO))
ok_to_prompt = B_TRUE;
if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
exit(NWAM_ERR);
if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
exit(NWAM_ERR);
(void) sigset(SIGINT, SIG_IGN);
if (optind == argc) {
if (!cmd_file_mode)
err = do_interactive();
else
err = cmd_file(cmd_file_name);
} else {
err = one_command_at_a_time(argc - optind, &(argv[optind]));
}
(void) del_GetLine(gl);
return (err);
}