libiscsit.c revision bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * or http://www.opensolaris.org/os/licensing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
327151705b7439cb7ab35c370f682cac7ef9523aCathy Zhou * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/types.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/stat.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <ctype.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <fcntl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <uuid/uuid.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <errno.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <unistd.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <strings.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <libintl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <libstmf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <libiscsit.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/iscsi_protocol.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/iscsit/isns_protocol.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/* From iscsitgtd */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai#define TARGET_NAME_VERS 2
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* this should be defined someplace central... */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define ISCSI_NAME_LEN_MAX 223
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* max length of a base64 encoded secret */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define MAX_BASE64_LEN 341
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* Default RADIUS server port */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#define DEFAULT_RADIUS_PORT 1812
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * The kernel reserves target portal group tag value 1 as the default.
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey */
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey#define ISCSIT_DEFAULT_TPGT 1
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#define MAXTAG 0xffff
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* helper for property list validation */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define PROPERR(lst, key, value) { \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (lst) { \
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) nvlist_add_string(lst, key, value); \
843e19887f64dde75055cf8842fc4db2171eff45johnlev } \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* helper function declarations */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouit_iqn_generate(char *iqn_buf, int iqn_buf_len, char *opt_iqn_suffix);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengit_val_pass(char *name, char *val, nvlist_t *e);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* consider making validate funcs public */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengit_validate_configprops(nvlist_t *nvl, nvlist_t *errs);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengit_validate_tgtprops(nvlist_t *nvl, nvlist_t *errs);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengit_validate_iniprops(nvlist_t *nvl, nvlist_t *errs);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Function: it_config_load()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Allocate and create an it_config_t structure representing the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * current iSCSI configuration. This structure is compiled using
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the 'provider' data returned by stmfGetProviderData(). If there
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * is no provider data associated with iscsit, the it_config_t
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * structure will be set to a default configuration.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Parameters:
a776d98e5f349dbb7f5a47eca48f50e6117adcb7Robert Mustacchi * cfg A C representation of the current iSCSI configuration
a776d98e5f349dbb7f5a47eca48f50e6117adcb7Robert Mustacchi *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Return Values:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * 0 Success
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ENOMEM Could not allocate resources
843e19887f64dde75055cf8842fc4db2171eff45johnlev * EINVAL Invalid parameter
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
da14cebe459d3275048785f25bd869cb09b5307fEric Chengit_config_load(it_config_t **cfg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int ret = 0;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey nvlist_t *cfg_nv = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev it_config_t *newcfg = NULL;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey uint64_t stmf_token = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
eae72b5b807baa9116e64502cbb278edf15f3146Sebastien Roy if (!cfg) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (EINVAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *cfg = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = stmfGetProviderDataProt(ISCSIT_MODNAME, &cfg_nv,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng STMF_PORT_PROVIDER_TYPE, &stmf_token);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((ret == STMF_STATUS_SUCCESS) ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (ret == STMF_ERROR_NOT_FOUND)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If not initialized yet, return empty it_config_t
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Else, convert nvlist to struct
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = it_nv_to_config(cfg_nv, &newcfg);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng newcfg->stmf_token = stmf_token;
843e19887f64dde75055cf8842fc4db2171eff45johnlev *cfg = newcfg;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
eae72b5b807baa9116e64502cbb278edf15f3146Sebastien Roy return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Function: it_config_commit()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Informs the iscsit service that the configuration has changed and
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * commits the new configuration to persistent store by calling
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * stmfSetProviderData. This function can be called multiple times
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * during a configuration sequence if necessary.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Parameters:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * cfg A C representation of the current iSCSI configuration
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Return Values:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 0 Success
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ENOMEM Could not allocate resources
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * EINVAL Invalid it_config_t structure
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * TBD ioctl() failed
eae72b5b807baa9116e64502cbb278edf15f3146Sebastien Roy * TBD could not save config to STMF
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevit_config_commit(it_config_t *cfg)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ret;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng nvlist_t *cfgnv = NULL;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey char *packednv = NULL;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey int iscsit_fd = -1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t pnv_size;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng iscsit_ioc_set_config_t iop;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng it_tgt_t *tgtp;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (!cfg) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (EINVAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng iscsit_fd = open(ISCSIT_NODE, O_RDWR|O_EXCL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (iscsit_fd == -1) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey ret = errno;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = it_config_to_nv(cfg, &cfgnv);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret == 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ret = nvlist_size(cfgnv, &pnv_size, NV_ENCODE_NATIVE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz packednv = malloc(pnv_size);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!packednv) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = ENOMEM;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret = nvlist_pack(cfgnv, &packednv, &pnv_size,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou NV_ENCODE_NATIVE, 0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Send the changes to the kernel first, for now. Kernel
843e19887f64dde75055cf8842fc4db2171eff45johnlev * will be the final sanity check before config is saved
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * persistently.
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey *
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * XXX - this leaves open the simultaneous-change hole
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * that STMF was trying to solve, but is a better sanity
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * check. Final decision on save order/config generation
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * number TBD.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (ret == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng iop.set_cfg_vers = ISCSIT_API_VERS0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng iop.set_cfg_pnvlist = packednv;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng iop.set_cfg_pnvlist_len = pnv_size;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((ioctl(iscsit_fd, ISCSIT_IOC_SET_CONFIG, &iop)) != 0) {
327151705b7439cb7ab35c370f682cac7ef9523aCathy Zhou ret = errno;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /*
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * Before saving the config persistently, remove any
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * PROP_OLD_TARGET_NAME entries. This is only interesting to
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * the active service.
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy */
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (ret == 0) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy tgtp = cfg->config_tgt_list;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy for (; tgtp != NULL; tgtp = tgtp->tgt_next) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (!tgtp->tgt_properties) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy continue;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy }
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (nvlist_exists(tgtp->tgt_properties,
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy PROP_OLD_TARGET_NAME)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) nvlist_remove_all(tgtp->tgt_properties,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey PROP_OLD_TARGET_NAME);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * stmfGetProviderDataProt() checks to ensure
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * that the config data hasn't changed since we fetched it.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The kernel now has a version we need to save persistently.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * CLI will 'do the right thing' and warn the user if it
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * gets STMF_ERROR_PROV_DATA_STALE. We'll try once to revert
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * the kernel to the persistently saved data, but ultimately,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * it's up to the administrator to validate things are as they
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * want them to be.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = stmfSetProviderDataProt(ISCSIT_MODNAME, cfgnv,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng STMF_PORT_PROVIDER_TYPE, &(cfg->stmf_token));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ret == STMF_STATUS_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (ret == STMF_ERROR_NOMEM) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret = ENOMEM;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (ret == STMF_ERROR_PROV_DATA_STALE) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int st;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou it_config_t *rcfg = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou st = it_config_load(&rcfg);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (st == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) it_config_commit(rcfg);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou it_config_free(rcfg);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) close(iscsit_fd);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if (packednv) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng free(packednv);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (cfgnv) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey nvlist_free(cfgnv);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (ret);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Function: it_config_setprop()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Validate the provided property list and set the global properties
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * for iSCSI Target. If errlist is not NULL, returns detailed
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * errors for each property that failed. The format for errorlist
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * is key = property, value = error string.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Parameters:
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey *
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * cfg The current iSCSI configuration obtained from
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * it_config_load()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * proplist nvlist_t containing properties for this target.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * errlist (optional) nvlist_t of errors encountered when
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * validating the properties.
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Return Values:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 0 Success
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * EINVAL Invalid property
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey */
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskeyint
da14cebe459d3275048785f25bd869cb09b5307fEric Chengit_config_setprop(it_config_t *cfg, nvlist_t *proplist, nvlist_t **errlist)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey int ret;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng it_portal_t *isns = NULL;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey it_portal_t *pnext = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng it_portal_t *newisnslist = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char **arr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint32_t count;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint32_t newcount;
843e19887f64dde75055cf8842fc4db2171eff45johnlev nvlist_t *cprops = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *val = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!cfg || !proplist) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey return (EINVAL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (errlist) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey (void) nvlist_alloc(errlist, 0, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * copy the existing properties, merge, then validate
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the merged properties before committing them.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (cfg->config_global_properties) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = nvlist_dup(cfg->config_global_properties, &cprops, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = nvlist_alloc(&cprops, NV_UNIQUE_NAME, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* base64 encode the radius secret, if it's changed */
843e19887f64dde75055cf8842fc4db2171eff45johnlev val = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) nvlist_lookup_string(proplist, PROP_RADIUS_SECRET, &val);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (val) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char bsecret[MAX_BASE64_LEN];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = it_val_pass(PROP_RADIUS_SECRET, val, *errlist);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) memset(bsecret, 0, MAX_BASE64_LEN);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = iscsi_binary_to_base64_str((uint8_t *)val,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strlen(val), bsecret, MAX_BASE64_LEN);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* replace the value in the nvlist */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = nvlist_add_string(proplist,
843e19887f64dde75055cf8842fc4db2171eff45johnlev PROP_RADIUS_SECRET, bsecret);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = nvlist_merge(cprops, proplist, 0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* see if we need to remove the radius server setting */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng val = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) nvlist_lookup_string(cprops, PROP_RADIUS_SERVER, &val);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (val && (strcasecmp(val, "none") == 0)) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) nvlist_remove_all(cprops, PROP_RADIUS_SERVER);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* and/or remove the alias */
843e19887f64dde75055cf8842fc4db2171eff45johnlev val = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) nvlist_lookup_string(cprops, PROP_ALIAS, &val);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (val && (strcasecmp(val, "none") == 0)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) nvlist_remove_all(cprops, PROP_ALIAS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ret == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = it_validate_configprops(cprops, *errlist);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (cprops) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nvlist_free(cprops);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (ret);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Update iSNS server list, if exists in provided property list.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret = nvlist_lookup_string_array(proplist, PROP_ISNS_SERVER,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &arr, &count);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ret == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* special case: if "none", remove all defined */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcasecmp(arr[0], "none") != 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret = it_array_to_portallist(arr, count,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ISNS_DEFAULT_SERVER_PORT, &newisnslist, &newcount);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou newisnslist = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou newcount = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) nvlist_remove_all(cprops, PROP_ISNS_SERVER);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ret == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev isns = cfg->config_isns_svr_list;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while (isns) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pnext = isns->next;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou free(isns);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou isns = pnext;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey cfg->config_isns_svr_list = newisnslist;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cfg->config_isns_svr_count = newcount;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Replace the array in the nvlist to ensure
843e19887f64dde75055cf8842fc4db2171eff45johnlev * duplicates are properly removed & port numbers
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * are added.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (newcount > 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int i = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char **newarray;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
843e19887f64dde75055cf8842fc4db2171eff45johnlev newarray = malloc(sizeof (char *) * newcount);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (newarray == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = ENOMEM;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai for (isns = newisnslist; isns != NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai isns = isns->next) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) sockaddr_to_str(
843e19887f64dde75055cf8842fc4db2171eff45johnlev &(isns->portal_addr),
843e19887f64dde75055cf8842fc4db2171eff45johnlev &(newarray[i++]));
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) nvlist_add_string_array(cprops,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng PROP_ISNS_SERVER, newarray,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng newcount);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < newcount; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (newarray[i]) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng free(newarray[i]);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng free(newarray);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (ret == ENOENT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* not an error */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ret == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* replace the global properties list */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nvlist_free(cfg->config_global_properties);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cfg->config_global_properties = cprops;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (cprops) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nvlist_free(cprops);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (ret);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Function: it_config_free()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Free any resources associated with the it_config_t structure.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Parameters:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * cfg A C representation of the current iSCSI configuration
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengit_config_free(it_config_t *cfg)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng it_config_free_cmn(cfg);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Function: it_tgt_create()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Allocate and create an it_tgt_t structure representing a new iSCSI
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * target node. If tgt_name is NULL, then a unique target node name will
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * be generated automatically. Otherwise, the value of tgt_name will be
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * used as the target node name. The new it_tgt_t structure is added to
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the target list (cfg_tgt_list) in the configuration structure, and the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * new target will not be instantiated until the modified configuration
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * is committed by calling it_config_commit().
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Parameters:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * cfg The current iSCSI configuration obtained from
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * it_config_load()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * tgt Pointer to an iSCSI target structure
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * tgt_name The target node name for the target to be created.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The name must be in either IQN or EUI format. If
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * this value is NULL, a node name will be generated
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * automatically in IQN format.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Return Values:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * 0 Success
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ENOMEM Could not allocated resources
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * EINVAL Invalid parameter
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * EFAULT Invalid iSCSI name specified
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouint
d62bc4badc1c1f1549c961cfb8b420e650e1272byzit_tgt_create(it_config_t *cfg, it_tgt_t **tgt, char *tgt_name)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int ret = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng it_tgt_t *ptr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng it_tgt_t *cfgtgt;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char *namep = tgt_name;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz char buf[ISCSI_NAME_LEN_MAX + 1];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!cfg || !tgt) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey return (EINVAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!namep) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* generate a name */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = it_iqn_generate(buf, sizeof (buf), NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev namep = buf;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* validate the passed-in name */
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if (!validate_iscsi_name(namep)) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (EFAULT);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* make sure this name isn't already on the list */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cfgtgt = cfg->config_tgt_list;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while (cfgtgt != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (strcmp(namep, cfgtgt->tgt_name) == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EEXIST);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cfgtgt = cfgtgt->tgt_next;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ptr = calloc(1, sizeof (it_tgt_t));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ptr == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (ENOMEM);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(ptr->tgt_name, namep, sizeof (ptr->tgt_name));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ptr->tgt_generation = 1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ptr->tgt_next = cfg->config_tgt_list;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey cfg->config_tgt_list = ptr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cfg->config_tgt_count++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *tgt = ptr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * Function: it_tgt_setprop()
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Validate the provided property list and set the properties for
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai * the specified target. If errlist is not NULL, returns detailed
843e19887f64dde75055cf8842fc4db2171eff45johnlev * errors for each property that failed. The format for errorlist
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * is key = property, value = error string.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Parameters:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * cfg The current iSCSI configuration obtained from
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * it_config_load()
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * tgt Pointer to an iSCSI target structure
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * proplist nvlist_t containing properties for this target.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * errlist (optional) nvlist_t of errors encountered when
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * validating the properties.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Return Values:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * 0 Success
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * EINVAL Invalid property
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai *
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai */
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiint
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavaiit_tgt_setprop(it_config_t *cfg, it_tgt_t *tgt, nvlist_t *proplist,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey nvlist_t **errlist)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int ret;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng nvlist_t *tprops = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char *val = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (!cfg || !tgt || !proplist) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai if (errlist) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai (void) nvlist_alloc(errlist, 0, 0);
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * copy the existing properties, merge, then validate
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the merged properties before committing them.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (tgt->tgt_properties) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = nvlist_dup(tgt->tgt_properties, &tprops, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = nvlist_alloc(&tprops, NV_UNIQUE_NAME, 0);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = nvlist_merge(tprops, proplist, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* unset chap username or alias if requested */
843e19887f64dde75055cf8842fc4db2171eff45johnlev val = NULL;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey (void) nvlist_lookup_string(proplist, PROP_TARGET_CHAP_USER, &val);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if (val && (strcasecmp(val, "none") == 0)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) nvlist_remove_all(tprops, PROP_TARGET_CHAP_USER);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng val = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) nvlist_lookup_string(proplist, PROP_ALIAS, &val);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (val && (strcasecmp(val, "none") == 0)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) nvlist_remove_all(tprops, PROP_ALIAS);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* base64 encode the CHAP secret, if it's changed */
843e19887f64dde75055cf8842fc4db2171eff45johnlev val = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) nvlist_lookup_string(proplist, PROP_TARGET_CHAP_SECRET, &val);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if (val) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char bsecret[MAX_BASE64_LEN];
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = it_val_pass(PROP_TARGET_CHAP_SECRET, val, *errlist);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) memset(bsecret, 0, MAX_BASE64_LEN);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = iscsi_binary_to_base64_str((uint8_t *)val,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng strlen(val), bsecret, MAX_BASE64_LEN);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == 0) {
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy /* replace the value in the nvlist */
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey ret = nvlist_add_string(tprops,
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey PROP_TARGET_CHAP_SECRET, bsecret);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = it_validate_tgtprops(tprops, *errlist);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (tprops) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng nvlist_free(tprops);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (ret);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (tgt->tgt_properties) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz nvlist_free(tgt->tgt_properties);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tgt->tgt_properties = tprops;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Function: it_tgt_delete()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Delete target represented by 'tgt', where 'tgt' is an existing
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * it_tgt_structure within the configuration 'cfg'. The target removal
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * will not take effect until the modified configuration is committed
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * by calling it_config_commit().
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Parameters:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * cfg The current iSCSI configuration obtained from
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * it_config_load()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * tgt Pointer to an iSCSI target structure
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey *
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * force Set the target to offline before removing it from
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the config. If not specified, the operation will
327151705b7439cb7ab35c370f682cac7ef9523aCathy Zhou * fail if the target is determined to be online.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Return Values:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 0 Success
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * EBUSY Target is online
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengint
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskeyit_tgt_delete(it_config_t *cfg, it_tgt_t *tgt, boolean_t force)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int ret;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz it_tgt_t *ptgt;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng it_tgt_t *prev = NULL;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy stmfDevid devid;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy stmfTargetProperties props;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (!cfg || !tgt) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey return (0);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ptgt = cfg->config_tgt_list;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while (ptgt != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (strcmp(tgt->tgt_name, ptgt->tgt_name) == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey prev = ptgt;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ptgt = ptgt->tgt_next;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!ptgt) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * check to see if this target is offline. If it is not,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * and the 'force' flag is TRUE, tell STMF to offline it
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * before removing from the configuration.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret = stmfDevidFromIscsiName(ptgt->tgt_name, &devid);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ret != STMF_STATUS_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* can't happen? */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (EINVAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey ret = stmfGetTargetProperties(&devid, &props);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret == STMF_STATUS_SUCCESS) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * only other return is STMF_ERROR_NOT_FOUND, which
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * means we don't have to offline it.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (props.status == STMF_TARGET_PORT_ONLINE) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!force) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (EBUSY);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = stmfOfflineTarget(&devid);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ret != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EBUSY);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey if (prev) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey prev->tgt_next = ptgt->tgt_next;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* first one on the list */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cfg->config_tgt_list = ptgt->tgt_next;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey ptgt->tgt_next = NULL; /* Only free this target */
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cfg->config_tgt_count--;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng it_tgt_free(ptgt);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Function: it_tgt_free()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Frees an it_tgt_t structure. If tgt_next is not NULL, frees
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * all structures in the list.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengit_tgt_free(it_tgt_t *tgt)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey it_tgt_free_cmn(tgt);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Function: it_tpgt_create()
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Allocate and create an it_tpgt_t structure representing a new iSCSI
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * target portal group tag. The new it_tpgt_t structure is added to the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * target tpgt list (tgt_tpgt_list) in the it_tgt_t structure. The new
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * target portal group tag will not be instantiated until the modified
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * configuration is committed by calling it_config_commit().
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Parameters:
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * cfg The current iSCSI configuration obtained from
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * it_config_load()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * tgt Pointer to the iSCSI target structure associated
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * with the target portal group tag
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * tpgt Pointer to a target portal group tag structure
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * tpg_name The name of the TPG to be associated with this TPGT
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * tpgt_tag 16-bit numerical identifier for this TPGT. If
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * tpgt_tag is '0', this function will choose the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * tag number. If tpgt_tag is >0, and the requested
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * tag is determined to be in use, another value
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * will be chosen.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Return Values:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 0 Success
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * ENOMEM Could not allocate resources
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * EINVAL Invalid parameter
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * EEXIST Specified tag name is already used.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * E2BIG No available tag numbers
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskeyint
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerit_tpgt_create(it_config_t *cfg, it_tgt_t *tgt, it_tpgt_t **tpgt,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char *tpg_name, uint16_t tpgt_tag)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey it_tpgt_t *ptr = NULL;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai it_tpgt_t *cfgt;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai char tagid_used[MAXTAG + 1];
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai uint16_t tagid = ISCSIT_DEFAULT_TPGT;
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!cfg || !tgt || !tpgt || !tpg_name) {
4eaa471005973e11a6110b69fe990530b3b95a38Rishi Srivatsavai return (EINVAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) memset(&(tagid_used[0]), 0, sizeof (tagid_used));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Make sure this name and/or tag isn't already on the list
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey * At the same time, capture all tag ids in use for this target
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * About tag numbering -- since tag numbers are used by
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the iSCSI protocol, we should be careful about reusing
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * them too quickly. Start with a value greater than the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * highest one currently defined. If current == MAXTAG,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * just find an unused tag.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cfgt = tgt->tgt_tpgt_list;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey while (cfgt != NULL) {
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey tagid_used[cfgt->tpgt_tag] = 1;
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (strcmp(tpg_name, cfgt->tpgt_tpg_name) == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EEXIST);
4ac67f0276a8313b5cefec38af347b94b7bfb526Anurag S. Maskey }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (cfgt->tpgt_tag > tagid) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tagid = cfgt->tpgt_tag;
}
cfgt = cfgt->tpgt_next;
}
if ((tpgt_tag > ISCSIT_DEFAULT_TPGT) && (tpgt_tag < MAXTAG) &&
(tagid_used[tpgt_tag] == 0)) {
/* ok to use requested */
tagid = tpgt_tag;
} else if (tagid == MAXTAG) {
/*
* The highest value is used, find an available id.
*/
tagid = ISCSIT_DEFAULT_TPGT + 1;
for (; tagid < MAXTAG; tagid++) {
if (tagid_used[tagid] == 0) {
break;
}
}
if (tagid >= MAXTAG) {
return (E2BIG);
}
} else {
/* next available ID */
tagid++;
}
ptr = calloc(1, sizeof (it_tpgt_t));
if (!ptr) {
return (ENOMEM);
}
(void) strlcpy(ptr->tpgt_tpg_name, tpg_name,
sizeof (ptr->tpgt_tpg_name));
ptr->tpgt_generation = 1;
ptr->tpgt_tag = tagid;
ptr->tpgt_next = tgt->tgt_tpgt_list;
tgt->tgt_tpgt_list = ptr;
tgt->tgt_tpgt_count++;
tgt->tgt_generation++;
*tpgt = ptr;
return (0);
}
/*
* Function: it_tpgt_delete()
*
* Delete the target portal group tag represented by 'tpgt', where
* 'tpgt' is an existing is_tpgt_t structure within the target 'tgt'.
* The target portal group tag removal will not take effect until the
* modified configuration is committed by calling it_config_commit().
*
* Parameters:
* cfg The current iSCSI configuration obtained from
* it_config_load()
* tgt Pointer to the iSCSI target structure associated
* with the target portal group tag
* tpgt Pointer to a target portal group tag structure
*/
void
it_tpgt_delete(it_config_t *cfg, it_tgt_t *tgt, it_tpgt_t *tpgt)
{
it_tpgt_t *ptr;
it_tpgt_t *prev = NULL;
if (!cfg || !tgt || !tpgt) {
return;
}
ptr = tgt->tgt_tpgt_list;
while (ptr) {
if (ptr->tpgt_tag == tpgt->tpgt_tag) {
break;
}
prev = ptr;
ptr = ptr->tpgt_next;
}
if (!ptr) {
return;
}
if (prev) {
prev->tpgt_next = ptr->tpgt_next;
} else {
tgt->tgt_tpgt_list = ptr->tpgt_next;
}
ptr->tpgt_next = NULL;
tgt->tgt_tpgt_count--;
tgt->tgt_generation++;
it_tpgt_free(ptr);
}
/*
* Function: it_tpgt_free()
*
* Deallocates resources of an it_tpgt_t structure. If tpgt->next
* is not NULL, frees all members of the list.
*/
void
it_tpgt_free(it_tpgt_t *tpgt)
{
it_tpgt_free_cmn(tpgt);
}
/*
* Function: it_tpg_create()
*
* Allocate and create an it_tpg_t structure representing a new iSCSI
* target portal group. The new it_tpg_t structure is added to the global
* tpg list (cfg_tgt_list) in the it_config_t structure. The new target
* portal group will not be instantiated until the modified configuration
* is committed by calling it_config_commit().
*
* Parameters:
* cfg The current iSCSI configuration obtained from
* it_config_load()
* tpg Pointer to the it_tpg_t structure representing
* the target portal group
* tpg_name Identifier for the target portal group
* portal_ip_port A string containing an appropriatedly formatted
* IP address:port. Both IPv4 and IPv6 addresses are
* permitted. This value becomes the first portal in
* the TPG -- applications can add additional values
* using it_portal_create() before committing the TPG.
* Return Values:
* 0 Success
* ENOMEM Cannot allocate resources
* EINVAL Invalid parameter
* EEXIST Requested portal in use by another target portal
* group
*/
int
it_tpg_create(it_config_t *cfg, it_tpg_t **tpg, char *tpg_name,
char *portal_ip_port)
{
int ret;
it_tpg_t *ptr;
it_portal_t *portal = NULL;
if (!cfg || !tpg || !tpg_name || !portal_ip_port) {
return (EINVAL);
}
*tpg = NULL;
ptr = cfg->config_tpg_list;
while (ptr) {
if (strcmp(tpg_name, ptr->tpg_name) == 0) {
break;
}
ptr = ptr->tpg_next;
}
if (ptr) {
return (EEXIST);
}
ptr = calloc(1, sizeof (it_tpg_t));
if (!ptr) {
return (ENOMEM);
}
ptr->tpg_generation = 1;
(void) strlcpy(ptr->tpg_name, tpg_name, sizeof (ptr->tpg_name));
/* create the portal */
ret = it_portal_create(cfg, ptr, &portal, portal_ip_port);
if (ret != 0) {
free(ptr);
return (ret);
}
ptr->tpg_next = cfg->config_tpg_list;
cfg->config_tpg_list = ptr;
cfg->config_tpg_count++;
*tpg = ptr;
return (0);
}
/*
* Function: it_tpg_delete()
*
* Delete target portal group represented by 'tpg', where 'tpg' is an
* existing it_tpg_t structure within the global configuration 'cfg'.
* The target portal group removal will not take effect until the
* modified configuration is committed by calling it_config_commit().
*
* Parameters:
* cfg The current iSCSI configuration obtained from
* it_config_load()
* tpg Pointer to the it_tpg_t structure representing
* the target portal group
* force Remove this target portal group even if it's
* associated with one or more targets.
*
* Return Values:
* 0 Success
* EINVAL Invalid parameter
* EBUSY Portal group associated with one or more targets.
*/
int
it_tpg_delete(it_config_t *cfg, it_tpg_t *tpg, boolean_t force)
{
it_tpg_t *ptr;
it_tpg_t *prev = NULL;
it_tgt_t *tgt;
it_tpgt_t *tpgt;
it_tpgt_t *ntpgt;
if (!cfg || !tpg) {
return (EINVAL);
}
ptr = cfg->config_tpg_list;
while (ptr) {
if (strcmp(ptr->tpg_name, tpg->tpg_name) == 0) {
break;
}
prev = ptr;
ptr = ptr->tpg_next;
}
if (!ptr) {
return (0);
}
/*
* See if any targets are using this portal group.
* If there are, and the force flag is not set, fail.
*/
tgt = cfg->config_tgt_list;
while (tgt) {
tpgt = tgt->tgt_tpgt_list;
while (tpgt) {
ntpgt = tpgt->tpgt_next;
if (strcmp(tpgt->tpgt_tpg_name, tpg->tpg_name)
== 0) {
if (!force) {
return (EBUSY);
}
it_tpgt_delete(cfg, tgt, tpgt);
}
tpgt = ntpgt;
}
tgt = tgt->tgt_next;
}
/* Now that it's not in use anywhere, remove the TPG */
if (prev) {
prev->tpg_next = ptr->tpg_next;
} else {
cfg->config_tpg_list = ptr->tpg_next;
}
ptr->tpg_next = NULL;
cfg->config_tpg_count--;
it_tpg_free(ptr);
return (0);
}
/*
* Function: it_tpg_free()
*
* Deallocates resources associated with an it_tpg_t structure.
* If tpg->next is not NULL, frees all members of the list.
*/
void
it_tpg_free(it_tpg_t *tpg)
{
it_tpg_free_cmn(tpg);
}
/*
* Function: it_portal_create()
*
* Add an it_portal_t structure presenting a new portal to the specified
* target portal group. The change to the target portal group will not take
* effect until the modified configuration is committed by calling
* it_config_commit().
*
* Parameters:
* cfg The current iSCSI configration obtained from
* it_config_load()
* tpg Pointer to the it_tpg_t structure representing the
* target portal group
* portal Pointer to the it_portal_t structure representing
* the portal
* portal_ip_port A string containing an appropriately formatted
* IP address or IP address:port in either IPv4 or
* IPv6 format.
* Return Values:
* 0 Success
* ENOMEM Could not allocate resources
* EINVAL Invalid parameter
* EEXIST Portal already configured for another portal group
*/
int
it_portal_create(it_config_t *cfg, it_tpg_t *tpg, it_portal_t **portal,
char *portal_ip_port)
{
struct sockaddr_storage sa;
it_portal_t *ptr;
it_tpg_t *ctpg = NULL;
if (!cfg || !tpg || !portal || !portal_ip_port) {
return (EINVAL);
}
if ((it_common_convert_sa(portal_ip_port, &sa, ISCSI_LISTEN_PORT))
== NULL) {
return (EINVAL);
}
/* Check that this portal doesn't appear in any other tag */
ctpg = cfg->config_tpg_list;
while (ctpg) {
ptr = ctpg->tpg_portal_list;
for (; ptr != NULL; ptr = ptr->next) {
if (it_sa_compare(&(ptr->portal_addr), &sa) != 0) {
continue;
}
/*
* Existing in the same group is not an error,
* but don't add it again.
*/
if (strcmp(ctpg->tpg_name, tpg->tpg_name) == 0) {
return (0);
} else {
/* Not allowed */
return (EEXIST);
}
}
ctpg = ctpg->tpg_next;
}
ptr = calloc(1, sizeof (it_portal_t));
if (!ptr) {
return (ENOMEM);
}
(void) memcpy(&(ptr->portal_addr), &sa,
sizeof (struct sockaddr_storage));
ptr->next = tpg->tpg_portal_list;
tpg->tpg_portal_list = ptr;
tpg->tpg_portal_count++;
tpg->tpg_generation++;
return (0);
}
/*
* Function: it_portal_delete()
*
* Remove the specified portal from the specified target portal group.
* The portal removal will not take effect until the modified configuration
* is committed by calling it_config_commit().
*
* Parameters:
* cfg The current iSCSI configration obtained from
* it_config_load()
* tpg Pointer to the it_tpg_t structure representing the
* target portal group
* portal Pointer to the it_portal_t structure representing
* the portal
*/
void
it_portal_delete(it_config_t *cfg, it_tpg_t *tpg, it_portal_t *portal)
{
it_portal_t *ptr;
it_portal_t *prev;
if (!cfg || !tpg || !portal) {
return;
}
ptr = tpg->tpg_portal_list;
while (ptr) {
if (memcmp(&(ptr->portal_addr), &(portal->portal_addr),
sizeof (ptr->portal_addr)) == 0) {
break;
}
prev = ptr;
ptr = ptr->next;
}
if (!ptr) {
return;
}
if (prev) {
prev->next = ptr->next;
} else {
tpg->tpg_portal_list = ptr->next;
}
tpg->tpg_portal_count--;
tpg->tpg_generation++;
free(ptr);
}
/*
* Function: it_ini_create()
*
* Add an initiator context to the global configuration. The new
* initiator context will not be instantiated until the modified
* configuration is committed by calling it_config_commit().
*
* Parameters:
* cfg The current iSCSI configration obtained from
* it_config_load()
* ini Pointer to the it_ini_t structure representing
* the initiator context.
* ini_node_name The iSCSI node name of the remote initiator.
*
* Return Values:
* 0 Success
* ENOMEM Could not allocate resources
* EINVAL Invalid parameter.
* EFAULT Invalid initiator name
*/
int
it_ini_create(it_config_t *cfg, it_ini_t **ini, char *ini_node_name)
{
it_ini_t *ptr;
if (!cfg || !ini || !ini_node_name) {
return (EINVAL);
}
/*
* Ensure this is a valid ini name
*/
if (!validate_iscsi_name(ini_node_name)) {
return (EFAULT);
}
ptr = cfg->config_ini_list;
while (ptr) {
if (strcmp(ptr->ini_name, ini_node_name) == 0) {
break;
}
ptr = ptr->ini_next;
}
if (ptr) {
return (EEXIST);
}
ptr = calloc(1, sizeof (it_ini_t));
if (!ptr) {
return (ENOMEM);
}
(void) strlcpy(ptr->ini_name, ini_node_name, sizeof (ptr->ini_name));
ptr->ini_generation = 1;
/* nvlist for props? */
ptr->ini_next = cfg->config_ini_list;
cfg->config_ini_list = ptr;
cfg->config_ini_count++;
*ini = ptr;
return (0);
}
/*
* Function: it_ini_setprop()
*
* Validate the provided property list and set the initiator properties.
* If errlist is not NULL, returns detailed errors for each property
* that failed. The format for errorlist is key = property,
* value = error string.
*
* Parameters:
*
* ini The initiator being updated.
* proplist nvlist_t containing properties for this target.
* errlist (optional) nvlist_t of errors encountered when
* validating the properties.
*
* Return Values:
* 0 Success
* EINVAL Invalid property
*
*/
int
it_ini_setprop(it_ini_t *ini, nvlist_t *proplist, nvlist_t **errlist)
{
int ret;
nvlist_t *iprops = NULL;
char *val = NULL;
if (!ini || !proplist) {
return (EINVAL);
}
if (errlist) {
(void) nvlist_alloc(errlist, 0, 0);
}
/*
* copy the existing properties, merge, then validate
* the merged properties before committing them.
*/
if (ini->ini_properties) {
ret = nvlist_dup(ini->ini_properties, &iprops, 0);
} else {
ret = nvlist_alloc(&iprops, NV_UNIQUE_NAME, 0);
}
if (ret == 0) {
ret = nvlist_merge(iprops, proplist, 0);
}
/* unset chap username if requested */
if ((nvlist_lookup_string(proplist, PROP_CHAP_USER, &val)) == 0) {
if (strcasecmp(val, "none") == 0) {
(void) nvlist_remove_all(iprops, PROP_CHAP_USER);
}
}
/* base64 encode the CHAP secret, if it's changed */
if ((nvlist_lookup_string(proplist, PROP_CHAP_SECRET, &val)) == 0) {
char bsecret[MAX_BASE64_LEN];
ret = it_val_pass(PROP_CHAP_SECRET, val, *errlist);
if (ret == 0) {
(void) memset(bsecret, 0, MAX_BASE64_LEN);
ret = iscsi_binary_to_base64_str((uint8_t *)val,
strlen(val), bsecret, MAX_BASE64_LEN);
if (ret == 0) {
/* replace the value in the nvlist */
ret = nvlist_add_string(iprops,
PROP_CHAP_SECRET, bsecret);
}
}
}
if (ret == 0) {
ret = it_validate_iniprops(iprops, *errlist);
}
if (ret != 0) {
if (iprops) {
nvlist_free(iprops);
}
return (ret);
}
if (ini->ini_properties) {
nvlist_free(ini->ini_properties);
}
ini->ini_properties = iprops;
return (0);
}
/*
* Function: it_ini_delete()
*
* Remove the specified initiator context from the global configuration.
* The removal will not take effect until the modified configuration is
* committed by calling it_config_commit().
*
* Parameters:
* cfg The current iSCSI configration obtained from
* it_config_load()
* ini Pointer to the it_ini_t structure representing
* the initiator context.
*/
void
it_ini_delete(it_config_t *cfg, it_ini_t *ini)
{
it_ini_t *ptr;
it_ini_t *prev = NULL;
if (!cfg || !ini) {
return;
}
ptr = cfg->config_ini_list;
while (ptr) {
if (strcmp(ptr->ini_name, ini->ini_name) == 0) {
break;
}
prev = ptr;
ptr = ptr->ini_next;
}
if (!ptr) {
return;
}
if (prev) {
prev->ini_next = ptr->ini_next;
} else {
cfg->config_ini_list = ptr->ini_next;
}
ptr->ini_next = NULL; /* Only free this initiator */
cfg->config_ini_count--;
it_ini_free(ptr);
}
/*
* Function: it_ini_free()
*
* Deallocates resources of an it_ini_t structure. If ini->next is
* not NULL, frees all members of the list.
*/
void
it_ini_free(it_ini_t *ini)
{
it_ini_free_cmn(ini);
}
/*
* Goes through the target property list and validates
* each entry. If errs is non-NULL, will return explicit errors
* for each property that fails validation.
*/
static int
it_validate_tgtprops(nvlist_t *nvl, nvlist_t *errs)
{
int errcnt = 0;
nvpair_t *nvp = NULL;
data_type_t nvtype;
char *name;
char *val;
char *auth = NULL;
if (!nvl) {
return (0);
}
while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
name = nvpair_name(nvp);
nvtype = nvpair_type(nvp);
if (!name) {
continue;
}
val = NULL;
if (strcmp(name, PROP_TARGET_CHAP_USER) == 0) {
if (nvtype != DATA_TYPE_STRING) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
} else if (strcmp(name, PROP_TARGET_CHAP_SECRET) == 0) {
/*
* must be between 12 and 255 chars in cleartext.
* will be base64 encoded when it's set.
*/
if (nvtype == DATA_TYPE_STRING) {
(void) nvpair_value_string(nvp, &val);
}
if (!val) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
} else if (strcmp(name, PROP_ALIAS) == 0) {
if (nvtype != DATA_TYPE_STRING) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
} else if (strcmp(name, PROP_AUTH) == 0) {
if (nvtype == DATA_TYPE_STRING) {
val = NULL;
(void) nvpair_value_string(nvp, &val);
}
if (!val) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
if ((strcmp(val, PA_AUTH_NONE) != 0) &&
(strcmp(val, PA_AUTH_CHAP) != 0) &&
(strcmp(val, PA_AUTH_RADIUS) != 0) &&
(strcmp(val, "default") != 0)) {
PROPERR(errs, val, gettext(
"must be none, chap, radius or default"));
errcnt++;
}
auth = val;
continue;
} else if (strcmp(name, PROP_OLD_TARGET_NAME) == 0) {
continue;
} else {
/* unrecognized property */
PROPERR(errs, name, gettext("unrecognized property"));
errcnt++;
}
}
if (errcnt) {
return (EINVAL);
}
/* if auth is being set to default, remove from this nvlist */
if (auth && (strcmp(auth, "default") == 0)) {
(void) nvlist_remove_all(nvl, PROP_AUTH);
}
return (0);
}
/*
* Goes through the config property list and validates
* each entry. If errs is non-NULL, will return explicit errors
* for each property that fails validation.
*/
static int
it_validate_configprops(nvlist_t *nvl, nvlist_t *errs)
{
int errcnt = 0;
nvpair_t *nvp = NULL;
data_type_t nvtype;
char *name;
char *val;
struct sockaddr_storage sa;
boolean_t update_rad_server = B_FALSE;
char *rad_server;
char *auth = NULL;
if (!nvl) {
return (0);
}
while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
name = nvpair_name(nvp);
nvtype = nvpair_type(nvp);
if (!name) {
continue;
}
val = NULL;
/* prefetch string value as we mostly need it */
if (nvtype == DATA_TYPE_STRING) {
(void) nvpair_value_string(nvp, &val);
}
if (strcmp(name, PROP_ALIAS) == 0) {
if (!val) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
}
} else if (strcmp(name, PROP_AUTH) == 0) {
if (!val) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
if ((strcmp(val, PA_AUTH_NONE) != 0) &&
(strcmp(val, PA_AUTH_CHAP) != 0) &&
(strcmp(val, PA_AUTH_RADIUS) != 0)) {
PROPERR(errs, PROP_AUTH,
gettext("must be none, chap or radius"));
errcnt++;
}
auth = val;
} else if (strcmp(name, PROP_ISNS_ENABLED) == 0) {
if (nvtype != DATA_TYPE_BOOLEAN_VALUE) {
PROPERR(errs, name,
gettext("must be a boolean value"));
errcnt++;
}
} else if (strcmp(name, PROP_ISNS_SERVER) == 0) {
char **arr = NULL;
uint32_t acount = 0;
(void) nvlist_lookup_string_array(nvl, name,
&arr, &acount);
while (acount > 0) {
if (strcasecmp(arr[acount - 1], "none") == 0) {
break;
}
if ((it_common_convert_sa(arr[acount - 1],
&sa, 0)) == NULL) {
PROPERR(errs, arr[acount - 1],
gettext("invalid address"));
errcnt++;
}
acount--;
}
} else if (strcmp(name, PROP_RADIUS_SECRET) == 0) {
if (!val) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
} else if (strcmp(name, PROP_RADIUS_SERVER) == 0) {
struct sockaddr_storage sa;
if (!val) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
if ((it_common_convert_sa(val, &sa,
DEFAULT_RADIUS_PORT)) == NULL) {
PROPERR(errs, name,
gettext("invalid address"));
errcnt++;
} else {
/*
* rewrite this property to ensure port
* number is added.
*/
if (sockaddr_to_str(&sa, &rad_server) == 0) {
update_rad_server = B_TRUE;
}
}
} else {
/* unrecognized property */
PROPERR(errs, name, gettext("unrecognized property"));
errcnt++;
}
}
/*
* If we successfully reformatted the radius server to add the port
* number then update the nvlist
*/
if (update_rad_server) {
(void) nvlist_add_string(nvl, name, rad_server);
}
/*
* if auth = radius, ensure radius server & secret are set.
*/
if (auth) {
if (strcmp(auth, PA_AUTH_RADIUS) == 0) {
/* need server & secret for radius */
if (!nvlist_exists(nvl, PROP_RADIUS_SERVER)) {
PROPERR(errs, PROP_RADIUS_SERVER,
gettext("missing required property"));
errcnt++;
}
if (!nvlist_exists(nvl, PROP_RADIUS_SECRET)) {
PROPERR(errs, PROP_RADIUS_SECRET,
gettext("missing required property"));
errcnt++;
}
}
}
if (errcnt) {
return (EINVAL);
}
return (0);
}
/*
* Goes through the ini property list and validates
* each entry. If errs is non-NULL, will return explicit errors
* for each property that fails validation.
*/
static int
it_validate_iniprops(nvlist_t *nvl, nvlist_t *errs)
{
int errcnt = 0;
nvpair_t *nvp = NULL;
data_type_t nvtype;
char *name;
char *val;
if (!nvl) {
return (0);
}
while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
name = nvpair_name(nvp);
nvtype = nvpair_type(nvp);
if (!name) {
continue;
}
if (strcmp(name, PROP_CHAP_USER) == 0) {
if (nvtype != DATA_TYPE_STRING) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
} else if (strcmp(name, PROP_CHAP_SECRET) == 0) {
/*
* must be between 12 and 255 chars in cleartext.
* will be base64 encoded when it's set.
*/
if (nvtype == DATA_TYPE_STRING) {
val = NULL;
(void) nvpair_value_string(nvp, &val);
}
if (!val) {
PROPERR(errs, name,
gettext("must be a string value"));
errcnt++;
continue;
}
} else {
/* unrecognized property */
PROPERR(errs, name, gettext("unrecognized property"));
errcnt++;
}
}
if (errcnt) {
return (EINVAL);
}
return (0);
}
static int
it_iqn_generate(char *iqn_buf, int iqn_buf_len, char *opt_iqn_suffix)
{
int ret;
uuid_t id;
char id_str[UUID_PRINTABLE_STRING_LENGTH];
uuid_generate_random(id);
uuid_unparse(id, id_str);
if (opt_iqn_suffix) {
ret = snprintf(iqn_buf, iqn_buf_len, "iqn.1986-03.com.sun:"
"%02d:%s.%s", TARGET_NAME_VERS, id_str, opt_iqn_suffix);
} else {
ret = snprintf(iqn_buf, iqn_buf_len, "iqn.1986-03.com.sun:"
"%02d:%s", TARGET_NAME_VERS, id_str);
}
if (ret > iqn_buf_len) {
return (1);
}
return (0);
}
static int
it_val_pass(char *name, char *val, nvlist_t *e)
{
size_t sz;
if (!name || !val) {
return (EINVAL);
}
/*
* must be at least 12 chars and less than 256 chars cleartext.
*/
sz = strlen(val);
/*
* Since we will be automatically encoding secrets we don't really
* need the prefix anymore.
*/
if (sz < 12) {
PROPERR(e, name, gettext("secret too short"));
} else if (sz > 255) {
PROPERR(e, name, gettext("secret too long"));
} else {
/* all is well */
return (0);
}
return (1);
}
/*
* Function: validate_iscsi_name()
*
* Ensures the passed-in string is a valid IQN or EUI iSCSI name
*
*/
boolean_t
validate_iscsi_name(char *in_name)
{
size_t in_len;
int i;
char month[3];
if (in_name == NULL) {
return (B_FALSE);
}
in_len = strlen(in_name);
if (in_len < 12) {
return (B_FALSE);
}
if (strncasecmp(in_name, "iqn.", 4) == 0) {
/*
* IQN names are iqn.yyyy-mm.<xxx>
*/
if ((!isdigit(in_name[4])) ||
(!isdigit(in_name[5])) ||
(!isdigit(in_name[6])) ||
(!isdigit(in_name[7])) ||
(in_name[8] != '-') ||
(!isdigit(in_name[9])) ||
(!isdigit(in_name[10])) ||
(in_name[11] != '.')) {
return (B_FALSE);
}
(void) strncpy(month, &(in_name[9]), 2);
month[2] = '\0';
i = atoi(month);
if ((i < 0) || (i > 12)) {
return (B_FALSE);
}
/* Finally, validate the overall length, in wide chars */
in_len = mbstowcs(NULL, in_name, 0);
if (in_len > ISCSI_NAME_LEN_MAX) {
return (B_FALSE);
}
} else if (strncasecmp(in_name, "eui.", 4) == 0) {
/*
* EUI names are "eui." + 16 hex chars
*/
if (in_len != 20) {
return (B_FALSE);
}
for (i = 4; i < in_len; i++) {
if (!isxdigit(in_name[i])) {
return (B_FALSE);
}
}
} else {
return (B_FALSE);
}
return (B_TRUE);
}