/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* nwamadm is a command interpreter to administer NWAM profiles. It
* which first calls parse_argv() to parse the input arguments and set
* approriate variables for each command. The rest of the program is
* helper functions for the handler functions.
*/
#include <assert.h>
#include <errno.h>
#include <libdlwlan.h>
#include <libinetutil.h>
#include <libnwam.h>
#include <libscf.h>
#include <locale.h>
#include <ofmt.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
#endif
typedef void (cmd_func_t)(int, char **);
struct cmd {
};
/* constants for commands */
#define CMD_HELP 0
/* functions to call */
/* table of commands and usage */
"help",
"Print this usage message.", B_FALSE },
"enable [-p <profile-type>] [-c <ncu-class>] <object-name>",
"Enable the specified profile.", B_FALSE },
"disable [-p <profile-type>] [-c <ncu-class>] <object-name>",
"Disable the specified profile.", B_FALSE },
"list [-x] [-p <profile-type>] [-c <ncu-class>] [<object-name>]",
"List profiles and their current states.", B_TRUE },
"show-events",
"Display all events.", B_TRUE },
"scan-wifi <link-name>",
"Request a WiFi scan for the selected link.", B_TRUE },
"select-wifi <link-name>",
"Make a WLAN selection from the last WiFi scan.", B_TRUE }
};
/* Structure for "nwamadm list" output */
typedef struct profile_entry {
/* widths of colums for printing */
/* id for columns of "nwamadm list" */
typedef enum {
/* header, width, id, callback */
};
/* Global variables */
/* set early in main(), never modified thereafter, used all over the place */
static char *execname;
/* whether the auxilary states are to be printed or not */
/* Functions */
static const char *
{
}
/* returns description of given command */
static const char *
{
}
/*
* Called with explicit B_TRUE when help is explicitly required,
* B_FALSE for errors
*/
static void
{
int i;
if (explicit)
}
}
/* PRINTFLIKE1 */
static void
{
}
/* PRINTFLIKE2 */
static void
{
}
/* prints the usage for cmd_num and exits */
static void
{
}
/*
* Prints the usage and description of all commands
*/
/* ARGSUSED */
static void
{
}
/* determines if the NCP is active or not. If so, sets arg and halts walk. */
static int
{
if (state == NWAM_STATE_ONLINE) {
return (1);
}
return (0);
}
/* find the currently active NCP and returns its handle */
static nwam_ncp_handle_t
{
char *active_ncp;
== NWAM_WALK_HALTED) {
if (active_ncp == NULL)
return (NULL);
/* retrieve the NCP handle */
if (ret == NWAM_SUCCESS)
return (ncph);
}
return (NULL);
}
/* check if the given name is a valid loc, test by reading the given loc */
static boolean_t
{
return (B_FALSE);
return (B_TRUE);
}
static boolean_t
{
return (B_FALSE);
return (B_TRUE);
}
static boolean_t
{
return (B_FALSE);
return (B_TRUE);
}
static boolean_t
{
return (B_FALSE);
return (B_FALSE);
return (B_TRUE);
}
/*
* Given a name, returns object type (loc, enm, ncp, or ncu) and how many
* objects matched that name.
*/
static nwam_object_type_t
{
int n = 0;
n++;
}
n++;
}
n++;
}
n++;
}
/* if n > 1, then it means *type was set multiple times, undo it */
if (n != 1)
*num = n;
return (type);
}
/*
* Parses argv array and populates object_type and name.
* Program exits on failure.
*/
static void
{
int arg;
/* check argv for option */
optind = 0;
switch (arg) {
case 'p':
if (type == NWAM_OBJECT_TYPE_UNKNOWN)
break;
case 'c':
}
if (ncu == NWAM_NCU_TYPE_ANY ||
break;
case 'x':
/* -x is only for list */
die("-x can only be used with 'list'");
break;
case '?':
default:
}
}
if (ncu != NWAM_NCU_TYPE_ANY) {
/* If -c is given, -p must be NCU. If unspecified, assume NCU */
if (type != NWAM_OBJECT_TYPE_UNKNOWN &&
die("'-c <ncu-class>' can only be used for ncu");
}
/* name is mandatory for enable and disable, but not for list */
die("too many profile names given");
die("no profile name given");
/*
* No need to determine type for list.
* If -p is not given for enable or disable, then determine type.
*/
int num = 0;
if (num == 0) {
} else if (num > 1) {
die("more than one profile matched '%s' - use "
"'-p <profile-type>' to specify a profile type.",
*name);
}
}
*object_type = type;
}
static nwam_error_t
{
return (ret);
if (enable)
else
return (ret);
}
static nwam_error_t
{
return (ret);
if (enable)
else
return (ret);
}
static nwam_error_t
{
return (NWAM_ENTITY_NOT_FOUND);
}
switch (ret) {
case NWAM_SUCCESS:
if (enable)
else
break;
/* Call ncu_action() for link and interface types */
if (ret != NWAM_SUCCESS)
break;
break;
}
if (retrieved_ncph)
return (ret);
}
/*
* If more than one type of profile with the same name, return error.
* In such situations, the -p option must be used.
* If a location is enabled when a different one is already enabled, then
* that location is disabled automatically by nwamd.
*/
static void
{
const char *name;
/* parse_argv() returns only on success */
/*
* NCPs and Locations don't need to disable the currently active
* profile - nwamd automatically switches to the new active profile.
* and will disable it if necessary.
*/
/* activate given profile */
switch (type) {
case NWAM_OBJECT_TYPE_LOC:
break;
case NWAM_OBJECT_TYPE_ENM:
break;
case NWAM_OBJECT_TYPE_NCP:
{
break;
break;
}
case NWAM_OBJECT_TYPE_NCU:
break;
}
switch (ret) {
case NWAM_SUCCESS:
break;
case NWAM_ENTITY_NOT_MANUAL:
die("Only profiles with manual activation-mode can be enabled");
break;
default:
}
}
/*
* Disables a given profile. Similar to enable, the -p option must be used
* if more than one type of profile is matched by the given name.
*/
static void
{
const char *name;
/* parse_argv() returns only on success */
&name);
/* deactivate the given profile */
switch (type) {
case NWAM_OBJECT_TYPE_LOC:
break;
case NWAM_OBJECT_TYPE_ENM:
break;
case NWAM_OBJECT_TYPE_NCU:
break;
case NWAM_OBJECT_TYPE_NCP:
die("ncp's cannot be disabled. Enable a different ncp to "
"switch to that ncp");
}
switch (ret) {
case NWAM_SUCCESS:
break;
case NWAM_ENTITY_NOT_MANUAL:
die("Only profiles with manual activation-mode can be "
"disabled");
break;
default:
}
}
/* prints each column */
static boolean_t
{
case LIST_TYPE:
/* ncu:ip or ncu:phys for NCUs; ncp, loc, enm for others */
const char *class;
} else {
}
break;
case LIST_PROFILE:
break;
case LIST_STATE:
bufsize);
break;
case LIST_AUXSTATE:
break;
default:
break;
}
return (B_TRUE);
}
/* returns the state and auxilliary state of the object */
static nwam_state_t
{
switch (type) {
case NWAM_OBJECT_TYPE_ENM:
break;
case NWAM_OBJECT_TYPE_LOC:
break;
case NWAM_OBJECT_TYPE_NCP:
break;
case NWAM_OBJECT_TYPE_NCU:
break;
default:
/* NOTREACHED */
break;
}
if (ret == NWAM_PERMISSION_DENIED) {
} else if (ret != NWAM_SUCCESS) {
}
if (aux_statep != NULL)
*aux_statep = astate;
return (state);
}
/* populate profile_entry_t with values for object with given handle */
static int
{
char *name;
if (type == NWAM_OBJECT_TYPE_NCU) {
!= NWAM_SUCCESS)
return (ret);
} else {
}
switch (type) {
case NWAM_OBJECT_TYPE_ENM:
break;
case NWAM_OBJECT_TYPE_LOC:
break;
case NWAM_OBJECT_TYPE_NCP:
break;
case NWAM_OBJECT_TYPE_NCU:
break;
default:
/* NOTREACHED */
break;
}
if (ret != NWAM_SUCCESS) {
return (ret);
}
&pent->p_aux_state);
return (NWAM_SUCCESS);
}
/* callback functions used by walk */
static int
{
if (ret != NWAM_SUCCESS)
return (0);
}
static int
{
if (ret != NWAM_SUCCESS)
if (state == NWAM_STATE_ONLINE) {
}
return (0);
}
static int
{
if (ret != NWAM_SUCCESS)
return (0);
}
static int
{
if (ret != NWAM_SUCCESS)
return (0);
}
/*
* lists all profiles and their state
*/
static void
{
/* parse_argv() returns only on success */
(const char **)&name);
if (extended_list)
else
if (oferr != OFMT_SUCCESS) {
}
/* object-name given in command-line */
/*
* If objects with different types have the same name
* (type = UNKNOWN), then try to open handle for each object
* and print if successful.
*/
if (type == NWAM_OBJECT_TYPE_NCP ||
type == NWAM_OBJECT_TYPE_UNKNOWN) {
}
}
if (type == NWAM_OBJECT_TYPE_NCU ||
type == NWAM_OBJECT_TYPE_UNKNOWN) {
&ncuh);
if (ret == NWAM_ENTITY_MULTIPLE_VALUES) {
NWAM_NCU_TYPE_LINK, 0, &ncuh)
== NWAM_SUCCESS) {
}
NWAM_NCU_TYPE_INTERFACE, 0, &ncuh)
== NWAM_SUCCESS) {
}
} else if (ret == NWAM_SUCCESS) {
}
}
}
if (type == NWAM_OBJECT_TYPE_LOC ||
type == NWAM_OBJECT_TYPE_UNKNOWN) {
}
}
if (type == NWAM_OBJECT_TYPE_ENM ||
type == NWAM_OBJECT_TYPE_UNKNOWN) {
}
}
/* If at least object is found, don't return error */
if (found)
ret = NWAM_SUCCESS;
else
}
/* object-name not given in command-line */
/*
* If type given (type != UNKNOWN), just walk objects in that
* type. Otherwise, walk all ncp, ncu, loc and enm.
*/
if (type == NWAM_OBJECT_TYPE_NCP ||
type == NWAM_OBJECT_TYPE_UNKNOWN) {
if (ret != NWAM_SUCCESS)
goto done;
}
/* no UNKNOWN for NCUs. They walked with active NCP above */
if (type == NWAM_OBJECT_TYPE_NCU) {
NULL);
if (ret != NWAM_SUCCESS)
goto done;
}
}
if (type == NWAM_OBJECT_TYPE_LOC ||
type == NWAM_OBJECT_TYPE_UNKNOWN) {
if (ret != NWAM_SUCCESS)
goto done;
}
if (type == NWAM_OBJECT_TYPE_ENM ||
type == NWAM_OBJECT_TYPE_UNKNOWN) {
if (ret != NWAM_SUCCESS)
goto done;
}
}
done:
else if (ret != NWAM_SUCCESS)
}
/*
* Print NWAM events.
*/
static void
{
int i;
break;
break;
"priority-group: %d",
break;
for (i = 0;
i++) {
"%d: %c%c ESSID %s BSSID %s", i + 1,
}
break;
break;
break;
gettext("connect to WLAN ESSID %s, BSSID %s %s"),
"succeeded" : "failed");
break;
case NWAM_EVENT_TYPE_INFO:
break;
break;
case NWAM_EVENT_TYPE_IF_STATE:
case AF_INET:
break;
case AF_INET6:
break;
}
"flags %x addr %s/%d",
} else {
}
break;
break;
"up" : "down";
break;
}
}
if (display) {
}
}
/*
* listens for events and displays them via the eventhandler() function above.
*/
/* ARGSUSED */
static void
{
err = nwam_events_init();
if (err != NWAM_SUCCESS)
/* print header */
DESCRIPTION_WIDTH, "DESCRIPTION");
do {
/*
* Needed for stdout redirection to ensure event output is
* regularly flushed to file.
*/
if (err == NWAM_SUCCESS) {
}
} while (err == NWAM_SUCCESS);
}
/* May need to convert case-insensitive link name match to case-sensitive one */
static nwam_error_t
{
return (NWAM_ENTITY_NOT_FOUND);
if (err == NWAM_SUCCESS)
return (err);
}
static void
{
if (argc != 1)
if (err != NWAM_SUCCESS)
}
static void
{
if (argc != 1)
argv[0]);
}
if (err != NWAM_SUCCESS) {
linkname);
}
bssid[0] = '\0';
/* Loop until valid selection made */
for (;;) {
(void) printf("\n");
/* Display WLAN choices for user to select from */
for (i = 0; i < num_wlans; i++) {
(void) printf("%d: ESSID %s BSSID %s\n",
}
i + 1);
break;
}
/* If "Other" or a hidden WLAN is selected, ask for ESSID */
do {
/* If "Other" was selected, secmode must be specified. */
if (choice == i + 1) {
for (;;) {
!= NULL &&
security_mode <= 3)
break;
}
} else {
}
/*
* We have to determine if we have a key for this ESSID from
* the known WLAN list, since we cannot determine this from
* the scan results.
*/
else
} else {
sizeof (essid));
sizeof (bssid));
}
do {
"ESSID %s: "), essid);
if (security_mode == DLADM_WLAN_SECMODE_WEP) {
for (;;) {
(void) printf(
gettext("\nEnter key slot [1-4]: "));
keyslot <= 4)
break;
}
}
if (err != NWAM_SUCCESS)
}
if (err != NWAM_SUCCESS)
}
int
{
int i;
char *state;
(void) textdomain(TEXT_DOMAIN);
else
execname++;
if (argc < 2) {
}
if (cmdtab[i].cmd_needs_nwamd) {
SCF_STATE_STRING_ONLINE) != 0) {
die("enable '%s' to use '%s %s'",
}
}
}
}
return (1);
}