Ejemplo n.º 1
0
/*
 * smb_smf_end_transaction(handle)
 *
 * Commit the changes that were added to the transaction in the
 * handle. Do all necessary cleanup.
 */
int
smb_smf_end_transaction(smb_scfhandle_t *handle)
{
	int ret = SMBD_SMF_OK;
	int rc;

	if (handle == NULL)
		return (SMBD_SMF_SYSTEM_ERR);

	if (handle->scf_trans == NULL) {
		ret = SMBD_SMF_SYSTEM_ERR;
	} else {
		rc = scf_transaction_commit(handle->scf_trans);
		if (rc == 1) {
			ret = SMBD_SMF_OK;
		} else if (rc == 0) {
			ret = SMBD_SMF_INVALID_ARG;
			smb_smf_scf_log_error("Failed to commit, old pg: "
			    "transaction: %s");
		} else {
			ret = SMBD_SMF_SYSTEM_ERR;
			smb_smf_scf_log_error("Failed to commit, error: "
			    "transaction: %s");
		}
		scf_transaction_destroy_children(handle->scf_trans);
		scf_transaction_destroy(handle->scf_trans);
		handle->scf_trans = NULL;
	}
	return (ret);
}
Ejemplo n.º 2
0
/*
 * Start transaction on current pg in handle.
 * The pg could be service or instance level.
 * Must be called after pg handle is obtained
 * from create or get.
 */
int
smb_smf_start_transaction(smb_scfhandle_t *handle)
{
	int ret = SMBD_SMF_OK;

	if (!handle || (!handle->scf_pg))
		return (SMBD_SMF_SYSTEM_ERR);

	/*
	 * lookup the property group and create it if it doesn't already
	 * exist.
	 */
	if (handle->scf_state == SCH_STATE_INIT) {
		if (ret == SMBD_SMF_OK) {
			handle->scf_trans =
			    scf_transaction_create(handle->scf_handle);
			if (handle->scf_trans != NULL) {
				if (scf_transaction_start(handle->scf_trans,
				    handle->scf_pg) != 0) {
					ret = SMBD_SMF_SYSTEM_ERR;
					scf_transaction_destroy(
					    handle->scf_trans);
					handle->scf_trans = NULL;
				}
			} else {
				ret = SMBD_SMF_SYSTEM_ERR;
			}
		}
	}
	if (ret == SMBD_SMF_SYSTEM_ERR &&
	    scf_error() == SCF_ERROR_PERMISSION_DENIED)
		ret = SMBD_SMF_NO_PERMISSION;

	return (ret);
}
Ejemplo n.º 3
0
static void
delete_prop(const scf_instance_t *inst, const char *pg, const char *prop)
{
	scf_transaction_t		*tx;
	scf_transaction_entry_t		*ent;
	scf_propertygroup_t		*gpg;
	scf_property_t			*eprop;
	int				ret;

	if ((gpg = scf_pg_create(h)) == NULL ||
	    (eprop = scf_property_create(h)) == NULL ||
	    (tx = scf_transaction_create(h)) == NULL ||
	    (ent = scf_entry_create(h)) == NULL)
		scfdie();

	if (scf_instance_get_pg(inst, pg, gpg) != SCF_SUCCESS) {
		if (scf_error() != SCF_ERROR_NOT_FOUND)
			scfdie();

		uu_die(gettext("Error: \"%s\" property group missing.\n"), pg);
	}

	do {
		if (scf_transaction_start(tx, gpg) != SCF_SUCCESS) {
			if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
				scfdie();

			uu_die(gettext("Error: Permission denied.\n"));
		}

		if (scf_transaction_property_delete(tx, ent,
		    prop) != SCF_SUCCESS) {
			if (scf_error() != SCF_ERROR_NOT_FOUND)
				scfdie();

			uu_die(
			    gettext("Error: \"%s\" property does not exist.\n"),
			    prop);
		}

		ret = scf_transaction_commit(tx);
		if (ret < 0) {
			if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
				scfdie();

			uu_die(gettext("Error: Permission denied.\n"));
		}
		if (ret == 0) {
			scf_transaction_reset(tx);
			if (scf_pg_update(gpg) == -1)
				scfdie();
		}
	} while (ret == 0);

	(void) scf_entry_destroy(ent);
	scf_transaction_destroy(tx);
	scf_property_destroy(eprop);
	scf_pg_destroy(gpg);
}
Ejemplo n.º 4
0
void
mgmt_transaction_abort(targ_scf_t *h)
{
	if (h->t_trans != NULL) {
		scf_transaction_reset_all(h->t_trans);
		scf_transaction_destroy_children(h->t_trans);
		scf_transaction_destroy(h->t_trans);
		h->t_trans = NULL;
	}
}
Ejemplo n.º 5
0
Boolean_t
mgmt_transaction_end(targ_scf_t *h)
{
	Boolean_t	ret = True;

	if (scf_transaction_commit(h->t_trans) < 0)
		ret = False;
	scf_pg_update(h->t_pg);
	scf_transaction_destroy_children(h->t_trans);
	scf_transaction_destroy(h->t_trans);
	h->t_trans = NULL;
	return (ret);
}
Ejemplo n.º 6
0
/*
 * This function starts a transaction with name of a property group
 * and name of its property. If the property group does not exist
 * this function will create an empty property group.
 */
Boolean_t
mgmt_transaction_start(targ_scf_t *h, char *pg, char *prop)
{
	Boolean_t	ret = True;

	h->t_trans = scf_transaction_create(h->t_handle);
	if (h->t_trans != NULL) {
		if ((create_pg(h, pg, prop) == False) ||
		    (scf_transaction_start(h->t_trans, h->t_pg) != 0)) {
			scf_transaction_destroy(h->t_trans);
			h->t_trans = NULL;
			ret = False;
			syslog(LOG_ERR, "transaction_start start: %s\n",
			    scf_strerror(scf_error()));
		}
	} else {
		syslog(LOG_ERR, "transaction_start create: %s\n",
		    scf_strerror(scf_error()));
		ret = False;
	}
	return (ret);
}
Ejemplo n.º 7
0
/*
 * smb_smf_end_transaction(handle)
 *
 * Commit the changes that were added to the transaction in the
 * handle. Do all necessary cleanup.
 */
int
smb_smf_end_transaction(smb_scfhandle_t *handle)
{
	int ret = SMBC_SMF_OK;

	if (handle == NULL) {
		return (SMBC_SMF_SYSTEM_ERR);
	}

	if (handle->scf_trans == NULL) {
		ret = SMBC_SMF_SYSTEM_ERR;
	} else {
		if (scf_transaction_commit(handle->scf_trans) < 0) {
			ret = SMBC_SMF_SYSTEM_ERR;
			smb_smf_scf_log_error("Failed to commit "
			    "transaction: %s");
		}
		scf_transaction_destroy_children(handle->scf_trans);
		scf_transaction_destroy(handle->scf_trans);
		handle->scf_trans = NULL;
	}
	return (ret);
}
Ejemplo n.º 8
0
/*
 * store_inetd_hash stores the string hash in inetd's configuration file hash
 * in the repository. On success, SCF_ERROR_NONE is returned. Otherwise, the
 * scf_error value is returned.
 */
scf_error_t
store_inetd_hash(const char *hash)
{
	int ret;
	scf_error_t rval = SCF_ERROR_NONE;
	scf_handle_t *h;
	scf_propertygroup_t *pg = NULL;
	scf_instance_t *inst = NULL;
	scf_transaction_t *tx = NULL;
	scf_transaction_entry_t *txent = NULL;
	scf_property_t *prop = NULL;
	scf_value_t *val = NULL;

	if ((h = scf_handle_create(SCF_VERSION)) == NULL ||
	    scf_handle_bind(h) == -1)
		goto error;

	if ((pg = scf_pg_create(h)) == NULL ||
	    (inst = scf_instance_create(h)) == NULL ||
	    scf_handle_decode_fmri(h, INETD_INSTANCE_FMRI, NULL, NULL, inst,
	    NULL, NULL, SCF_DECODE_FMRI_EXACT) == -1)
		goto error;

	if (scf_instance_get_pg(inst, HASH_PG, pg) == -1) {
		if (scf_error() != SCF_ERROR_NOT_FOUND ||
		    scf_instance_add_pg(inst, HASH_PG, SCF_GROUP_APPLICATION,
		    0, pg) == -1)
			goto error;
	}

	if ((tx = scf_transaction_create(h)) == NULL ||
	    (txent = scf_entry_create(h)) == NULL ||
	    (prop = scf_property_create(h)) == NULL ||
	    (val = scf_value_create(h)) == NULL)
		goto error;

	do {
		if (scf_transaction_start(tx, pg) == -1)
			goto error;

		if (scf_transaction_property_new(tx, txent, HASH_PROP,
		    SCF_TYPE_ASTRING) == -1 &&
		    scf_transaction_property_change_type(tx, txent, HASH_PROP,
		    SCF_TYPE_ASTRING) == -1)
			goto error;

		if (scf_value_set_astring(val, hash) == -1 ||
		    scf_entry_add_value(txent, val) == -1)
			goto error;

		if ((ret = scf_transaction_commit(tx)) == -1)
			goto error;

		if (ret == 0) {
			scf_transaction_reset(tx);
			if (scf_pg_update(pg) == -1)
				goto error;
		}
	} while (ret == 0);

	goto success;

error:
	rval = scf_error();

success:
	scf_value_destroy(val);
	scf_property_destroy(prop);
	scf_entry_destroy(txent);
	scf_transaction_destroy(tx);
	scf_instance_destroy(inst);
	scf_pg_destroy(pg);
	scf_handle_destroy(h);
	return (rval);
}
Ejemplo n.º 9
0
static int
add_pg_method(scf_handle_t *handle, scf_instance_t *instance,
    const char *kssl_entry, const char *pg_name, const char *flags,
    const char *value_str)
{
	int len, rv;
	char *command;
	const char *base_command;
	int status = FAILURE;
	boolean_t errflag = B_FALSE;
	scf_transaction_t *tran;
	scf_propertygroup_t *pg;

	pg = add_property_group_to_instance(handle, instance,
	    pg_name, SCF_GROUP_METHOD);
	if (pg == NULL) {
		/* flag is false to suppress duplicate error messages */
		errflag = B_FALSE;
		goto out0;
	}
	KSSL_DEBUG("%s method added\n", pg_name);

	tran = scf_transaction_create(handle);
	if (tran == NULL) {
		KSSL_DEBUG("scf_transaction_create failed: %s\n",
		    scf_strerror(scf_error()));
		errflag = B_TRUE;
		goto out0;
	}
	KSSL_DEBUG("scf_transaction_create succeeded\n");

	do {
		if (scf_transaction_start(tran, pg) != 0) {
			KSSL_DEBUG("scf_transaction_start failed: %s\n",
			    scf_strerror(scf_error()));
			if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
				(void) fprintf(stderr, gettext(
				    "Error: Permission denied.\n"));
				errflag = B_FALSE;
			} else if (scf_error() ==  SCF_ERROR_DELETED) {
				(void) fprintf(stderr, gettext(
				    "Error: property group %s has"
				    " been deleted.\n"), pg_name);
				errflag = B_FALSE;
			} else
				errflag = B_TRUE;
			goto out1;
		}
		KSSL_DEBUG("scf_transaction_start succeeded\n");

		if (strcmp(pg_name, "stop") == 0)
			base_command = "/usr/lib/kssladm delete";
		else
			base_command = "/usr/lib/kssladm create";

		len = strlen(base_command) + strlen(flags) +
		    strlen(kssl_entry) + 3;

		command = malloc(len);
		if (command == NULL) {
			goto out2;
		}

		(void) snprintf(command, len, "%s %s %s",
		    base_command, flags, kssl_entry);
		KSSL_DEBUG("command=%s\n", command);

		if (add_new_property(handle, SCF_PROPERTY_EXEC,
		    SCF_TYPE_ASTRING, command, tran) != SUCCESS) {
			free(command);
			goto out2;
		}
		free(command);

		if (add_new_property(handle, SCF_PROPERTY_TIMEOUT,
		    SCF_TYPE_COUNT, "60", tran) != SUCCESS)
			goto out2;

		if (set_method_context(handle, tran, value_str) != SUCCESS)
			goto out2;

		rv = scf_transaction_commit(tran);
		switch (rv) {
		case 1:
			KSSL_DEBUG("scf_transaction_commit succeeded\n");
			status = SUCCESS;
			goto out2;
		case 0:
			scf_transaction_reset(tran);
			if (scf_pg_update(pg) == -1) {
				goto out2;
			}
			break;
		case -1:
		default:
			KSSL_DEBUG("ERROR: scf_transaction_commit failed: %s\n",
			    scf_strerror(scf_error()));
			if (scf_error() == SCF_ERROR_PERMISSION_DENIED) {
				(void) fprintf(stderr, gettext(
				    "Error: Permission denied.\n"));
				errflag = B_FALSE;
			} else {
				errflag = B_TRUE;
			}
			goto out2;
		}
	} while (rv == 0);

out2:
	scf_transaction_reset(tran);
out1:
	scf_transaction_destroy_children(tran);
	scf_transaction_destroy(tran);
out0:
	if (pg != NULL)
		scf_pg_destroy(pg);
	if (errflag)
		(void) fprintf(stderr, gettext(
		    "Unexpected fatal libscf error: %s. Exiting.\n"),
		    scf_strerror(scf_error()));
	return (status);
}
Ejemplo n.º 10
0
/*
 * mgmt_config_save2scf() saves main configuration to scf
 * See also : mgmt_get_main_config()
 */
Boolean_t
mgmt_config_save2scf()
{
	targ_scf_t *h = NULL;
	scf_property_t *prop = NULL;
	scf_value_t *value = NULL;
	scf_iter_t *iter = NULL;
	char pgname[64];
	char passcode[32];
	unsigned int	outlen;
	tgt_node_t	*n = NULL;
	tgt_node_t	*pn = NULL;
	tgt_node_t	*tn = NULL;
	scf_transaction_t *tx = NULL;
	secret_list_t	*sl_head;
	secret_list_t	*sl_tail;

	h = mgmt_handle_init();

	if (h == NULL)
		return (False);

	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);

	if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
		scf_pg_delete(h->t_pg);
		mgmt_transaction_end(h);
	}

	if (mgmt_transaction_start(h, "passwords", "application") == True) {
		scf_pg_delete(h->t_pg);
		mgmt_transaction_end(h);
	}

	if (scf_iter_service_pgs_typed(iter, h->t_service, "configuration")
	    == -1) {
		goto error;
	}

	tx = scf_transaction_create(h->t_handle);
	while (scf_iter_next_pg(iter, h->t_pg) > 0) {
		scf_transaction_start(tx, h->t_pg);
		scf_pg_delete(h->t_pg);
		scf_transaction_commit(tx);
	}
	scf_transaction_reset(tx);
	scf_transaction_destroy(tx);

	sl_head = (secret_list_t *)calloc(1, sizeof (secret_list_t));
	sl_tail = sl_head;

	if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
		for (n = main_config->x_child; n; n = n->x_sibling) {
			if (strcmp(n->x_name,
			    XML_ELEMENT_CHAPSECRET) == 0) {
				sl_tail->next =  (secret_list_t *)
				    calloc(1, sizeof (secret_list_t));
				sl_tail = sl_tail->next;
				sl_tail->name = strdup("main");
				sl_tail->secret = strdup(n->x_value);
				continue;
			}
			/* so does the radius server secret */
			if (strcmp(n->x_name,
			    XML_ELEMENT_RAD_SECRET) == 0) {
				sl_tail->next =  (secret_list_t *)
				    calloc(1, sizeof (secret_list_t));
				sl_tail = sl_tail->next;
				sl_tail->name = strdup("radius");
				sl_tail->secret = strdup(n->x_value);
				continue;
			}
			if (n->x_child == NULL) {
				new_property(h, n);
			}
		}
		new_property(h, main_config->x_attr);
		n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
		    ISCSI_AUTH_MODIFY);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
		    ISCSI_AUTH_VALUE);
		new_property(h, n);
		tgt_node_free(n);
		mgmt_transaction_end(h);
	}

	/* now update target/initiator/tpgt information */
	for (n = main_config->x_child; n; n = n->x_sibling) {
		if (n->x_child == NULL)
			continue;

		snprintf(pgname, sizeof (pgname), "%s_%s", n->x_name,
		    n->x_value);

		if (mgmt_transaction_start(h, pgname, "configuration")
		    == True) {
			for (pn = n->x_child; pn; pn = pn->x_sibling) {
				if (strcmp(pn->x_name,
				    XML_ELEMENT_CHAPSECRET) == 0) {
					sl_tail->next =  (secret_list_t *)
					    calloc(1, sizeof (secret_list_t));
					sl_tail = sl_tail->next;
					sl_tail->name = (char *)
					    calloc(1, strlen(n->x_value) + 3);
					snprintf(sl_tail->name,
					    strlen(n->x_value) + 3,
					    "I_%s", n->x_value);
					sl_tail->secret = strdup(pn->x_value);
					continue;
				}
				if (pn->x_child == NULL) {
					/* normal property */
					new_property(h, pn);
				} else {
					/* pn -> xxx-list */
					new_value_list(h, pn);
				}
				tn = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME,
				    String, ISCSI_AUTH_MODIFY);
				new_property(h, tn);
				tgt_node_free(tn);
				tn = tgt_node_alloc(ISCSI_VALUE_AUTHNAME,
				    String, ISCSI_AUTH_VALUE);
				new_property(h, tn);
				tgt_node_free(tn);
			}
			mgmt_transaction_end(h);
		}
	}

	if (mgmt_transaction_start(h, "passwords", "application") == True) {
		while (sl_head != NULL) {
			/* Here we use sl_tail as a temporari var */
			sl_tail = sl_head->next;
			if (sl_head->name) {
				/* max length of encoded passwd is 24B */
				sasl_encode64(sl_head->secret,
				    strlen(sl_head->secret), passcode,
				    sizeof (passcode), &outlen);

				n = tgt_node_alloc(sl_head->name, String,
				    passcode);
				new_property(h, n);
				tgt_node_free(n);
			}
			if (sl_head->name)
				free(sl_head->name);
			if (sl_head->secret)
				free(sl_head->secret);
			free(sl_head);
			sl_head = sl_tail;
		}
		n = tgt_node_alloc(ISCSI_READ_AUTHNAME, String,
		    ISCSI_AUTH_READ);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
		    ISCSI_AUTH_VALUE);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
		    ISCSI_AUTH_MODIFY);
		new_property(h, n);
		tgt_node_free(n);
		mgmt_transaction_end(h);
	}

	if (smf_refresh_instance(SA_TARGET_SVC_INSTANCE_FMRI) != 0)
		goto error;

	(void) pthread_mutex_unlock(&scf_conf_mutex);
	scf_iter_destroy(iter);
	scf_value_destroy(value);
	scf_property_destroy(prop);
	return (True);

error:
	(void) pthread_mutex_unlock(&scf_conf_mutex);
	scf_iter_destroy(iter);
	scf_value_destroy(value);
	scf_property_destroy(prop);
	mgmt_handle_fini(h);
	return (False);
}
Ejemplo n.º 11
0
int
fs_smf_set_prop(smf_fstype_t fstype, char *prop_name, char *valbuf,
    char *instance, scf_type_t sctype, char *fmri)
{
	fs_smfhandle_t *phandle = NULL;
	scf_handle_t *handle;
	scf_propertygroup_t *pg;
	scf_property_t *prop;
	scf_transaction_t *tran = NULL;
	scf_transaction_entry_t *entry = NULL;
	scf_instance_t *inst;
	scf_value_t *val;
	int valint;
	int index = 0;
	int ret = 0;
	char *p = NULL;
	char *svcname, srv[MAXPATHLEN];
	const char *pgname;

	/*
	 * The SVC names we are using currently are already
	 * appended by default. Fix this for instances project.
	 */
	snprintf(srv, MAXPATHLEN, "%s", fmri);
	p = strstr(fmri, ":default");
	if (p == NULL) {
		strcat(srv, ":");
		if (instance == NULL)
			instance = "default";
		if (strlen(srv) + strlen(instance) > MAXPATHLEN)
			goto out;
		strncat(srv, instance, strlen(instance));
	}
	svcname = srv;
	phandle = fs_smf_init(fmri, instance);
	if (phandle == NULL) {
		return (SMF_SYSTEM_ERR);
	}
	handle = phandle->fs_handle;
	pg = phandle->fs_pg;
	prop = phandle->fs_property;
	inst = phandle->fs_instance;
	val = phandle->fs_value;
	tran = scf_transaction_create(handle);
	entry = scf_entry_create(handle);

	if (handle == NULL || pg == NULL || prop == NULL ||
	    val == NULL|| tran == NULL || entry == NULL || inst == NULL) {
		ret = SMF_SYSTEM_ERR;
		goto out;
	}

	if (scf_handle_decode_fmri(handle, svcname, phandle->fs_scope,
	    phandle->fs_service, inst, NULL, NULL, 0) != 0) {
		ret = scf_error();
		goto out;
	}
	if (fstype == AUTOFS_SMF)
		pgname = AUTOFS_PROPS_PGNAME;
	else
		pgname = NFS_PROPS_PGNAME;

	if (scf_instance_get_pg(inst, pgname,
	    pg) != -1) {
		uint8_t	vint;
		if (scf_transaction_start(tran, pg) == -1) {
			ret = scf_error();
			goto out;
		}
		switch (sctype) {
		case SCF_TYPE_INTEGER:
			errno = 0;
			valint = strtoul(valbuf, NULL, 0);
			if (errno != 0) {
				ret = SMF_SYSTEM_ERR;
				goto out;
			}
			if (scf_transaction_property_change(tran,
			    entry, prop_name, SCF_TYPE_INTEGER) == 0) {
				scf_value_set_integer(val, valint);
				if (scf_entry_add_value(entry, val) < 0) {
					ret = scf_error();
					goto out;
				}
			}
			break;
		case SCF_TYPE_ASTRING:
			if (scf_transaction_property_change(tran, entry,
			    prop_name, SCF_TYPE_ASTRING) == 0) {
				if (scf_value_set_astring(val,
				    valbuf) == 0) {
					if (scf_entry_add_value(entry,
					    val) != 0) {
						ret = scf_error();
						goto out;
					}
				} else
					ret = SMF_SYSTEM_ERR;
			} else
				ret = SMF_SYSTEM_ERR;
			break;
		case SCF_TYPE_BOOLEAN:
			if (strcmp(valbuf, "1") == 0) {
				vint = 1;
			} else if (strcmp(valbuf, "0") == 0) {
				vint = 0;
			} else  {
				ret = SMF_SYSTEM_ERR;
				break;
			}
			if (scf_transaction_property_change(tran, entry,
			    prop_name, SCF_TYPE_BOOLEAN) == 0) {
				scf_value_set_boolean(val, (uint8_t)vint);
				if (scf_entry_add_value(entry, val) != 0) {
					ret = scf_error();
					goto out;
				}
			} else {
				ret = SMF_SYSTEM_ERR;
			}
			break;
		}
		if (ret != SMF_SYSTEM_ERR)
			scf_transaction_commit(tran);
	}
out:
	if (tran != NULL)
		scf_transaction_destroy(tran);
	if (entry != NULL)
		scf_entry_destroy(entry);
	fs_smf_fini(phandle);
	return (ret);
}
Ejemplo n.º 12
0
conerr_t
smfu_set_property(char *fmri, char *pgname, char *propname, char *value)
{
	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_value_t *val = scf_value_create(scfhandle);
	scf_transaction_t *tx = scf_transaction_create(scfhandle);
	scf_transaction_entry_t *ent = scf_entry_create(scfhandle);
	scf_type_t type;

	if (scfhandle == NULL || service == NULL || instance == NULL ||
	    pg == NULL || prop == NULL || tx == NULL || ent == 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_property_type(prop, &type) != 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;
	}

top:
	if (scf_transaction_start(tx, pg) == -1 ||
	    scf_transaction_property_change(tx, ent, propname, type) != 0 ||
	    scf_value_set_from_string(val, type, value) != 0 ||
	    scf_entry_add_value(ent, val) != 0) {
		rad_log(RL_ERROR, "couldn't set property: '%s/%s/%s': %s\n",
		    fmri, pgname, propname, scf_strerror(scf_error()));
		err = maperr(scf_error());
		goto out;
	}

	switch (scf_transaction_commit(tx)) {
	/* success */
	case 1:
		if (smf_refresh_instance(fmri) != 0) {
			err = maperr(scf_error());
			goto out;
		}
		break;
	/* retry */
	case 0:
		if (scf_pg_update(pg) != 0) {
			err = maperr(scf_error());
			goto out;
		}
		scf_transaction_reset(tx);
		goto top;
	default:
		err = maperr(scf_error());
		goto out;
	}
out:
	scf_entry_destroy(ent);
	scf_transaction_destroy(tx);
	scf_value_destroy(val);
	scf_property_destroy(prop);
	scf_pg_destroy(pg);
	scf_instance_destroy(instance);
	scf_service_destroy(service);
	scf_handle_destroy(scfhandle);

	return (err);
}
Ejemplo n.º 13
0
static void
modify_prop(const scf_instance_t *inst, const char *pg, const char *prop,
    scf_type_t type, void *value)
{
	scf_transaction_t		*tx;
	scf_transaction_entry_t		*ent;
	scf_propertygroup_t		*gpg;
	scf_property_t			*eprop;
	scf_value_t			*v;
	int				ret, create = 0;
	char				*fmri;
	ssize_t				max_fmri_len;

	if ((gpg = scf_pg_create(h)) == NULL ||
	    (eprop = scf_property_create(h)) == NULL ||
	    (v = scf_value_create(h)) == NULL)
		scfdie();

	/* Get the property group or create it if it is missing. */
	if (scf_instance_get_pg(inst, pg, gpg) == -1) {
		if (scf_error() != SCF_ERROR_NOT_FOUND)
			scfdie();

		max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
		if ((fmri = malloc(max_fmri_len + 1)) == NULL)
			uu_die(gettext("Error: Out of memory.\n"));

		if (scf_instance_to_fmri(inst, fmri, max_fmri_len + 1) < 0)
			scfdie();

		syslog(LOG_NOTICE, "inetadm: Property group \"%s\" missing "
		    "from \"%s\", attempting to add it.\n", pg, fmri);
		free(fmri);

		if (scf_instance_add_pg(inst, pg, SCF_GROUP_FRAMEWORK, 0,
		    gpg) == -1) {
			switch (scf_error()) {
			case SCF_ERROR_EXISTS:
				break;
			case SCF_ERROR_PERMISSION_DENIED:
				uu_die(gettext("Error: Permission denied.\n"));
			default:
				scfdie();
			}
		}
	}

	if (scf_pg_get_property(gpg, prop, eprop) == -1) {
		if (scf_error() != SCF_ERROR_NOT_FOUND)
			scfdie();

		create = 1;
	}

	if ((tx = scf_transaction_create(h)) == NULL ||
	    (ent = scf_entry_create(h)) == NULL)
		scfdie();

	do {
		uu_list_t	*sv_list;

		if (scf_transaction_start(tx, gpg) == -1) {
			if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
				scfdie();

			uu_die(gettext("Error: Permission denied.\n"));
		}

		/* Modify the property or create it if it is missing */
		if (create)
			ret = scf_transaction_property_new(tx, ent, prop, type);
		else
			ret = scf_transaction_property_change_type(tx, ent,
			    prop, type);
		if (ret == -1)
			scfdie();

		switch (type) {
		case SCF_TYPE_BOOLEAN:
			scf_value_set_boolean(v, *(uint8_t *)value);
			break;
		case SCF_TYPE_INTEGER:
			scf_value_set_integer(v, *(int64_t *)value);
			break;
		case SCF_TYPE_ASTRING:
			if (strcmp(prop, PR_PROTO_NAME) == 0) {
				add_proto_list(ent, h, (char **)value,
				    &sv_list);
			} else if (scf_value_set_astring(v, value) == -1) {
				scfdie();
			}
			break;
		default:
			uu_die(gettext("Error: Internal inetadm error"));
		}

		if ((strcmp(prop, PR_PROTO_NAME) != 0) &&
		    (scf_entry_add_value(ent, v) == -1))
			scfdie();

		ret = scf_transaction_commit(tx);
		if (ret == -1) {
			if (scf_error() != SCF_ERROR_PERMISSION_DENIED)
				scfdie();

			uu_die(gettext("Error: Permission denied.\n"));
		}

		scf_transaction_reset(tx);

		if (ret == 0) {
			if (scf_pg_update(gpg) == -1)
				scfdie();
		}

		if (strcmp(prop, PR_PROTO_NAME) == 0)
			remove_proto_list(ent, sv_list);

	} while (ret == 0);

	scf_value_destroy(v);
	scf_entry_destroy(ent);
	scf_transaction_destroy(tx);
	scf_property_destroy(eprop);
	scf_pg_destroy(gpg);
}