4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
27 * nwamadm is a command interpreter to administer NWAM profiles. It
28 * is all in C (i.e., no lex/yacc), and all the argument passing is
29 * argc/argv based. main() calls the command's handler function,
30 * which first calls parse_argv() to parse the input arguments and set
31 * approriate variables for each command. The rest of the program is
32 * helper functions for the handler functions.
35 #include <arpa/inet.h>
38 #include <libdlwlan.h>
39 #include <libinetutil.h>
43 #include <netinet/in.h>
50 #include <sys/socket.h>
51 #include <sys/types.h>
54 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
55 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
58 typedef void (cmd_func_t
)(int, char **);
61 uint_t cmd_num
; /* command number */
62 const char *cmd_name
; /* command name */
63 cmd_func_t
*cmd_handler
; /* function to call */
64 const char *cmd_usage
; /* short form help */
65 const char *cmd_desc
; /* command description */
66 boolean_t cmd_needs_nwamd
; /* nwam needs to run */
69 /* constants for commands */
74 #define CMD_SHOW_EVENTS 4
75 #define CMD_SCAN_WIFI 5
76 #define CMD_SELECT_WIFI 6
78 #define CMD_MIN CMD_HELP
79 #define CMD_MAX CMD_SELECT_WIFI
81 /* functions to call */
82 static cmd_func_t help_func
, enable_func
, disable_func
, list_func
;
83 static cmd_func_t show_events_func
, scan_wifi_func
, select_wifi_func
;
84 static ofmt_cb_t print_list_cb
;
86 /* table of commands and usage */
87 static struct cmd cmdtab
[] = {
88 { CMD_HELP
, "help", help_func
,
90 "Print this usage message.", B_FALSE
},
91 { CMD_ENABLE
, "enable", enable_func
,
92 "enable [-p <profile-type>] [-c <ncu-class>] <object-name>",
93 "Enable the specified profile.", B_FALSE
},
94 { CMD_DISABLE
, "disable", disable_func
,
95 "disable [-p <profile-type>] [-c <ncu-class>] <object-name>",
96 "Disable the specified profile.", B_FALSE
},
97 { CMD_LIST
, "list", list_func
,
98 "list [-x] [-p <profile-type>] [-c <ncu-class>] [<object-name>]",
99 "List profiles and their current states.", B_TRUE
},
100 { CMD_SHOW_EVENTS
, "show-events", show_events_func
,
102 "Display all events.", B_TRUE
},
103 { CMD_SCAN_WIFI
, "scan-wifi", scan_wifi_func
,
104 "scan-wifi <link-name>",
105 "Request a WiFi scan for the selected link.", B_TRUE
},
106 { CMD_SELECT_WIFI
, "select-wifi", select_wifi_func
,
107 "select-wifi <link-name>",
108 "Make a WLAN selection from the last WiFi scan.", B_TRUE
}
111 /* Structure for "nwamadm list" output */
113 typedef struct profile_entry
{
114 nwam_object_type_t p_type
;
115 nwam_ncu_class_t p_ncu_class
;
116 char p_name
[NWAM_MAX_NAME_LEN
];
117 nwam_state_t p_state
;
118 nwam_aux_state_t p_aux_state
;
121 /* widths of colums for printing */
122 #define TYPE_WIDTH 12 /* width of TYPE column */
123 #define PROFILE_WIDTH 15 /* width of PROFILE column */
124 #define STATE_WIDTH 15 /* width of STATE column */
125 #define AUXSTATE_WIDTH 36 /* width of AUXILIARY STATE column */
127 #define EVENT_WIDTH 15 /* width of EVENT column */
128 #define DESCRIPTION_WIDTH 64 /* width of DESCRIPTION column */
130 /* id for columns of "nwamadm list" */
138 static const ofmt_field_t list_fields
[] = {
139 /* header, width, id, callback */
140 { "TYPE", TYPE_WIDTH
, LIST_TYPE
, print_list_cb
},
141 { "PROFILE", PROFILE_WIDTH
, LIST_PROFILE
, print_list_cb
},
142 { "STATE", STATE_WIDTH
, LIST_STATE
, print_list_cb
},
143 { "AUXILIARY STATE", AUXSTATE_WIDTH
, LIST_AUXSTATE
, print_list_cb
},
147 /* Global variables */
149 /* set early in main(), never modified thereafter, used all over the place */
150 static char *execname
;
152 /* whether the auxilary states are to be printed or not */
153 static boolean_t extended_list
= B_FALSE
;
158 cmd_to_str(int cmd_num
)
160 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
161 return (cmdtab
[cmd_num
].cmd_name
);
164 /* returns description of given command */
166 long_help(int cmd_num
)
168 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
169 return (gettext(cmdtab
[cmd_num
].cmd_desc
));
173 * Called with explicit B_TRUE when help is explicitly required,
177 usage(boolean_t
explicit)
180 FILE *fd
= explicit ? stdout
: stderr
;
182 (void) fprintf(fd
, gettext("usage: <subcommand> <args> ...\n"));
183 for (i
= CMD_MIN
; i
<= CMD_MAX
; i
++) {
184 (void) fprintf(fd
, "\t%s\n", cmdtab
[i
].cmd_usage
);
186 (void) fprintf(fd
, "\t\t%s\n\n", long_help(i
));
192 die(const char *format
, ...)
196 format
= gettext(format
);
197 (void) fprintf(stderr
, "%s: ", execname
);
199 va_start(alist
, format
);
200 (void) vfprintf(stderr
, format
, alist
);
202 (void) fprintf(stderr
, "\n");
209 die_nwamerr(nwam_error_t err
, const char *format
, ...)
213 format
= gettext(format
);
214 (void) fprintf(stderr
, "%s: ", execname
);
216 va_start(alist
, format
);
217 (void) vfprintf(stderr
, format
, alist
);
219 (void) fprintf(stderr
, ": %s\n", nwam_strerror(err
));
224 /* prints the usage for cmd_num and exits */
226 die_usage(int cmd_num
)
228 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
230 (void) fprintf(stderr
, "%s: %s\n", gettext("usage"),
231 cmdtab
[cmd_num
].cmd_usage
);
232 (void) fprintf(stderr
, "\t%s\n", long_help(cmd_num
));
238 * Prints the usage and description of all commands
242 help_func(int argc
, char *argv
[])
247 /* determines if the NCP is active or not. If so, sets arg and halts walk. */
249 active_ncp_callback(nwam_ncp_handle_t ncph
, void *arg
)
252 nwam_state_t state
= NWAM_STATE_UNINITIALIZED
;
253 nwam_aux_state_t aux
;
255 (void) nwam_ncp_get_state(ncph
, &state
, &aux
);
256 if (state
== NWAM_STATE_ONLINE
) {
257 if (nwam_ncp_get_name(ncph
, namep
) != NWAM_SUCCESS
)
265 /* find the currently active NCP and returns its handle */
266 static nwam_ncp_handle_t
267 determine_active_ncp()
270 nwam_ncp_handle_t ncph
;
273 if (nwam_walk_ncps(active_ncp_callback
, &active_ncp
, 0, NULL
)
274 == NWAM_WALK_HALTED
) {
275 if (active_ncp
== NULL
)
278 /* retrieve the NCP handle */
279 ret
= nwam_ncp_read(active_ncp
, 0, &ncph
);
281 if (ret
== NWAM_SUCCESS
)
288 /* check if the given name is a valid loc, test by reading the given loc */
290 valid_loc(const char *name
)
292 nwam_loc_handle_t loch
;
294 if (nwam_loc_read(name
, 0, &loch
) != NWAM_SUCCESS
)
301 valid_enm(const char *name
)
303 nwam_enm_handle_t enmh
;
305 if (nwam_enm_read(name
, 0, &enmh
) != NWAM_SUCCESS
)
312 valid_ncp(const char *name
)
314 nwam_ncp_handle_t ncph
;
316 if (nwam_ncp_read(name
, 0, &ncph
) != NWAM_SUCCESS
)
323 valid_ncu(const char *name
)
325 nwam_ncp_handle_t ncph
;
326 nwam_ncu_handle_t ncuh
;
329 if ((ncph
= determine_active_ncp()) == NULL
)
332 ret
= nwam_ncu_read(ncph
, name
, NWAM_NCU_TYPE_ANY
, 0, &ncuh
);
334 if (ret
!= NWAM_SUCCESS
&& ret
!= NWAM_ENTITY_MULTIPLE_VALUES
)
341 * Given a name, returns object type (loc, enm, ncp, or ncu) and how many
342 * objects matched that name.
344 static nwam_object_type_t
345 determine_object_type(const char *name
, int *num
)
347 nwam_object_type_t type
;
350 /* see if a valid loc, enm, ncp and/or ncu exists with given name */
351 if (valid_loc(name
)) {
353 type
= NWAM_OBJECT_TYPE_LOC
;
355 if (valid_enm(name
)) {
357 type
= NWAM_OBJECT_TYPE_ENM
;
359 if (valid_ncp(name
)) {
361 type
= NWAM_OBJECT_TYPE_NCP
;
363 if (valid_ncu(name
)) {
365 type
= NWAM_OBJECT_TYPE_NCU
;
368 /* if n > 1, then it means *type was set multiple times, undo it */
370 type
= NWAM_OBJECT_TYPE_UNKNOWN
;
377 * Parses argv array and populates object_type and name.
378 * Program exits on failure.
381 parse_argv(int argc
, char *argv
[], int cmd_num
, nwam_object_type_t
*object_type
,
382 nwam_ncu_type_t
*ncu_type
, nwam_ncu_class_t
*ncu_class
, const char **name
)
385 nwam_object_type_t type
= NWAM_OBJECT_TYPE_UNKNOWN
;
386 uint64_t ncu
= NWAM_NCU_TYPE_ANY
;
387 uint64_t class = NWAM_NCU_CLASS_ANY
;
389 /* check argv for option */
391 while ((arg
= getopt(argc
, argv
, "?p:c:x")) != EOF
) {
394 type
= nwam_string_to_object_type(optarg
);
395 if (type
== NWAM_OBJECT_TYPE_UNKNOWN
)
396 die("Invalid profile-type: %s", optarg
);
399 if (nwam_value_string_get_uint64(NWAM_NCU_PROP_CLASS
,
400 optarg
, &class) != NWAM_SUCCESS
) {
401 die("Invalid ncu-class: %s", optarg
);
403 ncu
= nwam_ncu_class_to_type(class);
404 if (ncu
== NWAM_NCU_TYPE_ANY
||
405 ncu
== NWAM_NCU_TYPE_UNKNOWN
)
406 die("Invalid ncu-class: %s", optarg
);
409 /* -x is only for list */
410 if (cmd_num
!= CMD_LIST
)
411 die("-x can only be used with 'list'");
412 extended_list
= B_TRUE
;
420 if (ncu
!= NWAM_NCU_TYPE_ANY
) {
421 /* If -c is given, -p must be NCU. If unspecified, assume NCU */
422 if (type
!= NWAM_OBJECT_TYPE_UNKNOWN
&&
423 type
!= NWAM_OBJECT_TYPE_NCU
)
424 die("'-c <ncu-class>' can only be used for ncu");
426 type
= NWAM_OBJECT_TYPE_NCU
;
429 /* name is mandatory for enable and disable, but not for list */
430 if (optind
== (argc
-1))
431 *name
= argv
[optind
];
432 else if (argc
!= optind
)
433 die("too many profile names given");
434 else if (cmd_num
!= CMD_LIST
)
435 die("no profile name given");
438 * No need to determine type for list.
439 * If -p is not given for enable or disable, then determine type.
441 if (cmd_num
!= CMD_LIST
&& type
== NWAM_OBJECT_TYPE_UNKNOWN
) {
444 type
= determine_object_type(*name
, &num
);
446 die("no profile matched '%s'", *name
);
447 } else if (num
> 1) {
448 die("more than one profile matched '%s' - use "
449 "'-p <profile-type>' to specify a profile type.",
459 /* Enables/Disables profiles depending on boolean */
461 loc_action(const char *name
, boolean_t enable
, char **realnamep
)
463 nwam_loc_handle_t loch
;
466 if ((ret
= nwam_loc_read(name
, 0, &loch
)) != NWAM_SUCCESS
)
470 ret
= nwam_loc_enable(loch
);
472 ret
= nwam_loc_disable(loch
);
474 (void) nwam_loc_get_name(loch
, realnamep
);
480 enm_action(const char *name
, boolean_t enable
, char **realnamep
)
482 nwam_enm_handle_t enmh
;
485 if ((ret
= nwam_enm_read(name
, 0, &enmh
)) != NWAM_SUCCESS
)
489 ret
= nwam_enm_enable(enmh
);
491 ret
= nwam_enm_disable(enmh
);
493 (void) nwam_enm_get_name(enmh
, realnamep
);
499 ncu_action(const char *name
, nwam_ncp_handle_t ncph
, nwam_ncu_type_t type
,
500 boolean_t enable
, char **realnamep
)
502 nwam_ncu_handle_t ncuh
;
504 boolean_t retrieved_ncph
= B_FALSE
;
507 if ((ncph
= determine_active_ncp()) == NULL
)
508 return (NWAM_ENTITY_NOT_FOUND
);
509 retrieved_ncph
= B_TRUE
;
512 ret
= nwam_ncu_read(ncph
, name
, type
, 0, &ncuh
);
516 ret
= nwam_ncu_enable(ncuh
);
518 ret
= nwam_ncu_disable(ncuh
);
519 (void) nwam_ncu_get_name(ncuh
, realnamep
);
522 case NWAM_ENTITY_MULTIPLE_VALUES
:
523 /* Call ncu_action() for link and interface types */
524 ret
= ncu_action(name
, ncph
, NWAM_NCU_TYPE_LINK
, enable
,
526 if (ret
!= NWAM_SUCCESS
)
529 ret
= ncu_action(name
, ncph
, NWAM_NCU_TYPE_INTERFACE
, enable
,
540 * If more than one type of profile with the same name, return error.
541 * In such situations, the -p option must be used.
542 * If a location is enabled when a different one is already enabled, then
543 * that location is disabled automatically by nwamd.
546 enable_func(int argc
, char *argv
[])
549 nwam_object_type_t type
= NWAM_OBJECT_TYPE_UNKNOWN
;
550 nwam_ncu_type_t ncu_type
= NWAM_NCU_TYPE_ANY
;
551 nwam_ncu_class_t ncu_class
= NWAM_NCU_CLASS_ANY
;
553 char *realname
= NULL
;
555 /* parse_argv() returns only on success */
556 parse_argv(argc
, argv
, CMD_ENABLE
, &type
, &ncu_type
, &ncu_class
, &name
);
559 * NCPs and Locations don't need to disable the currently active
560 * profile - nwamd automatically switches to the new active profile.
561 * and will disable it if necessary.
564 /* activate given profile */
566 case NWAM_OBJECT_TYPE_LOC
:
567 ret
= loc_action(name
, B_TRUE
, &realname
);
569 case NWAM_OBJECT_TYPE_ENM
:
570 ret
= enm_action(name
, B_TRUE
, &realname
);
572 case NWAM_OBJECT_TYPE_NCP
:
574 nwam_ncp_handle_t ncph
;
576 if ((ret
= nwam_ncp_read(name
, 0, &ncph
)) != NWAM_SUCCESS
)
579 ret
= nwam_ncp_enable(ncph
);
580 (void) nwam_ncp_get_name(ncph
, &realname
);
584 case NWAM_OBJECT_TYPE_NCU
:
585 ret
= ncu_action(name
, NULL
, ncu_type
, B_TRUE
, &realname
);
591 (void) printf(gettext("Enabling %s '%s'\n"),
592 nwam_object_type_to_string(type
),
593 realname
!= NULL
? realname
: name
);
595 case NWAM_ENTITY_NOT_MANUAL
:
596 die("Only profiles with manual activation-mode can be enabled");
599 die_nwamerr(ret
, "Could not enable %s '%s'",
600 nwam_object_type_to_string(type
),
601 realname
!= NULL
? realname
: name
);
607 * Disables a given profile. Similar to enable, the -p option must be used
608 * if more than one type of profile is matched by the given name.
611 disable_func(int argc
, char *argv
[])
614 nwam_object_type_t type
= NWAM_OBJECT_TYPE_UNKNOWN
;
615 nwam_ncu_type_t ncu_type
= NWAM_NCU_TYPE_ANY
;
616 nwam_ncu_class_t ncu_class
= NWAM_NCU_CLASS_ANY
;
618 char *realname
= NULL
;
620 /* parse_argv() returns only on success */
621 parse_argv(argc
, argv
, CMD_DISABLE
, &type
, &ncu_type
, &ncu_class
,
624 /* deactivate the given profile */
626 case NWAM_OBJECT_TYPE_LOC
:
627 ret
= loc_action(name
, B_FALSE
, &realname
);
629 case NWAM_OBJECT_TYPE_ENM
:
630 ret
= enm_action(name
, B_FALSE
, &realname
);
632 case NWAM_OBJECT_TYPE_NCU
:
633 ret
= ncu_action(name
, NULL
, ncu_type
, B_FALSE
, &realname
);
635 case NWAM_OBJECT_TYPE_NCP
:
636 die("ncp's cannot be disabled. Enable a different ncp to "
637 "switch to that ncp");
642 (void) printf(gettext("Disabling %s '%s'\n"),
643 nwam_object_type_to_string(type
),
644 realname
!= NULL
? realname
: name
);
646 case NWAM_ENTITY_NOT_MANUAL
:
647 die("Only profiles with manual activation-mode can be "
651 die_nwamerr(ret
, "Could not disable %s '%s'",
652 nwam_object_type_to_string(type
),
653 realname
!= NULL
? realname
: name
);
658 /* prints each column */
660 print_list_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
662 profile_entry_t
*pent
= ofarg
->ofmt_cbarg
;
664 switch (ofarg
->ofmt_id
) {
666 /* ncu:ip or ncu:phys for NCUs; ncp, loc, enm for others */
667 if (pent
->p_type
== NWAM_OBJECT_TYPE_NCU
) {
669 if (nwam_uint64_get_value_string(NWAM_NCU_PROP_CLASS
,
670 pent
->p_ncu_class
, &class) != NWAM_SUCCESS
)
671 class = ""; /* empty */
672 (void) snprintf(buf
, bufsize
, "%s:%s",
673 nwam_object_type_to_string(pent
->p_type
), class);
676 nwam_object_type_to_string(pent
->p_type
), bufsize
);
680 (void) strlcpy(buf
, pent
->p_name
, bufsize
);
683 (void) strlcpy(buf
, nwam_state_to_string(pent
->p_state
),
688 nwam_aux_state_to_string(pent
->p_aux_state
), bufsize
);
691 die("invalid print_list_cb() input: %d", ofarg
->ofmt_id
);
697 /* returns the state and auxilliary state of the object */
699 determine_object_state(nwam_object_type_t type
, void *handle
,
700 nwam_aux_state_t
*aux_statep
)
703 nwam_aux_state_t astate
;
707 case NWAM_OBJECT_TYPE_ENM
:
708 ret
= nwam_enm_get_state(handle
, &state
, &astate
);
710 case NWAM_OBJECT_TYPE_LOC
:
711 ret
= nwam_loc_get_state(handle
, &state
, &astate
);
713 case NWAM_OBJECT_TYPE_NCP
:
714 ret
= nwam_ncp_get_state(handle
, &state
, &astate
);
716 case NWAM_OBJECT_TYPE_NCU
:
717 ret
= nwam_ncu_get_state(handle
, &state
, &astate
);
724 if (ret
== NWAM_PERMISSION_DENIED
) {
725 die_nwamerr(ret
, "could not get object state");
726 } else if (ret
!= NWAM_SUCCESS
) {
727 state
= NWAM_STATE_UNINITIALIZED
;
728 astate
= NWAM_AUX_STATE_UNINITIALIZED
;
731 if (aux_statep
!= NULL
)
732 *aux_statep
= astate
;
736 /* populate profile_entry_t with values for object with given handle */
738 add_to_profile_entry(nwam_object_type_t type
, void *handle
,
739 profile_entry_t
*pent
)
745 if (type
== NWAM_OBJECT_TYPE_NCU
) {
746 nwam_ncu_class_t
class;
747 if ((ret
= nwam_ncu_get_ncu_class(handle
, &class))
750 pent
->p_ncu_class
= class;
752 pent
->p_ncu_class
= -1;
756 case NWAM_OBJECT_TYPE_ENM
:
757 ret
= nwam_enm_get_name(handle
, &name
);
759 case NWAM_OBJECT_TYPE_LOC
:
760 ret
= nwam_loc_get_name(handle
, &name
);
762 case NWAM_OBJECT_TYPE_NCP
:
763 ret
= nwam_ncp_get_name(handle
, &name
);
765 case NWAM_OBJECT_TYPE_NCU
:
766 ret
= nwam_ncu_get_name(handle
, &name
);
772 if (ret
!= NWAM_SUCCESS
) {
775 (void) strlcpy(pent
->p_name
, name
, sizeof (pent
->p_name
));
778 pent
->p_state
= determine_object_state(type
, handle
,
781 return (NWAM_SUCCESS
);
784 /* callback functions used by walk */
787 list_ncu_cb(nwam_ncu_handle_t ncuh
, void *arg
)
789 ofmt_handle_t ofmt
= arg
;
790 profile_entry_t pent
;
793 bzero(&pent
, sizeof (profile_entry_t
));
794 ret
= add_to_profile_entry(NWAM_OBJECT_TYPE_NCU
, ncuh
, &pent
);
795 if (ret
!= NWAM_SUCCESS
)
796 die_nwamerr(ret
, "could not add ncu to list");
797 ofmt_print(ofmt
, &pent
);
802 list_ncp_cb(nwam_ncp_handle_t ncph
, void *arg
)
804 ofmt_handle_t ofmt
= arg
;
805 profile_entry_t pent
;
809 bzero(&pent
, sizeof (profile_entry_t
));
810 ret
= add_to_profile_entry(NWAM_OBJECT_TYPE_NCP
, ncph
, &pent
);
811 if (ret
!= NWAM_SUCCESS
)
812 die_nwamerr(ret
, "could not add ncp to list");
813 ofmt_print(ofmt
, &pent
);
815 state
= determine_object_state(NWAM_OBJECT_TYPE_NCP
, ncph
, NULL
);
816 if (state
== NWAM_STATE_ONLINE
) {
817 (void) nwam_ncp_walk_ncus(ncph
, list_ncu_cb
, ofmt
,
818 NWAM_FLAG_NCU_TYPE_ALL
, NULL
);
824 list_loc_cb(nwam_loc_handle_t loch
, void *arg
)
826 ofmt_handle_t ofmt
= arg
;
827 profile_entry_t pent
;
830 bzero(&pent
, sizeof (profile_entry_t
));
831 ret
= add_to_profile_entry(NWAM_OBJECT_TYPE_LOC
, loch
, &pent
);
832 if (ret
!= NWAM_SUCCESS
)
833 die_nwamerr(ret
, "could not add loc to list");
834 ofmt_print(ofmt
, &pent
);
839 list_enm_cb(nwam_enm_handle_t enmh
, void *arg
)
841 ofmt_handle_t ofmt
= arg
;
842 profile_entry_t pent
;
845 bzero(&pent
, sizeof (profile_entry_t
));
846 ret
= add_to_profile_entry(NWAM_OBJECT_TYPE_ENM
, enmh
, &pent
);
847 if (ret
!= NWAM_SUCCESS
)
848 die_nwamerr(ret
, "could not add enm to list");
849 ofmt_print(ofmt
, &pent
);
854 * lists all profiles and their state
857 list_func(int argc
, char *argv
[])
859 nwam_error_t ret
= NWAM_SUCCESS
;
860 nwam_object_type_t type
= NWAM_OBJECT_TYPE_UNKNOWN
;
861 nwam_ncu_type_t ncu_type
= NWAM_NCU_TYPE_ANY
;
862 nwam_ncu_class_t ncu_class
= NWAM_NCU_CLASS_ANY
;
867 char *default_fields
= "type,profile,state";
868 char *extended_fields
= "type,profile,state,auxiliary state";
871 /* parse_argv() returns only on success */
872 parse_argv(argc
, argv
, CMD_LIST
, &type
, &ncu_type
, &ncu_class
,
873 (const char **)&name
);
876 fields
= extended_fields
;
878 fields
= default_fields
;
879 oferr
= ofmt_open(fields
, list_fields
, 0, 0, &ofmt
);
880 if (oferr
!= OFMT_SUCCESS
) {
881 char buf
[OFMT_BUFSIZE
];
882 (void) ofmt_strerror(ofmt
, oferr
, buf
, sizeof (buf
));
883 die("ofmt_open() failed: %s", buf
);
886 /* object-name given in command-line */
888 boolean_t found
= B_FALSE
;
891 * If objects with different types have the same name
892 * (type = UNKNOWN), then try to open handle for each object
893 * and print if successful.
895 if (type
== NWAM_OBJECT_TYPE_NCP
||
896 type
== NWAM_OBJECT_TYPE_UNKNOWN
) {
897 nwam_ncp_handle_t ncph
;
898 if (nwam_ncp_read(name
, 0, &ncph
) == NWAM_SUCCESS
) {
900 (void) list_ncp_cb(ncph
, ofmt
);
904 if (type
== NWAM_OBJECT_TYPE_NCU
||
905 type
== NWAM_OBJECT_TYPE_UNKNOWN
) {
906 nwam_ncp_handle_t ncph
;
907 nwam_ncu_handle_t ncuh
;
909 if ((ncph
= determine_active_ncp()) != NULL
) {
910 ret
= nwam_ncu_read(ncph
, name
, ncu_type
, 0,
912 if (ret
== NWAM_ENTITY_MULTIPLE_VALUES
) {
914 if (nwam_ncu_read(ncph
, name
,
915 NWAM_NCU_TYPE_LINK
, 0, &ncuh
)
917 (void) list_ncu_cb(ncuh
, ofmt
);
920 if (nwam_ncu_read(ncph
, name
,
921 NWAM_NCU_TYPE_INTERFACE
, 0, &ncuh
)
923 (void) list_ncu_cb(ncuh
, ofmt
);
926 } else if (ret
== NWAM_SUCCESS
) {
928 (void) list_ncu_cb(ncuh
, ofmt
);
934 if (type
== NWAM_OBJECT_TYPE_LOC
||
935 type
== NWAM_OBJECT_TYPE_UNKNOWN
) {
936 nwam_loc_handle_t loch
;
937 if (nwam_loc_read(name
, 0, &loch
) == NWAM_SUCCESS
) {
939 (void) list_loc_cb(loch
, ofmt
);
943 if (type
== NWAM_OBJECT_TYPE_ENM
||
944 type
== NWAM_OBJECT_TYPE_UNKNOWN
) {
945 nwam_enm_handle_t enmh
;
946 if (nwam_enm_read(name
, 0, &enmh
) == NWAM_SUCCESS
) {
948 (void) list_enm_cb(enmh
, ofmt
);
952 /* If at least object is found, don't return error */
956 ret
= NWAM_ENTITY_NOT_FOUND
;
959 /* object-name not given in command-line */
962 * If type given (type != UNKNOWN), just walk objects in that
963 * type. Otherwise, walk all ncp, ncu, loc and enm.
965 if (type
== NWAM_OBJECT_TYPE_NCP
||
966 type
== NWAM_OBJECT_TYPE_UNKNOWN
) {
967 ret
= nwam_walk_ncps(list_ncp_cb
, ofmt
, 0, NULL
);
968 if (ret
!= NWAM_SUCCESS
)
971 /* no UNKNOWN for NCUs. They walked with active NCP above */
972 if (type
== NWAM_OBJECT_TYPE_NCU
) {
973 nwam_ncp_handle_t ncph
;
974 if ((ncph
= determine_active_ncp()) != NULL
) {
975 ret
= nwam_ncp_walk_ncus(ncph
, list_ncu_cb
,
976 ofmt
, nwam_ncu_class_to_flag(ncu_class
),
979 if (ret
!= NWAM_SUCCESS
)
983 if (type
== NWAM_OBJECT_TYPE_LOC
||
984 type
== NWAM_OBJECT_TYPE_UNKNOWN
) {
985 ret
= nwam_walk_locs(list_loc_cb
, ofmt
,
986 NWAM_FLAG_ACTIVATION_MODE_ALL
, NULL
);
987 if (ret
!= NWAM_SUCCESS
)
990 if (type
== NWAM_OBJECT_TYPE_ENM
||
991 type
== NWAM_OBJECT_TYPE_UNKNOWN
) {
992 ret
= nwam_walk_enms(list_enm_cb
, ofmt
,
993 NWAM_FLAG_ACTIVATION_MODE_ALL
, NULL
);
994 if (ret
!= NWAM_SUCCESS
)
1001 if (ret
== NWAM_ENTITY_NOT_FOUND
&& name
!= NULL
)
1002 die("no profile matched '%s'", name
);
1003 else if (ret
!= NWAM_SUCCESS
)
1004 die_nwamerr(ret
, "list failed during walk");
1008 * Print NWAM events.
1011 eventhandler(nwam_event_t event
)
1013 char description
[DESCRIPTION_WIDTH
];
1014 char statestr
[DESCRIPTION_WIDTH
];
1015 char objstr
[DESCRIPTION_WIDTH
];
1016 char *object
= NULL
;
1017 const char *action
= NULL
;
1019 boolean_t display
= B_TRUE
;
1023 (void) strlcpy(description
, "-", sizeof (description
));
1025 switch (event
->nwe_type
) {
1026 case NWAM_EVENT_TYPE_OBJECT_ACTION
:
1027 action
= nwam_action_to_string
1028 (event
->nwe_data
.nwe_object_action
.nwe_action
);
1029 (void) snprintf(objstr
, sizeof (objstr
), "%s %s",
1030 nwam_object_type_to_string
1031 (event
->nwe_data
.nwe_object_action
.nwe_object_type
),
1032 event
->nwe_data
.nwe_object_action
.nwe_name
);
1036 case NWAM_EVENT_TYPE_OBJECT_STATE
:
1037 (void) snprintf(statestr
, sizeof (statestr
), "%s, %s",
1038 nwam_state_to_string
1039 (event
->nwe_data
.nwe_object_state
.nwe_state
),
1040 nwam_aux_state_to_string
1041 (event
->nwe_data
.nwe_object_state
.nwe_aux_state
));
1044 (void) snprintf(objstr
, sizeof (objstr
), "%s %s",
1045 nwam_object_type_to_string
1046 (event
->nwe_data
.nwe_object_state
.nwe_object_type
),
1047 event
->nwe_data
.nwe_object_state
.nwe_name
);
1051 case NWAM_EVENT_TYPE_PRIORITY_GROUP
:
1052 (void) snprintf(description
, DESCRIPTION_WIDTH
,
1053 "priority-group: %d",
1054 event
->nwe_data
.nwe_priority_group_info
.nwe_priority
);
1057 case NWAM_EVENT_TYPE_WLAN_SCAN_REPORT
:
1058 (void) printf("%-*s \n", EVENT_WIDTH
,
1059 nwam_event_type_to_string(event
->nwe_type
));
1060 wlans
= event
->nwe_data
.nwe_wlan_info
.nwe_wlans
;
1062 i
< event
->nwe_data
.nwe_wlan_info
.nwe_num_wlans
;
1064 (void) snprintf(description
, DESCRIPTION_WIDTH
,
1065 "%d: %c%c ESSID %s BSSID %s", i
+ 1,
1066 wlans
[i
].nww_selected
? 'S' : '-',
1067 wlans
[i
].nww_connected
? 'C' : '-',
1068 wlans
[i
].nww_essid
, wlans
[i
].nww_bssid
);
1069 (void) printf("%-*s %-*s\n", EVENT_WIDTH
, "-",
1070 DESCRIPTION_WIDTH
, description
);
1075 case NWAM_EVENT_TYPE_WLAN_NEED_CHOICE
:
1076 (void) printf("%-*s \n", EVENT_WIDTH
,
1077 nwam_event_type_to_string(event
->nwe_type
));
1081 case NWAM_EVENT_TYPE_WLAN_NEED_KEY
:
1082 (void) printf("%-*s \n", EVENT_WIDTH
,
1083 nwam_event_type_to_string(event
->nwe_type
));
1087 case NWAM_EVENT_TYPE_WLAN_CONNECTION_REPORT
:
1088 (void) snprintf(description
, DESCRIPTION_WIDTH
,
1089 gettext("connect to WLAN ESSID %s, BSSID %s %s"),
1090 event
->nwe_data
.nwe_wlan_info
.nwe_wlans
[0].nww_essid
,
1091 event
->nwe_data
.nwe_wlan_info
.nwe_wlans
[0].nww_bssid
,
1092 event
->nwe_data
.nwe_wlan_info
.nwe_connected
?
1093 "succeeded" : "failed");
1096 case NWAM_EVENT_TYPE_INFO
:
1097 (void) snprintf(description
, sizeof (description
),
1098 "%s", event
->nwe_data
.nwe_info
.nwe_message
);
1101 case NWAM_EVENT_TYPE_IF_ACTION
:
1102 action
= nwam_action_to_string
1103 (event
->nwe_data
.nwe_if_action
.nwe_action
);
1104 object
= event
->nwe_data
.nwe_if_action
.nwe_name
;
1107 case NWAM_EVENT_TYPE_IF_STATE
:
1108 object
= event
->nwe_data
.nwe_if_state
.nwe_name
;
1109 if (event
->nwe_data
.nwe_if_state
.nwe_addr_valid
) {
1110 struct sockaddr_storage
*address
=
1111 &(event
->nwe_data
.nwe_if_state
.nwe_addr
);
1112 struct sockaddr_storage
*netmask
=
1113 &(event
->nwe_data
.nwe_if_state
.nwe_netmask
);
1114 struct sockaddr_in
*v4addr
;
1115 struct sockaddr_in6
*v6addr
;
1116 char addrstr
[NWAM_MAX_VALUE_LEN
];
1117 int plen
= mask2plen((struct sockaddr
*)netmask
);
1119 switch (address
->ss_family
) {
1121 v4addr
= (struct sockaddr_in
*)address
;
1122 (void) inet_ntop(AF_INET
, &v4addr
->sin_addr
,
1123 addrstr
, sizeof (addrstr
));
1126 v6addr
= (struct sockaddr_in6
*)address
;
1127 (void) inet_ntop(AF_INET6
, &v6addr
->sin6_addr
,
1128 addrstr
, sizeof (addrstr
));
1131 (void) snprintf(statestr
, sizeof (statestr
),
1132 "flags %x addr %s/%d",
1133 event
->nwe_data
.nwe_if_state
.nwe_flags
,
1136 (void) snprintf(statestr
, sizeof (statestr
),
1137 "flags %x", event
->nwe_data
.nwe_if_state
.nwe_flags
);
1142 case NWAM_EVENT_TYPE_LINK_ACTION
:
1143 action
= nwam_action_to_string
1144 (event
->nwe_data
.nwe_link_action
.nwe_action
);
1145 object
= event
->nwe_data
.nwe_link_action
.nwe_name
;
1148 case NWAM_EVENT_TYPE_LINK_STATE
:
1149 state
= event
->nwe_data
.nwe_link_state
.nwe_link_up
?
1151 object
= event
->nwe_data
.nwe_link_state
.nwe_name
;
1155 if (object
!= NULL
&& action
!= NULL
) {
1156 (void) snprintf(description
, sizeof (description
),
1157 "%s -> action %s", object
, action
);
1158 } else if (object
!= NULL
&& state
!= NULL
) {
1159 (void) snprintf(description
, sizeof (description
),
1160 "%s -> state %s", object
, state
);
1164 (void) printf("%-*s %-*s\n", EVENT_WIDTH
,
1165 nwam_event_type_to_string(event
->nwe_type
),
1172 * listens for events and displays them via the eventhandler() function above.
1176 show_events_func(int argc
, char *argv
[])
1181 err
= nwam_events_init();
1183 if (err
!= NWAM_SUCCESS
)
1184 die_nwamerr(err
, "could not bind to receive events");
1187 (void) printf("%-*s %-*s\n", EVENT_WIDTH
, "EVENT",
1188 DESCRIPTION_WIDTH
, "DESCRIPTION");
1192 * Needed for stdout redirection to ensure event output is
1193 * regularly flushed to file.
1195 (void) fflush(stdout
);
1196 err
= nwam_event_wait(&event
);
1197 if (err
== NWAM_SUCCESS
) {
1198 eventhandler(event
);
1199 nwam_event_free(event
);
1201 } while (err
== NWAM_SUCCESS
);
1202 die_nwamerr(err
, "event handling stopped");
1205 /* May need to convert case-insensitive link name match to case-sensitive one */
1207 name_to_linkname(char *name
, char **linknamep
)
1210 nwam_ncp_handle_t ncph
= NULL
;
1211 nwam_ncu_handle_t ncuh
= NULL
;
1213 if ((ncph
= determine_active_ncp()) == NULL
)
1214 return (NWAM_ENTITY_NOT_FOUND
);
1216 err
= nwam_ncu_read(ncph
, name
, NWAM_NCU_TYPE_LINK
, 0, &ncuh
);
1217 if (err
== NWAM_SUCCESS
)
1218 err
= nwam_ncu_get_name(ncuh
, linknamep
);
1220 nwam_ncp_free(ncph
);
1221 nwam_ncu_free(ncuh
);
1226 scan_wifi_func(int argc
, char *argv
[])
1229 char *linkname
= NULL
;
1232 die_usage(CMD_SCAN_WIFI
);
1234 if ((err
= name_to_linkname(argv
[0], &linkname
)) != NWAM_SUCCESS
)
1235 die_nwamerr(err
, "scan request failed for %s", argv
[0]);
1237 err
= nwam_wlan_scan(linkname
);
1239 if (err
!= NWAM_SUCCESS
)
1240 die_nwamerr(err
, "scan request failed for %s", linkname
);
1246 select_wifi_func(int argc
, char *argv
[])
1249 char *linkname
= NULL
;
1250 uint_t i
, choice
, num_wlans
= 0;
1251 uint32_t security_mode
;
1252 boolean_t have_key
= B_FALSE
;
1253 nwam_wlan_t
*wlans
= NULL
;
1254 char choicestr
[NWAM_MAX_VALUE_LEN
];
1255 char modestr
[NWAM_MAX_VALUE_LEN
];
1256 char essid
[NWAM_MAX_VALUE_LEN
];
1257 char bssid
[NWAM_MAX_VALUE_LEN
];
1260 die_usage(CMD_SELECT_WIFI
);
1262 if ((err
= name_to_linkname(argv
[0], &linkname
)) != NWAM_SUCCESS
) {
1263 die_nwamerr(err
, "could not retrieve scan results for %s",
1266 err
= nwam_wlan_get_scan_results(linkname
, &num_wlans
, &wlans
);
1268 if (err
!= NWAM_SUCCESS
) {
1269 die_nwamerr(err
, "could not retrieve scan results for %s",
1274 /* Loop until valid selection made */
1276 (void) printf("\n");
1277 /* Display WLAN choices for user to select from */
1278 for (i
= 0; i
< num_wlans
; i
++) {
1279 (void) printf("%d: ESSID %s BSSID %s\n",
1280 i
+ 1, wlans
[i
].nww_essid
, wlans
[i
].nww_bssid
);
1282 (void) printf(gettext("%d: Other\n"), i
+ 1);
1284 (void) printf(gettext("\nChoose WLAN to connect to [1-%d]: "),
1287 if (fgets(choicestr
, sizeof (choicestr
), stdin
) != NULL
&&
1288 (choice
= atoi(choicestr
)) >= 1 && choice
<= (i
+ 1))
1292 if (choice
== i
+ 1 || wlans
[choice
- 1].nww_essid
[0] == '\0') {
1293 nwam_known_wlan_handle_t kwh
= NULL
;
1294 nwam_value_t keynameval
= NULL
;
1296 /* If "Other" or a hidden WLAN is selected, ask for ESSID */
1298 (void) printf(gettext("\nEnter WLAN name: "));
1299 while (fgets(essid
, sizeof (essid
), stdin
) == NULL
) {}
1300 essid
[strlen(essid
) - 1] = '\0';
1301 } while (strspn(essid
, " \t") == strlen(essid
));
1303 /* If "Other" was selected, secmode must be specified. */
1304 if (choice
== i
+ 1) {
1306 (void) printf(gettext("1: None\n"));
1307 (void) printf(gettext("2: WEP\n"));
1308 (void) printf(gettext("3: WPA\n"));
1309 (void) printf(gettext("Enter security mode: "));
1310 if (fgets(modestr
, sizeof (choicestr
), stdin
)
1312 (security_mode
= atoi(modestr
)) >= 1 &&
1317 security_mode
= wlans
[choice
- 1].nww_security_mode
;
1318 have_key
= wlans
[choice
- 1].nww_have_key
;
1322 * We have to determine if we have a key for this ESSID from
1323 * the known WLAN list, since we cannot determine this from
1326 if (nwam_known_wlan_read(essid
, 0, &kwh
) == NWAM_SUCCESS
&&
1327 nwam_known_wlan_get_prop_value(kwh
,
1328 NWAM_KNOWN_WLAN_PROP_KEYNAME
, &keynameval
) == NWAM_SUCCESS
)
1333 nwam_value_free(keynameval
);
1334 nwam_known_wlan_free(kwh
);
1336 (void) strlcpy(essid
, wlans
[choice
- 1].nww_essid
,
1338 (void) strlcpy(bssid
, wlans
[choice
- 1].nww_bssid
,
1340 security_mode
= wlans
[choice
- 1].nww_security_mode
;
1341 have_key
= wlans
[choice
- 1].nww_have_key
;
1344 if (security_mode
!= DLADM_WLAN_SECMODE_NONE
&& !have_key
) {
1346 char key
[NWAM_MAX_VALUE_LEN
];
1347 char slotstr
[NWAM_MAX_VALUE_LEN
];
1350 (void) printf(gettext("\nEnter WLAN key for "
1351 "ESSID %s: "), essid
);
1352 while (fgets(key
, sizeof (key
), stdin
) == NULL
) {}
1353 key
[strlen(key
) - 1] = '\0';
1354 } while (strspn(key
, " \t") == strlen(key
));
1356 if (security_mode
== DLADM_WLAN_SECMODE_WEP
) {
1359 gettext("\nEnter key slot [1-4]: "));
1360 if (fgets(slotstr
, sizeof (slotstr
), stdin
)
1361 != NULL
&& (keyslot
= atoi(slotstr
)) >= 1 &&
1367 err
= nwam_wlan_set_key(linkname
, essid
, bssid
, security_mode
,
1369 if (err
!= NWAM_SUCCESS
)
1370 die_nwamerr(err
, "could not set WiFi key");
1372 err
= nwam_wlan_select(linkname
, essid
, bssid
[0] != '\0' ? bssid
: NULL
,
1373 security_mode
, B_TRUE
);
1374 if (err
!= NWAM_SUCCESS
)
1375 die_nwamerr(err
, "could not select WLAN %s", essid
);
1381 main(int argc
, char *argv
[])
1386 (void) setlocale(LC_ALL
, "");
1387 (void) textdomain(TEXT_DOMAIN
);
1389 if ((execname
= strrchr(argv
[0], '/')) == NULL
)
1399 for (i
= CMD_MIN
; i
<= CMD_MAX
; i
++) {
1400 if (strcmp(argv
[1], cmd_to_str(i
)) == 0) {
1401 if (cmdtab
[i
].cmd_needs_nwamd
) {
1402 state
= smf_get_state(NWAM_FMRI
);
1403 if (state
== NULL
|| strcmp(state
,
1404 SCF_STATE_STRING_ONLINE
) != 0) {
1406 die("enable '%s' to use '%s %s'",
1407 NWAM_FMRI
, execname
,
1408 cmd_to_str(cmdtab
[i
].cmd_num
));
1413 cmdtab
[i
].cmd_handler(argc
- 2, &(argv
[2]));
1419 (void) fprintf(stderr
, gettext("%s: unknown subcommand '%s'\n"),