conerr_t smfu_get_property(char *fmri, char *pgname, char *propname, char *value, size_t n) { conerr_t err = ce_ok; scf_handle_t *scfhandle = handle_create(); scf_service_t *service = scf_service_create(scfhandle); scf_instance_t *instance = scf_instance_create(scfhandle); scf_propertygroup_t *pg = scf_pg_create(scfhandle); scf_property_t *prop = scf_property_create(scfhandle); scf_iter_t *iter = scf_iter_create(scfhandle); scf_value_t *val = scf_value_create(scfhandle); if (scfhandle == NULL || service == NULL || instance == NULL || pg == NULL || prop == NULL || iter == NULL || val == NULL) { err = ce_nomem; goto out; } if (scf_handle_decode_fmri(scfhandle, fmri, NULL, service, instance, NULL, NULL, 0) != SCF_SUCCESS) { rad_log(RL_ERROR, "couldn't decode '%s': %s\n", fmri, scf_strerror(scf_error())); err = maperr(scf_error()); goto out; } if (scf_instance_get_pg(instance, pgname, pg) != 0 || scf_pg_get_property(pg, propname, prop) != 0 || scf_iter_property_values(iter, prop) != 0) { rad_log(RL_ERROR, "couldn't get property: '%s/%s/%s': %s\n", fmri, pgname, propname, scf_strerror(scf_error())); err = maperr(scf_error()); goto out; } if (scf_iter_next_value(iter, val) > 0 && scf_value_get_as_string(val, value, n) == -1) { rad_log(RL_ERROR, "couldn't get property value: '%s/%s/%s': %s\n", fmri, pgname, propname, scf_strerror(scf_error())); err = maperr(scf_error()); goto out; } out: scf_value_destroy(val); scf_property_destroy(prop); scf_pg_destroy(pg); scf_iter_destroy(iter); scf_instance_destroy(instance); scf_service_destroy(service); scf_handle_destroy(scfhandle); return (err); }
static void print_value(scf_value_t *val) { char *buf, *qbuf; ssize_t bufsz, r; bufsz = scf_value_get_as_string(val, NULL, 0) + 1; if (bufsz - 1 < 0) scfdie(); buf = safe_malloc(bufsz); r = scf_value_get_as_string(val, buf, bufsz); assert(r + 1 == bufsz); qbuf = quote_for_shell(buf); (void) fputs(qbuf, stdout); free(qbuf); free(buf); }
/* * Create a property_t which represents an scf_property_t. Returns * 0 - success * ECANCELED - prop's pg was deleted * ECONNABORTED - repository disconnected * ENOMEM - out of memory * EACCES - permission denied when reading property */ static int load_property(scf_property_t *prop, property_t **ipp) { property_t *iprop; int r; ssize_t ssz; /* get name */ if (scf_property_get_name(prop, loadbuf, loadbuf_sz) < 0) { switch (scf_error()) { case SCF_ERROR_DELETED: return (ECANCELED); case SCF_ERROR_CONNECTION_BROKEN: return (ECONNABORTED); case SCF_ERROR_NOT_BOUND: case SCF_ERROR_NOT_SET: default: bad_error("scf_property_get_name", scf_error()); } } iprop = internal_property_new(); iprop->sc_property_name = strdup(loadbuf); if (iprop->sc_property_name == NULL) { internal_property_free(iprop); return (ENOMEM); } /* get type */ if (scf_property_type(prop, &iprop->sc_value_type) != 0) { switch (scf_error()) { case SCF_ERROR_DELETED: r = ECANCELED; goto out; case SCF_ERROR_CONNECTION_BROKEN: r = ECONNABORTED; goto out; case SCF_ERROR_NOT_BOUND: case SCF_ERROR_NOT_SET: default: bad_error("scf_property_type", scf_error()); } } /* get values */ if (scf_iter_property_values(load_valiter, prop) != 0) { switch (scf_error()) { case SCF_ERROR_DELETED: r = ECANCELED; goto out; case SCF_ERROR_CONNECTION_BROKEN: r = ECONNABORTED; goto out; case SCF_ERROR_HANDLE_MISMATCH: case SCF_ERROR_NOT_BOUND: case SCF_ERROR_NOT_SET: default: bad_error("scf_iter_property_values", scf_error()); } } for (;;) { value_t *ival; r = scf_iter_next_value(load_valiter, load_val); if (r == 0) break; if (r != 1) { switch (scf_error()) { case SCF_ERROR_DELETED: r = ECANCELED; goto out; case SCF_ERROR_CONNECTION_BROKEN: r = ECONNABORTED; goto out; case SCF_ERROR_PERMISSION_DENIED: r = EACCES; goto out; case SCF_ERROR_HANDLE_MISMATCH: case SCF_ERROR_NOT_BOUND: case SCF_ERROR_NOT_SET: case SCF_ERROR_INVALID_ARGUMENT: default: bad_error("scf_iter_next_value", scf_error()); } } ival = internal_value_new(); ival->sc_type = scf_value_type(load_val); assert(ival->sc_type != SCF_TYPE_INVALID); switch (ival->sc_type) { case SCF_TYPE_BOOLEAN: { uint8_t b; r = scf_value_get_boolean(load_val, &b); if (r != 0) bad_error("scf_value_get_boolean", scf_error()); ival->sc_u.sc_count = b; break; } case SCF_TYPE_COUNT: r = scf_value_get_count(load_val, &ival->sc_u.sc_count); if (r != 0) bad_error("scf_value_get_count", scf_error()); break; case SCF_TYPE_INTEGER: r = scf_value_get_integer(load_val, &ival->sc_u.sc_integer); if (r != 0) bad_error("scf_value_get_integer", scf_error()); break; default: ssz = scf_value_get_as_string(load_val, loadbuf, loadbuf_sz); if (ssz < 0) bad_error("scf_value_get_as_string", scf_error()); ival->sc_u.sc_string = strdup(loadbuf); if (ival->sc_u.sc_string == NULL) { r = ENOMEM; goto out; } ival->sc_free = internal_value_free_str; } internal_attach_value(iprop, ival); } *ipp = iprop; return (0); out: free(iprop->sc_property_name); internal_property_free(iprop); return (r); }
/* * mgmt_get_param() get parameter of a specific LUN from scf * Args: * node - the node which parameters will be stored in mem * target_name - the local target name * lun - the LUN number * See also : mgmt_param_save2scf() */ Boolean_t mgmt_get_param(tgt_node_t **node, char *target_name, int lun) { targ_scf_t *h = NULL; scf_property_t *prop = NULL; scf_value_t *value = NULL; scf_iter_t *iter = NULL; char pname[64]; char pgname[64]; char valuebuf[MAXPATHLEN]; tgt_node_t *n; Boolean_t status = False; h = mgmt_handle_init(); if (h == NULL) return (status); prop = scf_property_create(h->t_handle); value = scf_value_create(h->t_handle); iter = scf_iter_create(h->t_handle); snprintf(pgname, sizeof (pgname), "param_%s_%d", target_name, lun); (void) pthread_mutex_lock(&scf_param_mutex); if (scf_service_get_pg(h->t_service, pgname, h->t_pg) == -1) { goto error; } *node = tgt_node_alloc(XML_ELEMENT_PARAMS, String, NULL); if (*node == NULL) goto error; if (scf_iter_pg_properties(iter, h->t_pg) == -1) { goto error; } while (scf_iter_next_property(iter, prop) > 0) { scf_property_get_value(prop, value); scf_value_get_as_string(value, valuebuf, MAXPATHLEN); scf_property_get_name(prop, pname, sizeof (pname)); /* avoid load auth to incore data */ if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 || strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 || strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0) continue; n = tgt_node_alloc(pname, String, valuebuf); if (n == NULL) goto error; /* put version info into root node's attr */ if (strcmp(pname, XML_ELEMENT_VERS) == 0) { tgt_node_add_attr(*node, n); } else { /* add other basic info into root node */ tgt_node_add(*node, n); } } status = True; error: (void) pthread_mutex_unlock(&scf_param_mutex); scf_iter_destroy(iter); scf_value_destroy(value); scf_property_destroy(prop); mgmt_handle_fini(h); return (status); }
/* * mgmt_get_main_config() loads main configuration * from scf into a node tree. * Main configuration includes: admin/target/tpgt/initiator info. * admin info is stored in "iscsitgt" property group * target info is stored in "target_<name>" property group * initiator info is stored in "initiator_<name>" property group * tpgt info is stored in "tpgt_<number>" property group */ Boolean_t mgmt_get_main_config(tgt_node_t **node) { targ_scf_t *h = NULL; scf_property_t *prop = NULL; scf_value_t *value = NULL; scf_iter_t *iter = NULL; scf_iter_t *iter_v = NULL; scf_iter_t *iter_pv = NULL; char pname[32]; char valuebuf[MAXPATHLEN]; char passcode[32]; unsigned int outlen; tgt_node_t *n; tgt_node_t *pn; tgt_node_t *vn; Boolean_t status = False; h = mgmt_handle_init(); if (h == NULL) return (status); prop = scf_property_create(h->t_handle); value = scf_value_create(h->t_handle); iter = scf_iter_create(h->t_handle); (void) pthread_mutex_lock(&scf_conf_mutex); /* Basic Information is stored in iscsitgt pg */ if (scf_service_get_pg(h->t_service, "iscsitgt", h->t_pg) == -1) { goto error; } *node = NULL; *node = tgt_node_alloc("main_config", String, NULL); if (*node == NULL) goto error; if (scf_iter_pg_properties(iter, h->t_pg) == -1) { goto error; } while (scf_iter_next_property(iter, prop) > 0) { scf_property_get_value(prop, value); scf_value_get_as_string(value, valuebuf, MAXPATHLEN); scf_property_get_name(prop, pname, sizeof (pname)); /* avoid load auth to incore data */ if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 || strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 || strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0) continue; n = tgt_node_alloc(pname, String, valuebuf); if (n == NULL) goto error; /* put version info into root node's attr */ if (strcmp(pname, XML_ELEMENT_VERS) == 0) { tgt_node_add_attr(*node, n); } else { /* add other basic info into root node */ tgt_node_add(*node, n); } } /* * targets/initiators/tpgt information is * stored as type "configuration" in scf * each target's param is stored as type "parameter" */ if (scf_iter_service_pgs_typed(iter, h->t_service, "configuration") == -1) { goto error; } while (scf_iter_next_pg(iter, h->t_pg) > 0) { char *iname; scf_pg_get_name(h->t_pg, pname, sizeof (pname)); iname = strchr(pname, '_'); if (iname == NULL) { /* the pg found here is not a tgt/initiator/tpgt */ continue; } *iname = '\0'; iname++; /* * now pname is "target" or "initiator" or "tpgt" * meanwhile iname is the actual name of the item */ n = tgt_node_alloc(pname, String, iname); if (n == NULL) goto error; iter_v = scf_iter_create(h->t_handle); if (scf_iter_pg_properties(iter_v, h->t_pg) == -1) { goto error; } while (scf_iter_next_property(iter_v, prop) > 0) { /* there may be many values in one property */ char *vname; scf_property_get_name(prop, pname, sizeof (pname)); /* avoid load auth to incore data */ if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 || strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 || strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0) continue; vname = strstr(pname, "-list"); if (vname == NULL) { scf_property_get_value(prop, value); scf_value_get_as_string(value, valuebuf, MAXPATHLEN); pn = tgt_node_alloc(pname, String, valuebuf); if (pn == NULL) goto error; tgt_node_add(n, pn); } else { pn = tgt_node_alloc(pname, String, NULL); if (pn == NULL) goto error; tgt_node_add(n, pn); *vname = '\0'; iter_pv = scf_iter_create(h->t_handle); scf_iter_property_values(iter_pv, prop); while (scf_iter_next_value(iter_pv, value) > 0) { scf_value_get_as_string(value, valuebuf, MAXPATHLEN); vn = tgt_node_alloc(pname, String, valuebuf); if (vn == NULL) goto error; tgt_node_add(pn, vn); } scf_iter_destroy(iter_pv); iter_pv = NULL; } } tgt_node_add(*node, n); scf_iter_destroy(iter_v); iter_v = NULL; } /* chap-secrets are stored in "passwords" pgroup as "application" */ if (scf_service_get_pg(h->t_service, "passwords", h->t_pg) == 0) { if (scf_iter_pg_properties(iter, h->t_pg) == -1) { goto error; } while (scf_iter_next_property(iter, prop) > 0) { scf_property_get_value(prop, value); scf_value_get_as_string(value, valuebuf, MAXPATHLEN); scf_property_get_name(prop, pname, sizeof (pname)); /* avoid load auth to incore data */ if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 || strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 || strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0) continue; /* max length of decoded passwd is 16B */ sasl_decode64(valuebuf, strlen(valuebuf), passcode, sizeof (passcode), &outlen); if (strcmp(pname, "radius") == 0) { pn = tgt_node_alloc(XML_ELEMENT_RAD_SECRET, String, passcode); tgt_node_add(*node, pn); } else if (strcmp(pname, "main") == 0) { pn = tgt_node_alloc(XML_ELEMENT_CHAPSECRET, String, passcode); tgt_node_add(*node, pn); } else { /* find corresponding initiator */ n = NULL; while (n = tgt_node_next_child(*node, XML_ELEMENT_INIT, n)) { if (strcmp(pname + 2, n->x_value) != 0) continue; pn = tgt_node_alloc( XML_ELEMENT_CHAPSECRET, String, passcode); tgt_node_add(n, pn); } } } } status = True; error: if ((status != True) && (*node != NULL)) tgt_node_free(*node); (void) pthread_mutex_unlock(&scf_conf_mutex); if (iter_pv != NULL) scf_iter_destroy(iter_pv); if (iter_v != NULL) scf_iter_destroy(iter_v); scf_iter_destroy(iter); scf_value_destroy(value); scf_property_destroy(prop); mgmt_handle_fini(h); return (status); }
/* * mgmt_get_param() get parameter of a specific LUN from scf * Args: * node - the node which parameters will be stored in mem * target_name - the local target name * lun - the LUN number * See also : mgmt_param_save2scf() */ Boolean_t mgmt_get_param(tgt_node_t **node, char *target_name, int lun) { targ_scf_t *h = NULL; scf_property_t *prop = NULL; scf_value_t *value = NULL; scf_iter_t *iter = NULL; char *pname = NULL; char *expgname = NULL; char *pgname = NULL; char *valuebuf = NULL; ssize_t max_name_len; ssize_t expg_max_name_len; ssize_t max_value_len; tgt_node_t *n; Boolean_t status = False; /* Set NULL as default output value */ *node = NULL; h = mgmt_handle_init(); if (h == NULL) return (status); prop = scf_property_create(h->t_handle); value = scf_value_create(h->t_handle); iter = scf_iter_create(h->t_handle); if ((alloc_scf_name(&max_name_len, (void *)&pname) == NULL) || (alloc_scf_name(&max_name_len, (void *)&pgname) == NULL) || (alloc_scf_value(&max_value_len, (void *)&valuebuf) == NULL)) { goto error; } /* * Allocate memory for an "expanded" (or "decoded") Property Group * name. */ expg_max_name_len = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH) * PG_FACTOR + 1; if ((expgname = malloc(expg_max_name_len)) == NULL) { goto error; } (void) snprintf(pgname, max_name_len, "param_%s_%d", target_name, lun); pgname_encode(pgname, expgname, max_name_len); (void) pthread_mutex_lock(&scf_param_mutex); if (scf_service_get_pg(h->t_service, expgname, h->t_pg) == -1) { goto error; } *node = tgt_node_alloc(XML_ELEMENT_PARAMS, String, NULL); if (*node == NULL) goto error; if (scf_iter_pg_properties(iter, h->t_pg) == -1) { goto error; } while (scf_iter_next_property(iter, prop) > 0) { (void) scf_property_get_value(prop, value); (void) scf_value_get_as_string(value, valuebuf, max_value_len); (void) scf_property_get_name(prop, pname, max_name_len); /* avoid load auth to incore data */ if (strcmp(pname, ISCSI_READ_AUTHNAME) == 0 || strcmp(pname, ISCSI_MODIFY_AUTHNAME) == 0 || strcmp(pname, ISCSI_VALUE_AUTHNAME) == 0) continue; n = tgt_node_alloc(pname, String, valuebuf); if (n == NULL) goto error; /* put version info into root node's attr */ if (strcmp(pname, XML_ELEMENT_VERS) == 0) { tgt_node_add_attr(*node, n); } else { /* add other basic info into root node */ tgt_node_add(*node, n); } } status = True; error: (void) pthread_mutex_unlock(&scf_param_mutex); free(valuebuf); free(expgname); free(pgname); free(pname); scf_iter_destroy(iter); scf_value_destroy(value); scf_property_destroy(prop); mgmt_handle_fini(h); return (status); }