2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <limits.h>
2N/A#include <ctype.h>
2N/A#include <fcntl.h>
2N/A#include <errno.h>
2N/A#include <unistd.h>
2N/A#include <strings.h>
2N/A#include <libintl.h>
2N/A#include <libscf.h>
2N/A#include <libnvpair.h>
2N/A
2N/A#include <libstmf.h>
2N/A#include <libsrpt.h>
2N/A
2N/A#include "srpt_common.h"
2N/A
2N/A#define SRPT_PROV_NAME "srpt"
2N/A
2N/A/*
2N/A * Function: srpt_GetConfig()
2N/A *
2N/A * Parameters:
2N/A * cfg Current SRPT configuration in nvlist form
2N/A * token Configuration generation number. Use this token
2N/A * if updating the configuration with srpt_SetConfig.
2N/A *
2N/A * Return Values:
2N/A * 0 Success
2N/A * ENOMEM Could not allocate resources
2N/A * EINVAL Invalid parameter
2N/A */
2N/Aint
2N/Asrpt_GetConfig(nvlist_t **cfg, uint64_t *token)
2N/A{
2N/A int ret = 0;
2N/A nvlist_t *cfg_nv = NULL;
2N/A uint64_t stmf_token = 0;
2N/A nvlist_t *hcanv = NULL;
2N/A
2N/A if (!cfg) {
2N/A return (EINVAL);
2N/A }
2N/A
2N/A *cfg = NULL;
2N/A
2N/A ret = stmfGetProviderDataProt(SRPT_PROV_NAME, &cfg_nv,
2N/A STMF_PORT_PROVIDER_TYPE, &stmf_token);
2N/A
2N/A if (ret == STMF_STATUS_SUCCESS) {
2N/A ret = 0;
2N/A } else if (ret == STMF_ERROR_NOT_FOUND) {
2N/A /* Not initialized yet */
2N/A ret = nvlist_alloc(&cfg_nv, NV_UNIQUE_NAME, 0);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A /* create the HCA list */
2N/A ret = nvlist_alloc(&hcanv, NV_UNIQUE_NAME, 0);
2N/A if (ret == 0) {
2N/A ret = nvlist_add_nvlist(cfg_nv, SRPT_PROP_HCALIST,
2N/A hcanv);
2N/A if (ret != 0) {
2N/A nvlist_free(hcanv);
2N/A }
2N/A }
2N/A if (ret != 0) {
2N/A nvlist_free(cfg_nv);
2N/A cfg_nv = NULL;
2N/A }
2N/A } else if (ret == STMF_ERROR_NOMEM) {
2N/A ret = ENOMEM;
2N/A } else {
2N/A ret = EINVAL;
2N/A }
2N/A
2N/A *cfg = cfg_nv;
2N/A *token = stmf_token;
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Function: srpt_SetConfig()
2N/A *
2N/A * Parameters:
2N/A * cfg SRPT configuration in nvlist form
2N/A * token Configuration generation number from srpt_GetConfig.
2N/A * Use this token to ensure the configuration hasn't been
2N/A * updated by another user since the time it was fetched.
2N/A *
2N/A * Return Values:
2N/A * 0 Success
2N/A * ENOMEM Could not allocate resources
2N/A * EINVAL Invalid parameter
2N/A * ECANCELED Configuration updated by another user
2N/A */
2N/Aint
2N/Asrpt_SetConfig(nvlist_t *cfg, uint64_t token)
2N/A{
2N/A int ret = 0;
2N/A
2N/A ret = stmfSetProviderDataProt(SRPT_PROV_NAME, cfg,
2N/A STMF_PORT_PROVIDER_TYPE, &token);
2N/A
2N/A if (ret == STMF_STATUS_SUCCESS) {
2N/A ret = 0;
2N/A } else if (ret == STMF_ERROR_NOMEM) {
2N/A ret = ENOMEM;
2N/A } else if (ret == STMF_ERROR_PROV_DATA_STALE) {
2N/A ret = ECANCELED; /* could be a better errno */
2N/A } else {
2N/A ret = EINVAL;
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Function: srpt_GetDefaultState()
2N/A *
2N/A * Parameters:
2N/A * enabled If B_TRUE, indicates that targets will be created for all
2N/A * discovered HCAs that have not been specifically disabled.
2N/A * If B_FALSE, targets will not be created unless the HCA has
2N/A * been specifically enabled. See also srpt_SetDefaultState().
2N/A *
2N/A * Return Values:
2N/A * 0 Success
2N/A * ENOMEM Could not allocate resources
2N/A * EINVAL Invalid parameter
2N/A */
2N/Aint
2N/Asrpt_GetDefaultState(boolean_t *enabled)
2N/A{
2N/A int ret;
2N/A nvlist_t *cfgnv;
2N/A uint64_t token;
2N/A boolean_t val = B_TRUE;
2N/A
2N/A if (enabled == NULL) {
2N/A return (EINVAL);
2N/A }
2N/A
2N/A ret = srpt_GetConfig(&cfgnv, &token);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A
2N/A if (cfgnv != NULL) {
2N/A ret = nvlist_lookup_boolean_value(cfgnv,
2N/A SRPT_PROP_DEFAULT_ENABLED, &val);
2N/A
2N/A if (ret == ENOENT) {
2N/A ret = 0;
2N/A }
2N/A }
2N/A
2N/A *enabled = val;
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Function: srpt_SetDefaultState()
2N/A *
2N/A * Parameters:
2N/A * enabled If B_TRUE, indicates that targets will be created for all
2N/A * discovered HCAs that have not been specifically disabled.
2N/A * If B_FALSE, targets will not be created unless the HCA has
2N/A * been specifically enabled. See also srpt_SetDefaultState().
2N/A *
2N/A * Return Values:
2N/A * 0 Success
2N/A * ENOMEM Could not allocate resources
2N/A * EINVAL Invalid parameter
2N/A */
2N/Aint
2N/Asrpt_SetDefaultState(boolean_t enabled)
2N/A{
2N/A int ret;
2N/A nvlist_t *cfgnv;
2N/A uint64_t token;
2N/A
2N/A ret = srpt_GetConfig(&cfgnv, &token);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A
2N/A if (cfgnv == NULL) {
2N/A ret = nvlist_alloc(&cfgnv, NV_UNIQUE_NAME, 0);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A }
2N/A
2N/A ret = nvlist_add_boolean_value(cfgnv, SRPT_PROP_DEFAULT_ENABLED,
2N/A enabled);
2N/A
2N/A if (ret == 0) {
2N/A ret = srpt_SetConfig(cfgnv, token);
2N/A }
2N/A
2N/A nvlist_free(cfgnv);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Function: srpt_SetTargetState()
2N/A *
2N/A * Parameters:
2N/A * hca_guid HCA GUID. See description of srpt_NormalizeGuid
2N/A * enabled If B_TRUE, indicates that a target will be created for
2N/A * this HCA when the SRPT SMF service is enabled. If B_FALSE,
2N/A * a target will not be created
2N/A *
2N/A * Return Values:
2N/A * 0 Success
2N/A * ENOMEM Could not allocate resources
2N/A * EINVAL Invalid parameter
2N/A */
2N/Aint
2N/Asrpt_SetTargetState(char *hca_guid, boolean_t enabled)
2N/A{
2N/A int ret;
2N/A nvlist_t *cfgnv;
2N/A uint64_t token;
2N/A nvlist_t *hcalist;
2N/A nvlist_t *hcanv;
2N/A char guid[32];
2N/A uint64_t hcaguid;
2N/A
2N/A if (hca_guid == NULL) {
2N/A return (EINVAL);
2N/A }
2N/A
2N/A ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), &hcaguid);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A
2N/A ret = srpt_GetConfig(&cfgnv, &token);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A
2N/A /* get the list of HCAs */
2N/A ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
2N/A if (ret != 0) {
2N/A nvlist_free(cfgnv);
2N/A return (ret);
2N/A }
2N/A
2N/A ret = nvlist_lookup_nvlist(hcalist, guid, &hcanv);
2N/A if (ret == ENOENT) {
2N/A /* no entry yet */
2N/A ret = nvlist_alloc(&hcanv, NV_UNIQUE_NAME, 0);
2N/A if (ret == 0) {
2N/A ret = nvlist_add_uint64(hcanv, SRPT_PROP_GUID, hcaguid);
2N/A }
2N/A }
2N/A
2N/A if (ret == 0) {
2N/A ret = nvlist_add_boolean_value(hcanv, SRPT_PROP_ENABLED,
2N/A enabled);
2N/A }
2N/A
2N/A if (ret == 0) {
2N/A ret = nvlist_add_nvlist(hcalist, guid, hcanv);
2N/A }
2N/A
2N/A if (ret == 0) {
2N/A ret = srpt_SetConfig(cfgnv, token);
2N/A }
2N/A
2N/A nvlist_free(cfgnv);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * Function: srpt_GetTargetState()
2N/A *
2N/A * Parameters:
2N/A * hca_guid HCA GUID. See description of srpt_NormalizeGuid
2N/A * enabled If B_TRUE, indicates that a target will be created for
2N/A * this HCA when the SRPT SMF service is enabled. If B_FALSE,
2N/A * a target will not be created
2N/A *
2N/A * Return Values:
2N/A * 0 Success
2N/A * ENOMEM Could not allocate resources
2N/A * EINVAL Invalid parameter
2N/A */
2N/Aint
2N/Asrpt_GetTargetState(char *hca_guid, boolean_t *enabled)
2N/A{
2N/A int ret;
2N/A nvlist_t *cfgnv;
2N/A uint64_t token;
2N/A nvlist_t *hcalist;
2N/A nvlist_t *hcanv;
2N/A boolean_t defaultState = B_TRUE;
2N/A char guid[32];
2N/A
2N/A if (hca_guid == NULL) {
2N/A return (EINVAL);
2N/A }
2N/A
2N/A ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), NULL);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A
2N/A ret = srpt_GetConfig(&cfgnv, &token);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A
2N/A /* get the list of HCAs */
2N/A ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
2N/A if (ret != 0) {
2N/A nvlist_free(cfgnv);
2N/A return (ret);
2N/A }
2N/A
2N/A /*
2N/A * Find the default, for the likely case that this HCA isn't
2N/A * explicitly set.
2N/A */
2N/A (void) nvlist_lookup_boolean_value(cfgnv, SRPT_PROP_DEFAULT_ENABLED,
2N/A &defaultState);
2N/A
2N/A ret = nvlist_lookup_nvlist(hcalist, guid, &hcanv);
2N/A if (ret == 0) {
2N/A ret = nvlist_lookup_boolean_value(hcanv, SRPT_PROP_ENABLED,
2N/A enabled);
2N/A }
2N/A
2N/A if (ret == ENOENT) {
2N/A /* not explicitly set, use the default */
2N/A *enabled = defaultState;
2N/A ret = 0;
2N/A }
2N/A
2N/A nvlist_free(cfgnv);
2N/A
2N/A return (ret);
2N/A
2N/A}
2N/A
2N/A/*
2N/A * Function: srpt_ResetTarget()
2N/A *
2N/A * Clears the HCA-specific configuration. Target creation will revert to
2N/A * the default.
2N/A *
2N/A * Parameters:
2N/A * hca_guid HCA GUID. See description of srpt_NormalizeGuid
2N/A *
2N/A * Return Values:
2N/A * 0 Success
2N/A * ENOMEM Could not allocate resources
2N/A * EINVAL Invalid parameter
2N/A */
2N/Aint
2N/Asrpt_ResetTarget(char *hca_guid)
2N/A{
2N/A int ret;
2N/A nvlist_t *cfgnv;
2N/A nvlist_t *hcalist;
2N/A uint64_t token;
2N/A char guid[32];
2N/A
2N/A if (hca_guid == NULL) {
2N/A return (EINVAL);
2N/A }
2N/A
2N/A ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), NULL);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A
2N/A ret = srpt_GetConfig(&cfgnv, &token);
2N/A if (ret != 0) {
2N/A return (ret);
2N/A }
2N/A
2N/A /* get the list of HCAs */
2N/A ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
2N/A if (ret != 0) {
2N/A nvlist_free(cfgnv);
2N/A return (ret);
2N/A }
2N/A
2N/A /* don't set config if we don't actually change anything */
2N/A if (nvlist_exists(hcalist, guid)) {
2N/A (void) nvlist_remove_all(hcalist, guid);
2N/A
2N/A if (ret == 0) {
2N/A ret = srpt_SetConfig(cfgnv, token);
2N/A }
2N/A }
2N/A
2N/A nvlist_free(cfgnv);
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/A/*
2N/A * srpt_NormalizeGuid()
2N/A *
2N/A * Parameters:
2N/A * in HCA GUID. Must be in one of the following forms:
2N/A * 3BA000100CD18 - base hex form
2N/A * 0003BA000100CD18 - base hex form with leading zeroes
2N/A * hca:3BA000100CD18 - form from cfgadm and/or /dev/cfg
2N/A * eui.0003BA000100CD18 - EUI form
2N/A *
2N/A * buf Buffer to hold normalized guid string. Must be at least
2N/A * 17 chars long.
2N/A * buflen Length of provided buffer
2N/A * int_guid Optional. If not NULL, the integer form of the GUID will also
2N/A * be returned.
2N/A * Return Values:
2N/A * 0 Success
2N/A * EINVAL Invalid HCA GUID or invalid parameter.
2N/A */
2N/Aint
2N/Asrpt_NormalizeGuid(char *in, char *buf, size_t buflen, uint64_t *int_guid)
2N/A{
2N/A uint64_t guid;
2N/A char *bufp = in;
2N/A char *end = NULL;
2N/A
2N/A if ((in == NULL) || (buf == NULL)) {
2N/A return (EINVAL);
2N/A }
2N/A
2N/A if (strncasecmp(bufp, "eui.", 4) == 0) {
2N/A /* EUI form */
2N/A bufp += 4;
2N/A } else if (strncasecmp(bufp, "hca:", 4) == 0) {
2N/A /* cfgadm and /dev/hca form */
2N/A bufp += 4;
2N/A }
2N/A
2N/A /*
2N/A * strtoull() does not return EINVAL as documented. Lucky
2N/A * for us, neither 0 nor ULLONG_MAX will be valid. Trap on
2N/A * those and fail.
2N/A */
2N/A guid = strtoull(bufp, &end, 16);
2N/A if ((guid == 0) || (guid == ULLONG_MAX) ||
2N/A ((end != NULL) && (strlen(end) > 0))) {
2N/A return (EINVAL);
2N/A }
2N/A
2N/A#if 0
2N/A (void) snprintf(buf, buflen, "%llX", guid);
2N/A#endif
2N/A SRPT_FORMAT_HCAKEY(buf, buflen, guid);
2N/A
2N/A if (int_guid) {
2N/A *int_guid = guid;
2N/A }
2N/A
2N/A return (0);
2N/A}