mgmt_scf.c revision a9fd9a9e12bea66c9ea9b31f4b6f0ef584933f59
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <siginfo.h>
#include <libscf.h>
#include <syslog.h>
#include <synch.h>
#include <libxml/xmlreader.h>
#include <sys/resource.h>
#include <iscsitgt_impl.h>
#include <umem.h>
#include <priv.h>
#include <libgen.h>
#include <ctype.h>
#include <pthread.h>
#include <pwd.h>
#include <auth_attr.h>
#include <sasl/saslutil.h>
#include "mgmt_scf.h"
#include "port.h"
#include "iscsi_conn.h"
#include "target.h"
#include "utility.h"
#include "iscsi_ffp.h"
#include "errcode.h"
#include "t10.h"
static int isnumber(char *s);
static pthread_mutex_t scf_conf_mutex;
static pthread_mutex_t scf_param_mutex;
{
return (True);
}
void
{
(void) pthread_mutex_destroy(&scf_conf_mutex);
(void) pthread_mutex_destroy(&scf_param_mutex);
}
void
{
if (h != NULL) {
int unbind = 0;
unbind = 1;
scf_scope_destroy(h->t_scope);
}
scf_pg_destroy(h->t_pg);
if (unbind)
(void) scf_handle_unbind(h->t_handle);
}
free(h);
}
}
mgmt_handle_init(void)
{
targ_scf_t *h;
if (h == NULL)
return (NULL);
if (scf_handle_bind(h->t_handle) == 0) {
h->t_scope) == 0) {
if (scf_scope_get_service(h->t_scope,
SA_TARGET_SVC_NAME, h->t_service) != 0)
goto error;
} else {
"Got local scope which is wrong\n");
goto error;
}
} else
goto error;
} else {
free(h);
h = NULL;
"iscsitgt could not access SMF repository: %s\n",
scf_strerror(scf_error()));
}
return (h);
mgmt_handle_fini(h);
scf_strerror(scf_error()));
return (NULL);
}
/*
* This function starts a transaction with name of a property group
* and name of its property. If the property group does not exist
* this function will create an empty property group.
*/
{
scf_strerror(scf_error()));
}
} else {
scf_strerror(scf_error()));
}
return (ret);
}
{
if (scf_transaction_commit(h->t_trans) < 0)
scf_pg_update(h->t_pg);
return (ret);
}
void
{
}
}
static Boolean_t
{
return (False);
}
}
return (True);
}
/*
* mgmt_get_main_config() loads main configuration
* from scf into a node tree.
* admin info is stored in "iscsitgt" property group
* target info is stored in "target_<name>" property group
* initiator info is stored in "initiator_<name>" property group
* tpgt info is stored in "tpgt_<number>" property group
*/
{
targ_scf_t *h = NULL;
char pname[32];
char valuebuf[MAXPATHLEN];
char passcode[32];
unsigned int outlen;
tgt_node_t *n;
tgt_node_t *pn;
tgt_node_t *vn;
h = mgmt_handle_init();
if (h == NULL)
return (False);
(void) pthread_mutex_lock(&scf_conf_mutex);
/* Basic Information is stored in iscsitgt pg */
goto error;
}
goto error;
goto error;
}
/* avoid load auth to incore data */
continue;
if (n == NULL)
goto error;
/* put version info into root node's attr */
tgt_node_add_attr(*node, n);
} else {
/* add other basic info into root node */
tgt_node_add(*node, n);
}
}
/*
* targets/initiators/tpgt information is
* stored as type "configuration" in scf
* each target's param is stored as type "parameter"
*/
== -1) {
goto error;
}
char *iname;
continue;
}
*iname = '\0';
iname++;
/*
* now pname is "target" or "initiator" or "tpgt"
* meanwhile iname is the actual name of the item
*/
if (n == NULL)
goto error;
goto error;
}
/* there may be many values in one property */
char *vname;
/* avoid load auth to incore data */
continue;
goto error;
tgt_node_add(n, pn);
} else {
goto error;
tgt_node_add(n, pn);
*vname = '\0';
> 0) {
valuebuf);
goto error;
}
}
}
tgt_node_add(*node, n);
}
/* chap-secrets are stored in "passwords" pgroup as "application" */
goto error;
}
/* avoid load auth to incore data */
continue;
/* max length of decoded passwd is 16B */
} else {
/* find corresponding initiator */
n = NULL;
while (n = tgt_node_next_child(*node,
XML_ELEMENT_INIT, n)) {
continue;
pn = tgt_node_alloc(
tgt_node_add(n, pn);
}
}
}
}
(void) pthread_mutex_unlock(&scf_conf_mutex);
return (True);
(void) pthread_mutex_unlock(&scf_conf_mutex);
mgmt_handle_fini(h);
return (False);
}
static int
isnumber(char *s)
{
register int c;
if (!s || !(*s))
return (0);
while ((c = *(s++)) != '\0') {
if (!isdigit(c))
return (0);
}
return (1);
}
static void
tgt_node_t *n)
{
scf_transaction_entry_t *e = NULL;
scf_value_t *v = NULL;
e = scf_entry_create(h->t_handle);
v = scf_value_create(h->t_handle);
} else {
}
scf_entry_add_value(e, v);
}
static void
tgt_node_t *p)
{
scf_transaction_entry_t *e = NULL;
scf_value_t *v = NULL;
tgt_node_t *c;
char *name;
e = scf_entry_create(h->t_handle);
v = scf_value_create(h->t_handle);
scf_value_set_astring(v, c->x_value);
scf_entry_add_value(e, v);
}
}
/*
* mgmt_config_save2scf() saves main configuration to scf
* See also : mgmt_get_main_config()
*/
{
targ_scf_t *h = NULL;
char pgname[64];
char passcode[32];
unsigned int outlen;
tgt_node_t *n = NULL;
h = mgmt_handle_init();
if (h == NULL)
return (False);
(void) pthread_mutex_lock(&scf_conf_mutex);
scf_pg_delete(h->t_pg);
}
scf_pg_delete(h->t_pg);
}
== -1) {
goto error;
}
scf_pg_delete(h->t_pg);
}
XML_ELEMENT_CHAPSECRET) == 0) {
continue;
}
/* so does the radius server secret */
XML_ELEMENT_RAD_SECRET) == 0) {
continue;
}
new_property(h, n);
}
}
new_property(h, n);
tgt_node_free(n);
new_property(h, n);
tgt_node_free(n);
}
continue;
n->x_value);
== True) {
XML_ELEMENT_CHAPSECRET) == 0) {
"I_%s", n->x_value);
continue;
}
/* normal property */
new_property(h, pn);
} else {
/* pn -> xxx-list */
new_value_list(h, pn);
}
new_property(h, tn);
new_property(h, tn);
}
}
}
/* Here we use sl_tail as a temporari var */
/* max length of encoded passwd is 24B */
passcode);
new_property(h, n);
tgt_node_free(n);
}
}
new_property(h, n);
tgt_node_free(n);
new_property(h, n);
tgt_node_free(n);
new_property(h, n);
tgt_node_free(n);
}
(void) pthread_mutex_unlock(&scf_conf_mutex);
return (True);
(void) pthread_mutex_unlock(&scf_conf_mutex);
mgmt_handle_fini(h);
return (False);
}
{
targ_scf_t *h = NULL;
char pgname[64];
tgt_node_t *n = NULL;
h = mgmt_handle_init();
if (h == NULL)
return (False);
(void) pthread_mutex_lock(&scf_param_mutex);
scf_pg_delete(h->t_pg);
}
/* now n is node of basic property */
new_property(h, n);
}
}
new_property(h, n);
tgt_node_free(n);
new_property(h, n);
tgt_node_free(n);
}
(void) pthread_mutex_unlock(&scf_param_mutex);
return (True);
(void) pthread_mutex_unlock(&scf_param_mutex);
mgmt_handle_fini(h);
return (False);
}
/*
* mgmt_get_param() get parameter of a specific LUN from scf
* Args:
* node - the node which parameters will be stored in mem
* target_name - the local target name
* lun - the LUN number
* See also : mgmt_param_save2scf()
*/
{
targ_scf_t *h = NULL;
char pname[64];
char pgname[64];
char valuebuf[MAXPATHLEN];
tgt_node_t *n;
h = mgmt_handle_init();
if (h == NULL)
return (False);
(void) pthread_mutex_lock(&scf_param_mutex);
goto error;
}
goto error;
goto error;
}
/* avoid load auth to incore data */
continue;
if (n == NULL)
goto error;
/* put version info into root node's attr */
tgt_node_add_attr(*node, n);
} else {
/* add other basic info into root node */
tgt_node_add(*node, n);
}
}
(void) pthread_mutex_unlock(&scf_param_mutex);
return (True);
(void) pthread_mutex_unlock(&scf_param_mutex);
mgmt_handle_fini(h);
return (False);
}
{
targ_scf_t *h = NULL;
char pgname[64];
h = mgmt_handle_init();
if (h == NULL)
return (False);
scf_pg_delete(h->t_pg);
mgmt_handle_fini(h);
return (True);
} else {
mgmt_handle_fini(h);
return (False);
}
}
/*
* mgmt_convert_param() converts legacy params file of each LUN
* to scf data. It will convert LUNs under one target each time.
* Args:
* dir - string of directory where param file is stored
* tnode - node tree which contains to a target
*/
{
char path[MAXPATHLEN];
int xml_fd = -1;
int n;
int lun_num;
continue;
continue;
continue;
n = xmlTextReaderRead(r);
while (n == 1) {
break;
}
n = xmlTextReaderRead(r);
}
if (n < 0) {
break;
}
!= True) {
break;
} else {
}
}
return (ret);
}
/*
* this function tries to convert configuration in files into scf
* it loads xml conf into node tree then dump them to scf with
* mgmt_config_save2scf()
* this function has 3 return values:
* CONVERT_OK: successfully converted
* CONVERT_INIT_NEW: configuration files dont exist, created a new scf entry
* CONVERT_FAIL: some error occurred in conversion and no scf entry created.
* In this case, user have to check files manually and try
* conversion again.
*/
{
targ_scf_t *h = NULL;
int xml_fd = -1;
int n;
char path[MAXPATHLEN];
h = mgmt_handle_init();
if (h == NULL)
return (CONVERT_FAIL);
/* check main config in pgroup iscsitgt */
ret = CONVERT_OK;
goto done;
}
/* check the conf files */
/*
* if there is no configuration file, initialize
* an empty scf entry
*/
new_property(h, node);
/* "daemonize" is set to true by default */
"true");
new_property(h, node);
new_property(h, node);
new_property(h, node);
} else {
ret = CONVERT_FAIL;
goto done;
}
True) {
new_property(h, node);
new_property(h, node);
new_property(h, node);
} else {
ret = CONVERT_FAIL;
}
goto done;
}
if (r != NULL) {
n = xmlTextReaderRead(r);
while (n == 1) {
break;
}
n = xmlTextReaderRead(r);
}
if (n < 0) {
ret = CONVERT_FAIL;
goto done;
}
main_config = node;
if (target_basedir == NULL)
/* Now convert targets' config if possible */
if (xml_fd != -1)
r = NULL;
xml_fd = -1;
target_basedir, "config.xml");
if (r != NULL) {
n = xmlTextReaderRead(r);
while (n == 1) {
break;
}
n = xmlTextReaderRead(r);
}
if (n < 0) {
ret = CONVERT_FAIL;
goto done;
}
/* now combine main_config and node */
if (node) {
tgt_node_dup(next));
}
}
if (mgmt_config_save2scf() != True) {
if (xml_fd != -1)
ret = CONVERT_FAIL;
goto done;
}
/* Copy files into backup dir */
ret = CONVERT_FAIL;
goto done;
}
target_basedir, "config.xml");
continue;
}
!= True) {
ret = CONVERT_FAIL;
goto done;
}
}
ret = CONVERT_OK;
} else {
ret = CONVERT_FAIL;
goto done;
}
} else {
ret = CONVERT_FAIL;
goto done;
}
done:
if (xml_fd != -1)
mgmt_handle_fini(h);
return (ret);
}
/*
* backup() moves configuration xml files into backup directory
* under base-directory. It is called once when converting legacy
* xml data into scf data.
* Param files will be renamed as params.<lun#>.<initiatorname>
*/
static void
{
char dest[MAXPATHLEN];
char *bname;
if (ext) {
} else {
}
if (fork() == 0) {
exit(0);
}
}
/*
* check_auth() checks if a given cred has
* the authorization to create/remove targets/initiators/tpgt
* cred is from the door call.
*/
{
targ_scf_t *h = NULL;
int exit_code = 1;
const priv_set_t *eset;
switch (pid) {
case 0:
/* Child process to check authorization */
exit(-1);
}
exit(-1);
}
h = mgmt_handle_init();
if (h == NULL) {
exit(1);
}
scf_pg_delete(h->t_pg);
exit_code = 0;
} else {
exit_code = 1;
}
mgmt_handle_fini(h);
break;
case -1:
/* Fail to fork */
default:
if (exit_code == 0)
else
break;
}
return (ret);
}
/*
* check_auth_modify() checks if a given cred has
* cred is from the door call.
*/
{
targ_scf_t *h = NULL;
int exit_code = -1;
tgt_node_t *n = NULL;
const priv_set_t *eset;
switch (pid) {
case 0:
/* Child process to check authorization */
exit(-1);
}
exit(-1);
}
h = mgmt_handle_init();
if (h == NULL) {
exit(-1);
}
new_property(h, n);
tgt_node_free(n);
if (mgmt_transaction_end(h) == True) {
exit_code = 0;
} else {
exit_code = -1;
}
} else {
exit_code = -1;
}
if (exit_code != 0) {
mgmt_handle_fini(h);
}
if (ent) {
ent, "dummy");
}
}
mgmt_handle_fini(h);
break;
case -1:
/* Fail to fork */
default:
if (exit_code == 0)
else
break;
}
return (ret);
}