dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libsrpt / common / libsrpt.c
blob5a89f88568eabbcadeb3a2aa2c00e00f2f3cb85f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <limits.h>
28 #include <ctype.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <strings.h>
33 #include <libintl.h>
34 #include <libscf.h>
35 #include <libnvpair.h>
37 #include <libstmf.h>
38 #include <libsrpt.h>
40 #include "srpt_common.h"
42 #define SRPT_PROV_NAME "srpt"
45 * Function: srpt_GetConfig()
47 * Parameters:
48 * cfg Current SRPT configuration in nvlist form
49 * token Configuration generation number. Use this token
50 * if updating the configuration with srpt_SetConfig.
52 * Return Values:
53 * 0 Success
54 * ENOMEM Could not allocate resources
55 * EINVAL Invalid parameter
57 int
58 srpt_GetConfig(nvlist_t **cfg, uint64_t *token)
60 int ret = 0;
61 nvlist_t *cfg_nv = NULL;
62 uint64_t stmf_token = 0;
63 nvlist_t *hcanv = NULL;
65 if (!cfg) {
66 return (EINVAL);
69 *cfg = NULL;
71 ret = stmfGetProviderDataProt(SRPT_PROV_NAME, &cfg_nv,
72 STMF_PORT_PROVIDER_TYPE, &stmf_token);
74 if (ret == STMF_STATUS_SUCCESS) {
75 ret = 0;
76 } else if (ret == STMF_ERROR_NOT_FOUND) {
77 /* Not initialized yet */
78 ret = nvlist_alloc(&cfg_nv, NV_UNIQUE_NAME, 0);
79 if (ret != 0) {
80 return (ret);
82 /* create the HCA list */
83 ret = nvlist_alloc(&hcanv, NV_UNIQUE_NAME, 0);
84 if (ret == 0) {
85 ret = nvlist_add_nvlist(cfg_nv, SRPT_PROP_HCALIST,
86 hcanv);
87 if (ret != 0) {
88 nvlist_free(hcanv);
91 if (ret != 0) {
92 nvlist_free(cfg_nv);
93 cfg_nv = NULL;
95 } else if (ret == STMF_ERROR_NOMEM) {
96 ret = ENOMEM;
97 } else {
98 ret = EINVAL;
101 *cfg = cfg_nv;
102 *token = stmf_token;
104 return (ret);
108 * Function: srpt_SetConfig()
110 * Parameters:
111 * cfg SRPT configuration in nvlist form
112 * token Configuration generation number from srpt_GetConfig.
113 * Use this token to ensure the configuration hasn't been
114 * updated by another user since the time it was fetched.
116 * Return Values:
117 * 0 Success
118 * ENOMEM Could not allocate resources
119 * EINVAL Invalid parameter
120 * ECANCELED Configuration updated by another user
123 srpt_SetConfig(nvlist_t *cfg, uint64_t token)
125 int ret = 0;
127 ret = stmfSetProviderDataProt(SRPT_PROV_NAME, cfg,
128 STMF_PORT_PROVIDER_TYPE, &token);
130 if (ret == STMF_STATUS_SUCCESS) {
131 ret = 0;
132 } else if (ret == STMF_ERROR_NOMEM) {
133 ret = ENOMEM;
134 } else if (ret == STMF_ERROR_PROV_DATA_STALE) {
135 ret = ECANCELED; /* could be a better errno */
136 } else {
137 ret = EINVAL;
140 return (ret);
144 * Function: srpt_GetDefaultState()
146 * Parameters:
147 * enabled If B_TRUE, indicates that targets will be created for all
148 * discovered HCAs that have not been specifically disabled.
149 * If B_FALSE, targets will not be created unless the HCA has
150 * been specifically enabled. See also srpt_SetDefaultState().
152 * Return Values:
153 * 0 Success
154 * ENOMEM Could not allocate resources
155 * EINVAL Invalid parameter
158 srpt_GetDefaultState(boolean_t *enabled)
160 int ret;
161 nvlist_t *cfgnv;
162 uint64_t token;
163 boolean_t val = B_TRUE;
165 if (enabled == NULL) {
166 return (EINVAL);
169 ret = srpt_GetConfig(&cfgnv, &token);
170 if (ret != 0) {
171 return (ret);
174 if (cfgnv != NULL) {
175 ret = nvlist_lookup_boolean_value(cfgnv,
176 SRPT_PROP_DEFAULT_ENABLED, &val);
178 if (ret == ENOENT) {
179 ret = 0;
183 *enabled = val;
184 return (ret);
188 * Function: srpt_SetDefaultState()
190 * Parameters:
191 * enabled If B_TRUE, indicates that targets will be created for all
192 * discovered HCAs that have not been specifically disabled.
193 * If B_FALSE, targets will not be created unless the HCA has
194 * been specifically enabled. See also srpt_SetDefaultState().
196 * Return Values:
197 * 0 Success
198 * ENOMEM Could not allocate resources
199 * EINVAL Invalid parameter
202 srpt_SetDefaultState(boolean_t enabled)
204 int ret;
205 nvlist_t *cfgnv;
206 uint64_t token;
208 ret = srpt_GetConfig(&cfgnv, &token);
209 if (ret != 0) {
210 return (ret);
213 if (cfgnv == NULL) {
214 ret = nvlist_alloc(&cfgnv, NV_UNIQUE_NAME, 0);
215 if (ret != 0) {
216 return (ret);
220 ret = nvlist_add_boolean_value(cfgnv, SRPT_PROP_DEFAULT_ENABLED,
221 enabled);
223 if (ret == 0) {
224 ret = srpt_SetConfig(cfgnv, token);
227 nvlist_free(cfgnv);
229 return (ret);
233 * Function: srpt_SetTargetState()
235 * Parameters:
236 * hca_guid HCA GUID. See description of srpt_NormalizeGuid
237 * enabled If B_TRUE, indicates that a target will be created for
238 * this HCA when the SRPT SMF service is enabled. If B_FALSE,
239 * a target will not be created
241 * Return Values:
242 * 0 Success
243 * ENOMEM Could not allocate resources
244 * EINVAL Invalid parameter
247 srpt_SetTargetState(char *hca_guid, boolean_t enabled)
249 int ret;
250 nvlist_t *cfgnv;
251 uint64_t token;
252 nvlist_t *hcalist;
253 nvlist_t *hcanv;
254 char guid[32];
255 uint64_t hcaguid;
257 if (hca_guid == NULL) {
258 return (EINVAL);
261 ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), &hcaguid);
262 if (ret != 0) {
263 return (ret);
266 ret = srpt_GetConfig(&cfgnv, &token);
267 if (ret != 0) {
268 return (ret);
271 /* get the list of HCAs */
272 ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
273 if (ret != 0) {
274 nvlist_free(cfgnv);
275 return (ret);
278 ret = nvlist_lookup_nvlist(hcalist, guid, &hcanv);
279 if (ret == ENOENT) {
280 /* no entry yet */
281 ret = nvlist_alloc(&hcanv, NV_UNIQUE_NAME, 0);
282 if (ret == 0) {
283 ret = nvlist_add_uint64(hcanv, SRPT_PROP_GUID, hcaguid);
287 if (ret == 0) {
288 ret = nvlist_add_boolean_value(hcanv, SRPT_PROP_ENABLED,
289 enabled);
292 if (ret == 0) {
293 ret = nvlist_add_nvlist(hcalist, guid, hcanv);
296 if (ret == 0) {
297 ret = srpt_SetConfig(cfgnv, token);
300 nvlist_free(cfgnv);
302 return (ret);
306 * Function: srpt_GetTargetState()
308 * Parameters:
309 * hca_guid HCA GUID. See description of srpt_NormalizeGuid
310 * enabled If B_TRUE, indicates that a target will be created for
311 * this HCA when the SRPT SMF service is enabled. If B_FALSE,
312 * a target will not be created
314 * Return Values:
315 * 0 Success
316 * ENOMEM Could not allocate resources
317 * EINVAL Invalid parameter
320 srpt_GetTargetState(char *hca_guid, boolean_t *enabled)
322 int ret;
323 nvlist_t *cfgnv;
324 uint64_t token;
325 nvlist_t *hcalist;
326 nvlist_t *hcanv;
327 boolean_t defaultState = B_TRUE;
328 char guid[32];
330 if (hca_guid == NULL) {
331 return (EINVAL);
334 ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), NULL);
335 if (ret != 0) {
336 return (ret);
339 ret = srpt_GetConfig(&cfgnv, &token);
340 if (ret != 0) {
341 return (ret);
344 /* get the list of HCAs */
345 ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
346 if (ret != 0) {
347 nvlist_free(cfgnv);
348 return (ret);
352 * Find the default, for the likely case that this HCA isn't
353 * explicitly set.
355 (void) nvlist_lookup_boolean_value(cfgnv, SRPT_PROP_DEFAULT_ENABLED,
356 &defaultState);
358 ret = nvlist_lookup_nvlist(hcalist, guid, &hcanv);
359 if (ret == 0) {
360 ret = nvlist_lookup_boolean_value(hcanv, SRPT_PROP_ENABLED,
361 enabled);
364 if (ret == ENOENT) {
365 /* not explicitly set, use the default */
366 *enabled = defaultState;
367 ret = 0;
370 nvlist_free(cfgnv);
372 return (ret);
377 * Function: srpt_ResetTarget()
379 * Clears the HCA-specific configuration. Target creation will revert to
380 * the default.
382 * Parameters:
383 * hca_guid HCA GUID. See description of srpt_NormalizeGuid
385 * Return Values:
386 * 0 Success
387 * ENOMEM Could not allocate resources
388 * EINVAL Invalid parameter
391 srpt_ResetTarget(char *hca_guid)
393 int ret;
394 nvlist_t *cfgnv;
395 nvlist_t *hcalist;
396 uint64_t token;
397 char guid[32];
399 if (hca_guid == NULL) {
400 return (EINVAL);
403 ret = srpt_NormalizeGuid(hca_guid, guid, sizeof (guid), NULL);
404 if (ret != 0) {
405 return (ret);
408 ret = srpt_GetConfig(&cfgnv, &token);
409 if (ret != 0) {
410 return (ret);
413 /* get the list of HCAs */
414 ret = nvlist_lookup_nvlist(cfgnv, SRPT_PROP_HCALIST, &hcalist);
415 if (ret != 0) {
416 nvlist_free(cfgnv);
417 return (ret);
420 /* don't set config if we don't actually change anything */
421 if (nvlist_exists(hcalist, guid)) {
422 (void) nvlist_remove_all(hcalist, guid);
424 if (ret == 0) {
425 ret = srpt_SetConfig(cfgnv, token);
429 nvlist_free(cfgnv);
431 return (ret);
435 * srpt_NormalizeGuid()
437 * Parameters:
438 * in HCA GUID. Must be in one of the following forms:
439 * 3BA000100CD18 - base hex form
440 * 0003BA000100CD18 - base hex form with leading zeroes
441 * hca:3BA000100CD18 - form from cfgadm and/or /dev/cfg
442 * eui.0003BA000100CD18 - EUI form
444 * buf Buffer to hold normalized guid string. Must be at least
445 * 17 chars long.
446 * buflen Length of provided buffer
447 * int_guid Optional. If not NULL, the integer form of the GUID will also
448 * be returned.
449 * Return Values:
450 * 0 Success
451 * EINVAL Invalid HCA GUID or invalid parameter.
454 srpt_NormalizeGuid(char *in, char *buf, size_t buflen, uint64_t *int_guid)
456 uint64_t guid;
457 char *bufp = in;
458 char *end = NULL;
460 if ((in == NULL) || (buf == NULL)) {
461 return (EINVAL);
464 if (strncasecmp(bufp, "eui.", 4) == 0) {
465 /* EUI form */
466 bufp += 4;
467 } else if (strncasecmp(bufp, "hca:", 4) == 0) {
468 /* cfgadm and /dev/hca form */
469 bufp += 4;
473 * strtoull() does not return EINVAL as documented. Lucky
474 * for us, neither 0 nor ULLONG_MAX will be valid. Trap on
475 * those and fail.
477 guid = strtoull(bufp, &end, 16);
478 if ((guid == 0) || (guid == ULLONG_MAX) ||
479 ((end != NULL) && (strlen(end) > 0))) {
480 return (EINVAL);
483 #if 0
484 (void) snprintf(buf, buflen, "%llX", guid);
485 #endif
486 SRPT_FORMAT_HCAKEY(buf, buflen, guid);
488 if (int_guid) {
489 *int_guid = guid;
492 return (0);