linkprop.c revision 789e0dbbcdddab55f064dbca13950cb068a30efe
/*
* 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
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <libdevinfo.h>
#include <zone.h>
#include <libdllink.h>
#include <libdladm_impl.h>
#include <libdlwlan.h>
#include <dlfcn.h>
#include <link.h>
static dladm_status_t i_dladm_set_prop_db(const char *, const char *,
char **, uint_t);
static dladm_status_t i_dladm_get_prop_db(const char *, const char *,
char **, uint_t *);
const char *, char **, uint_t *);
static dladm_status_t i_dladm_set_prop_temp(const char *, const char *,
char **);
typedef struct val_desc {
char *vd_name;
void *vd_val;
} val_desc_t;
struct prop_desc;
uint_t, val_desc_t **);
static pd_getf_t do_get_zone;
static pd_setf_t do_set_zone;
static pd_checkf_t do_check_zone;
typedef struct prop_desc {
char *pd_name;
} prop_desc_t;
static prop_desc_t prop_table[] = {
};
{
return (DLADM_STATUS_BADARG);
if ((flags & DLADM_OPT_TEMP) != 0) {
if (status == DLADM_STATUS_TEMPONLY &&
(flags & DLADM_OPT_PERSIST) != 0)
return (DLADM_STATUS_TEMPONLY);
if (status == DLADM_STATUS_NOTFOUND) {
if (dladm_wlan_is_valid(link)) {
}
}
if (status != DLADM_STATUS_OK)
return (status);
}
if ((flags & DLADM_OPT_PERSIST) != 0) {
return (DLADM_STATUS_TEMPONLY);
}
return (status);
}
{
int i;
return (DLADM_STATUS_BADARG);
/* For wifi links, show wifi properties first */
if (dladm_wlan_is_valid(link)) {
if (status != DLADM_STATUS_OK)
return (status);
}
/* Then show data-link properties if there are any */
for (i = 0; i < MAX_PROPS; i++) {
break;
}
return (DLADM_STATUS_OK);
}
{
return (DLADM_STATUS_BADARG);
if (type == DLADM_PROP_VAL_PERSISTENT) {
return (DLADM_STATUS_TEMPONLY);
}
if (status != DLADM_STATUS_NOTFOUND)
return (status);
if (dladm_wlan_is_valid(link)) {
}
return (DLADM_STATUS_BADARG);
}
/*
* Data structures used for implementing persistent link properties
*/
typedef struct linkprop_val {
const char *lv_name;
struct linkprop_val *lv_nextval;
typedef struct linkprop_info {
const char *li_name;
struct linkprop_info *li_nextprop;
struct linkprop_val *li_val;
typedef struct linkprop_db_state linkprop_db_state_t;
char *, linkprop_info_t *, dladm_status_t *);
struct linkprop_db_state {
const char *ls_link;
const char *ls_propname;
char **ls_propval;
};
static void
{
}
}
}
/*
* Generate an entry in the link property database.
* Each entry has this format:
* <linkname> <prop0>=<val0>,...,<valn>;...;<propn>=<val0>,...,<valn>;
*/
static void
{
char tmpbuf[MAXLINELEN];
/*
* Delete line if there are no properties left.
*/
buf[0] = '\0';
return;
}
/*
* Skip properties without values.
*/
continue;
}
}
return;
}
}
/*
* This function is used to update or create an entry in the persistent db.
* process_linkprop_db() will first scan the db for an entry matching the
* specified link. If a match is found, this function is invoked with the
* entry's contents (buf) and its linked-list representation (listp). lsp
* holds the name and values of the property to be added or updated; this
* information will be merged with listp. Subsequently, an updated entry
* will be written to buf, which will in turn be written to disk by
* process_linkprop_db(). If no entry matches the specified link, listp
* will be NULL; a new entry will be generated in this case and it will
* contain only the property information in lsp.
*/
static boolean_t
{
int i;
buf[0] = '\0';
return (B_FALSE);
}
/*
* Find the linkprop we want to change.
*/
break;
}
/*
* If the linkprop is not found, append it to the list.
*/
goto fail;
}
/*
* nlip will need to be freed later if there is no list to
* append to.
*/
} else {
/*
* If the linkprop is found, delete the existing values from it.
*/
}
}
/*
* Fill our linkprop with the specified values.
*/
for (i = 0; i < *lsp->ls_valcntp; i++) {
goto fail;
}
}
} else {
}
return (B_FALSE);
fail:
return (B_FALSE);
}
/*
* This function is used for retrieving the values for a specific property.
* It gets called if an entry matching the specified link exists in the db.
* The entry is converted into a linked-list listp. This list is then scanned
* for the specified property name; if a matching property exists, its
* associated values are copied to the array lsp->ls_propval.
*/
/* ARGSUSED */
static boolean_t
{
/*
* Find the linkprop we want to get.
*/
break;
}
return (B_FALSE);
}
return (B_FALSE);
}
}
/*
* This function is meant to be called at most once for each call
* to process_linkprop_db(). For this reason, it's ok to overwrite
* the caller's valcnt array size with the actual number of values
* returned.
*/
return (B_FALSE);
}
/*
* This is used for initializing link properties.
* Unlike the other routines, this gets called for every entry in the
* database. lsp->ls_link is not user-specified but instead is set to
* the current link being processed.
*/
/* ARGSUSED */
static boolean_t
{
char **propval;
/*
* Construct the propval array and fill it with
* values from listp.
*/
break;
}
/*
* We continue with initializing other properties even
* after encountering an error. This error will be
* propagated to the caller via 'statusp'.
*/
if (status != DLADM_STATUS_OK)
}
return (B_TRUE);
}
static int
{
int i, len;
char *curr;
for (i = 0; i < len; i++) {
char c = buf[i];
/*
* Move to the next character if there is no match and
* if we have not reached the last character.
*/
continue;
if (match) {
/*
* Nul-terminate the string pointed to by 'curr'.
*/
buf[i] = '\0';
if (*curr == '\0')
goto fail;
}
/*
* We get here after we have processed the "<prop>="
* pattern. The pattern we are now interested in is
* "<val0>,<val1>,...,<valn>;". For each value we
* find, a linkprop_val_t will be allocated and
* added to the current 'lip'.
*/
if (c == '=')
goto fail;
goto fail;
if (c == ';') {
}
} else {
/*
* lip == NULL indicates that 'curr' must be refering
* to a property name. We allocate a new linkprop_info_t
* append it to the list given by the caller.
*/
if (c != '=')
goto fail;
goto fail;
}
}
/*
* The list must be non-empty and the last character must be ';'.
*/
goto fail;
return (0);
fail:
return (-1);
}
static boolean_t
{
/*
* Skip leading spaces, blank lines, and comments.
*/
for (i = 0; i < len; i++) {
break;
}
return (B_TRUE);
/*
* Skip links we're not interested in.
* Note that strncmp() and isspace() are used here
* instead of strtok() and strcmp() because we don't
* want to modify buf in case it does not contain the
* specified link.
*/
return (B_TRUE);
} else {
/*
* If a link is not specified, find the link name
* and assign it to lsp->ls_link.
*/
goto fail;
}
goto fail;
/*
* Now find the list of link properties.
*/
goto fail;
goto fail;
if (nolink)
return (cont);
fail:
if (nolink)
/*
* Delete corrupted line.
*/
buf[0] = '\0';
return (B_TRUE);
}
static dladm_status_t
{
char buf[MAXLINELEN];
/*
* This loop processes each line of the configuration file.
* buf can potentially be modified by process_linkprop_line().
* If this is a write operation and buf is not truncated, buf will
* be written to disk. process_linkprop_line() will no longer be
* called after it returns B_FALSE; at which point the remainder
* of the file will continue to be read and, if necessary, written
* to disk as well.
*/
if (cont)
break;
}
}
return (status);
/*
* If the specified link is not found above, we add the
* link and its properties to the configuration file.
*/
}
return (status);
}
(i_dladm_rw_db("/etc/dladm/linkprop.conf", \
static dladm_status_t
{
}
static dladm_status_t
{
}
dladm_init_linkprop(void)
{
}
static dladm_status_t
{
int fd;
return (dladm_errno2status(errno));
return (status);
}
*zidp = GLOBAL_ZONEID;
else
return (DLADM_STATUS_OK);
}
typedef int (*zone_get_devroot_t)(char *, char *, size_t);
static int
{
char root[MAXPATHLEN];
void *dlhandle;
void *sym;
int ret;
return (-1);
return (-1);
}
return (ret);
}
static dladm_status_t
{
char path[MAXPATHLEN];
char zone_name[ZONENAME_MAX];
return (dladm_errno2status(errno));
return (dladm_errno2status(errno));
return (dladm_errno2status(errno));
goto cleanup;
}
if (di_prof_commit(prof) != 0)
if (prof)
return (status);
}
static dladm_status_t
{
char path[MAXPATHLEN];
char zone_name[ZONENAME_MAX];
return (dladm_errno2status(errno));
return (dladm_errno2status(errno));
return (dladm_errno2status(errno));
goto cleanup;
}
if (di_prof_commit(prof) != 0)
if (prof)
return (status);
}
static dladm_status_t
{
char zone_name[ZONENAME_MAX];
if (status != DLADM_STATUS_OK)
return (status);
*val_cnt = 1;
if (zid != GLOBAL_ZONEID) {
return (dladm_errno2status(errno));
} else {
*prop_val[0] = '\0';
}
return (DLADM_STATUS_OK);
}
static dladm_status_t
{
if (val_cnt != 1)
return (DLADM_STATUS_BADVALCNT);
if (status != DLADM_STATUS_OK)
return (status);
/* Do nothing if setting to current value */
return (DLADM_STATUS_OK);
if (zid_old != GLOBAL_ZONEID) {
return (dladm_errno2status(errno));
goto rollback1;
}
if (status != DLADM_STATUS_OK)
goto rollback2;
}
if (zid_new != GLOBAL_ZONEID) {
goto rollback3;
}
goto rollback3;
}
if (status != DLADM_STATUS_OK) {
goto rollback3;
}
}
return (DLADM_STATUS_OK);
if (zid_old != GLOBAL_ZONEID)
if (zid_old != GLOBAL_ZONEID)
return (status);
}
/* ARGSUSED */
static dladm_status_t
val_desc_t **vdpp)
{
if (val_cnt != 1)
return (DLADM_STATUS_BADVALCNT);
return (DLADM_STATUS_BADVAL);
if (zid != GLOBAL_ZONEID) {
sizeof (flags)) < 0) {
return (dladm_errno2status(errno));
}
if (!(flags & ZF_NET_EXCL)) {
return (DLADM_STATUS_BADVAL);
}
}
return (DLADM_STATUS_NOMEM);
return (DLADM_STATUS_OK);
}
static dladm_status_t
{
int i;
return (DLADM_STATUS_BADARG);
for (i = 0; i < MAX_PROPS; i++)
break;
if (i == MAX_PROPS)
return (DLADM_STATUS_NOTFOUND);
pdp = &prop_table[i];
switch (type) {
case DLADM_PROP_VAL_CURRENT:
break;
case DLADM_PROP_VAL_DEFAULT:
break;
}
*val_cntp = 1;
break;
break;
}
if (cnt == 0) {
} else {
for (i = 0; i < cnt; i++) {
}
}
break;
default:
break;
}
return (status);
}
static dladm_status_t
{
return (DLADM_STATUS_TEMPONLY);
return (DLADM_STATUS_PROPRDONLY);
else
if (status != DLADM_STATUS_OK)
return (status);
} else {
return (DLADM_STATUS_NOTSUP);
return (DLADM_STATUS_NOMEM);
cnt = 1;
}
return (status);
}
static dladm_status_t
{
int i;
for (i = 0; i < MAX_PROPS; i++) {
continue;
flags);
status = s;
break;
} else {
if (s != DLADM_STATUS_OK &&
s != DLADM_STATUS_NOTSUP) {
status = s;
break;
}
}
}
if (!found)
return (status);
}
static boolean_t
{
int i;
for (i = 0; i < MAX_PROPS; i++) {
continue;
if (pdp->pd_temponly)
return (B_TRUE);
}
return (B_FALSE);
}