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/*
2N/A * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <alloca.h>
2N/A#include <netdb.h>
2N/A#include <strings.h>
2N/A#include <pthread.h>
2N/A#include <sys/types.h>
2N/A#include <sys/fm/protocol.h>
2N/A#include <sys/systeminfo.h>
2N/A#include <sys/varargs.h>
2N/A#include <unistd.h>
2N/A#include <uuid/uuid.h>
2N/A
2N/A#include "asr.h"
2N/A#include "asr_mem.h"
2N/A#include "asr_nvl.h"
2N/A#include "asr_scf.h"
2N/A#include "fm/libasr.h"
2N/A#include "libasr.h"
2N/A
2N/A#define ASR_ACTIVATE_BUFSIZE 1279
2N/A
2N/Astatic pthread_mutex_t asr_sysprops_lock = PTHREAD_MUTEX_INITIALIZER;
2N/Astatic nvlist_t *asr_sysprops = NULL;
2N/A
2N/Astatic char *asr_reg_props[] = {
2N/A ASR_PROP_REG_CLIENT_ID,
2N/A ASR_PROP_REG_CODE,
2N/A ASR_PROP_REG_MESSAGE,
2N/A ASR_PROP_REG_MSG_KEY,
2N/A ASR_PROP_REG_PUB_KEY,
2N/A ASR_PROP_REG_SYSTEM_ID,
2N/A ASR_PROP_REG_ASSET_ID,
2N/A ASR_PROP_REG_URL,
2N/A ASR_PROP_REG_USER_ID,
2N/A ASR_PROP_REG_PROXY_HOST,
2N/A ASR_PROP_REG_PROXY_USER,
2N/A ASR_PROP_REG_PROXY_PASS,
2N/A ASR_PROP_REG_INDEX,
2N/A ASR_PROP_REG_STATUS,
2N/A ASR_PROP_REG_TRANSPORT,
2N/A ASR_PROP_REG_TIMESTAMP,
2N/A NULL
2N/A};
2N/A
2N/A/*
2N/A * Formats local time into a string for debugging messages.
2N/A */
2N/Astatic void
2N/Aasr_time(char *timebuf, int tlen)
2N/A{
2N/A struct tm *tmptr;
2N/A time_t now = time(NULL);
2N/A tmptr = localtime(&now);
2N/A if (tmptr == NULL)
2N/A (void) strcpy(timebuf, "?");
2N/A else
2N/A (void) strftime(timebuf, tlen, "%c", tmptr);
2N/A}
2N/A
2N/A/*
2N/A * Sets the property name in the ASR handle with the given value.
2N/A */
2N/Aint
2N/Aasr_setprop_str(asr_handle_t *ah, const char *name, const char *value)
2N/A{
2N/A if (ah == NULL || name == NULL || ah->asr_cfg == NULL) {
2N/A asr_log_errno(ah, EASR_NULLDATA);
2N/A return (EASR_NULLDATA);
2N/A }
2N/A
2N/A if (asr_nvl_add_str(ah->asr_cfg, name, value) != 0) {
2N/A asr_log_error(ah, EASR_NVLIST,
2N/A "Unable to set property %s to %s",
2N/A name, value == NULL ? "null" : value);
2N/A return (ASR_FAILURE);
2N/A }
2N/A
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Sets the property name in the ASR handle with the given value.
2N/A * If value isn't set because it is NULL then the default_value will be used.
2N/A */
2N/Aint
2N/Aasr_setprop_strd(asr_handle_t *ah, const char *name,
2N/A const char *value, const char *default_value)
2N/A{
2N/A return (asr_setprop_str(ah, name,
2N/A (value == NULL) ? default_value : value));
2N/A}
2N/A
2N/A/*
2N/A * Gets a property from the ASR handle. If the property doesn't exist,
2N/A * its value is an empty string or there is an error then the default value is
2N/A * returned.
2N/A * If there is an error during the operation then asr_errno is set.
2N/A */
2N/Achar *
2N/Aasr_getprop_strd(asr_handle_t *ah, const char *name, char *default_value)
2N/A{
2N/A int err = 1;
2N/A char *val;
2N/A
2N/A if (ah == NULL || name == NULL || ah->asr_cfg == NULL) {
2N/A asr_log_errno(ah, EASR_NULLDATA);
2N/A return (NULL);
2N/A }
2N/A
2N/A err = nvlist_lookup_string(ah->asr_cfg, name, &val);
2N/A
2N/A if (err)
2N/A val = default_value;
2N/A
2N/A if (val == NULL || val[0] == '\0')
2N/A val = default_value;
2N/A
2N/A return (val);
2N/A}
2N/A
2N/A/*
2N/A * Gets a property from the ASR handle. If the property doesn't exist, its
2N/A * value is empty or there was an error then NULL is returned.
2N/A */
2N/Achar *
2N/Aasr_getprop_str(asr_handle_t *ah, const char *name)
2N/A{
2N/A return (asr_getprop_strd(ah, name, NULL));
2N/A}
2N/A
2N/A/*
2N/A * Gets a boolean property from the ASR handle. If the property doesn't
2N/A * exist then the default value is returned.
2N/A */
2N/Aboolean_t
2N/Aasr_getprop_bool(asr_handle_t *ah, const char *name, boolean_t default_value)
2N/A{
2N/A char *val = asr_getprop_str(ah, name);
2N/A boolean_t retval = default_value;
2N/A
2N/A if (val == NULL) {
2N/A boolean_t bval;
2N/A if (nvlist_lookup_boolean_value(ah->asr_cfg, name, &bval) == 0)
2N/A retval = bval;
2N/A } else {
2N/A if (strcmp(ASR_VALUE_TRUE, val) == 0)
2N/A retval = B_TRUE;
2N/A else if (strcmp(ASR_VALUE_FALSE, val) == 0)
2N/A retval = B_FALSE;
2N/A }
2N/A return (retval);
2N/A}
2N/A
2N/A/*
2N/A * Gets a number property from the ASR handle. If the property doesn't
2N/A * exist or can't be parsed then the default value is returned.
2N/A */
2N/Along
2N/Aasr_getprop_long(asr_handle_t *ah, const char *name, long default_value)
2N/A{
2N/A char *val = asr_getprop_str(ah, name);
2N/A long retval = default_value;
2N/A
2N/A if (val == NULL) {
2N/A int64_t ival;
2N/A if (nvlist_lookup_int64(ah->asr_cfg, name, &ival) == 0)
2N/A retval = ival;
2N/A } else {
2N/A long lval;
2N/A errno = 0;
2N/A lval = atol(val);
2N/A if (errno == 0)
2N/A retval = lval;
2N/A }
2N/A return (retval);
2N/A}
2N/A
2N/A/*
2N/A * Get the path value for the given property name. The root directory will
2N/A * be appended to the path. It is the responsibility of the caller to
2N/A * free the resulting string when done.
2N/A * If the property isn't set then the default_value will be returned.
2N/A * If there is an error then NULL will be returned.
2N/A */
2N/Achar *asr_getprop_path(
2N/A asr_handle_t *ah, const char *name, const char *default_value)
2N/A{
2N/A char *path = NULL;
2N/A char *root = asr_getprop_strd(ah, ASR_PROP_ROOTDIR, "/");
2N/A int rlen = strlen(root);
2N/A char *file = asr_getprop_str(ah, name);
2N/A int plen;
2N/A
2N/A if (file == NULL || file[0] == '\0')
2N/A file = (char *)default_value;
2N/A if (file == NULL || file[0] == '\0')
2N/A return (NULL);
2N/A plen = rlen + strlen(file) + 2;
2N/A if ((path = malloc(plen)) == NULL)
2N/A return (NULL);
2N/A if ('/' == root[rlen-1])
2N/A (void) snprintf(path, plen, "%s%s", root, file);
2N/A else
2N/A (void) snprintf(path, plen, "%s/%s", root, file);
2N/A return (path);
2N/A}
2N/A
2N/A/*
2N/A * Checks if string contains all the same chars as value c
2N/A */
2N/Astatic boolean_t
2N/Astrcharcmp(char c, char *val)
2N/A{
2N/A while (val[0] == c)
2N/A val++;
2N/A return (val[0] == '\0');
2N/A}
2N/A
2N/A/*
2N/A * Checks if a string property is set to a valid value. An invalid or unset
2N/A * value can be NULL, an empty string, all zeros, all spaces or 'unknown'
2N/A */
2N/Astatic boolean_t
2N/Aasr_is_str_prop_valid(char *prop)
2N/A{
2N/A if (prop == NULL || prop[0] == '\0' || strcharcmp('0', prop) ||
2N/A strcharcmp(' ', prop) || strcmp("unknown", prop) == 0)
2N/A return (B_FALSE);
2N/A return (B_TRUE);
2N/A}
2N/A
2N/A/*
2N/A * Checks that a system id is valid and the proper length
2N/A */
2N/Astatic boolean_t
2N/Aasr_issysid_valid(char *id)
2N/A{
2N/A return (asr_is_str_prop_valid(id) && strlen(id) == ASR_SN_LEN);
2N/A}
2N/A
2N/A/*
2N/A * Gets the registered asset id of the Solaris host. If one doesn't exist
2N/A * a new uuid is generated.
2N/A */
2N/Achar *
2N/Aasr_get_assetid(asr_handle_t *ah)
2N/A{
2N/A char *asset_id = asr_getprop_str(ah, ASR_PROP_ASSET_ID);
2N/A
2N/A if (!asr_is_str_prop_valid(asset_id))
2N/A asset_id = asr_getprop_str(ah, ASR_PROP_REG_ASSET_ID);
2N/A if (!asr_is_str_prop_valid(asset_id)) {
2N/A uuid_t uuid;
2N/A char uuidbuf[UUID_PRINTABLE_STRING_LENGTH];
2N/A uuid_generate(uuid);
2N/A uuid_unparse(uuid, uuidbuf);
2N/A if (asr_setprop_str(ah, ASR_PROP_ASSET_ID, uuidbuf) != 0)
2N/A return (NULL);
2N/A asset_id = asr_getprop_strd(ah, ASR_PROP_ASSET_ID, NULL);
2N/A }
2N/A return (asset_id);
2N/A}
2N/A
2N/A/*
2N/A * Finds system authority information used to populate ASR properties such as
2N/A * system-id and product-name from fm libtopo. The FMA authority fields will be
2N/A * searched in the following order:
2N/A * "system-id" = ("system-serial", "sys-comp-serial", "chassis-serial")
2N/A * "product-name" = ("system-name", "sys-comp-name", "chassis-name")
2N/A * Stores the FMA authority properties in a cache so that they are available
2N/A * for future calls.
2N/A */
2N/Astatic nvlist_t *
2N/Aasr_get_authority(asr_handle_t *ah)
2N/A{
2N/A nvlist_t *auth = NULL;
2N/A (void) pthread_mutex_lock(&asr_sysprops_lock);
2N/A if (asr_sysprops == NULL && asr_topo_auth(ah, &auth) == 0)
2N/A asr_sysprops = auth;
2N/A (void) pthread_mutex_unlock(&asr_sysprops_lock);
2N/A return (asr_sysprops);
2N/A}
2N/A
2N/Achar *
2N/Aasr_get_sysprop(asr_handle_t *ah, boolean_t (*validator)(char *),
2N/A char *name, ...)
2N/A{
2N/A va_list vp;
2N/A nvlist_t *auth;
2N/A char *id, *prop = asr_getprop_str(ah, name);
2N/A
2N/A if ((*validator)(prop))
2N/A return (prop);
2N/A if ((auth = asr_get_authority(ah)) == NULL)
2N/A return (NULL);
2N/A va_start(vp, name);
2N/A while ((id = va_arg(vp, char *)) != NULL) {
2N/A if ((prop = asr_nvl_strd(auth, id, NULL)) != NULL &&
2N/A (*validator)(prop)) {
2N/A va_end(vp);
2N/A return (prop);
2N/A }
2N/A }
2N/A va_end(vp);
2N/A return (NULL);
2N/A}
2N/A
2N/A/*
2N/A * Gets the system id which should be the 10 digit ASR system identity used
2N/A * for asset validation.
2N/A * If not found then the system won't be able to be activated with the ASR
2N/A * backend service but the generated asset id will be used as the system ID to
2N/A * support advanced telemetry. This can happen on older unsupported platforms,
2N/A * non Sun hardware and virtual machines.
2N/A */
2N/Achar *
2N/Aasr_get_systemid(asr_handle_t *ah)
2N/A{
2N/A char *system_id = asr_get_sysprop(ah, asr_issysid_valid,
2N/A ASR_PROP_SYSTEM_ID, FM_FMRI_AUTH_V1_SYSTEM_SN,
2N/A FM_FMRI_AUTH_V1_SYS_COMP_SN, FM_FMRI_AUTH_V1_CHASSIS_SN,
2N/A FM_FMRI_AUTH_V0_CHASSIS, NULL);
2N/A
2N/A if (asr_issysid_valid(system_id))
2N/A return (system_id);
2N/A else {
2N/A if (asr_topo_set_system_id(ah) == 0)
2N/A system_id = asr_getprop_str(ah, ASR_PROP_SYSTEM_ID);
2N/A }
2N/A if (asr_issysid_valid(system_id))
2N/A return (system_id);
2N/A else {
2N/A char info[80];
2N/A if (sysinfo(SI_HW_SERIAL, info, sizeof (info)) != -1) {
2N/A (void) asr_setprop_str(ah, ASR_PROP_SYSTEM_ID, info);
2N/A system_id = asr_getprop_str(ah, ASR_PROP_SYSTEM_ID);
2N/A }
2N/A }
2N/A if (asr_is_str_prop_valid(system_id))
2N/A return (system_id);
2N/A else {
2N/A system_id = asr_get_assetid(ah);
2N/A (void) asr_setprop_str(ah, ASR_PROP_SYSTEM_ID, system_id);
2N/A }
2N/A return (system_id);
2N/A}
2N/A
2N/A/*
2N/A * Gets the product name of the computer system if available.
2N/A */
2N/Achar *
2N/Aasr_get_product_name(asr_handle_t *ah)
2N/A{
2N/A char *product_name = asr_get_sysprop(ah, asr_is_str_prop_valid,
2N/A ASR_PROP_PRODUCT_NAME, FM_FMRI_AUTH_V1_SYSTEM_NM,
2N/A FM_FMRI_AUTH_V1_SYS_COMP_NM, FM_FMRI_AUTH_V1_CHASSIS_NM,
2N/A FM_FMRI_AUTH_V0_PRODUCT, NULL);
2N/A
2N/A if (asr_is_str_prop_valid(product_name))
2N/A return (product_name);
2N/A else {
2N/A if (asr_topo_set_product_name(ah) == 0)
2N/A product_name = asr_getprop_str(ah,
2N/A ASR_PROP_PRODUCT_NAME);
2N/A }
2N/A
2N/A return (asr_is_str_prop_valid(product_name) ? product_name :
2N/A ASR_DEFAULT_PRODUCT_NAME);
2N/A}
2N/A
2N/A/*
2N/A * Gets the product id of the computer system if available.
2N/A */
2N/Achar *
2N/Aasr_get_productid(asr_handle_t *ah)
2N/A{
2N/A char *product_id = asr_get_sysprop(ah, asr_is_str_prop_valid,
2N/A ASR_PROP_PRODUCT_ID, FM_FMRI_AUTH_V1_SYSTEM_PN,
2N/A FM_FMRI_AUTH_V1_SYS_COMP_PN, FM_FMRI_AUTH_V1_CHASSIS_PN, NULL);
2N/A return (asr_is_str_prop_valid(product_id) ? product_id :
2N/A asr_get_product_name(ah));
2N/A}
2N/A
2N/A/*
2N/A * Gets the site id which is usually the same as the systemid. In the case
2N/A * of an appliance the appliance serial number will be used.
2N/A */
2N/Achar *
2N/Aasr_get_siteid(asr_handle_t *ah)
2N/A{
2N/A char *site_id = asr_getprop_str(ah, ASR_PROP_SITE_ID);
2N/A if (site_id == NULL || site_id[0] == '\0')
2N/A site_id = asr_get_systemid(ah);
2N/A return (site_id);
2N/A}
2N/A
2N/A/*
2N/A * Gets the registered ASR client registration id
2N/A */
2N/Achar *
2N/Aasr_get_regid(asr_handle_t *ah)
2N/A{
2N/A return (asr_getprop_str(ah, ASR_PROP_REG_CLIENT_ID));
2N/A}
2N/A
2N/A/*
2N/A * Gets the message signing key length to be used when generating new
2N/A * client public/private key pairs for signing messages.
2N/A */
2N/Asize_t
2N/Aasr_get_keylen(asr_handle_t *ah)
2N/A{
2N/A char *keylen = asr_getprop_str(ah, ASR_PROP_KEYLEN);
2N/A unsigned long len;
2N/A
2N/A if (keylen == NULL)
2N/A len = ASR_DEFAULT_KEYLEN;
2N/A else if (sscanf(keylen, "%lu", &len) != 1) {
2N/A (void) asr_error(EASR_PROP_USAGE,
2N/A "Error parsing keylen (%s). Using default value %i",
2N/A keylen, ASR_DEFAULT_KEYLEN);
2N/A len = ASR_DEFAULT_KEYLEN;
2N/A }
2N/A return (len);
2N/A}
2N/A
2N/A/*
2N/A * Gets the timeout to be used for http requests.
2N/A */
2N/Along
2N/Aasr_get_http_timeout(asr_handle_t *ah)
2N/A{
2N/A char *timeout = asr_getprop_str(ah, ASR_PROP_HTTP_TIMEOUT);
2N/A long nsec;
2N/A
2N/A if (timeout == NULL)
2N/A nsec = ASR_DEFAULT_HTTP_TIMEOUT;
2N/A else if (sscanf(timeout, "%ld", &nsec) != 1) {
2N/A (void) asr_error(EASR_PROP_USAGE,
2N/A "Error parsing http timeout (%s). Using default value %i",
2N/A timeout, ASR_DEFAULT_HTTP_TIMEOUT);
2N/A nsec = ASR_DEFAULT_HTTP_TIMEOUT;
2N/A }
2N/A nsec *= 1000000L;
2N/A return (nsec);
2N/A}
2N/A
2N/A/*
2N/A * Gets the directory that the phone home service can use for writing
2N/A * log files, saving state and temporary data.
2N/A */
2N/Achar *
2N/Aasr_get_datadir(asr_handle_t *ah)
2N/A{
2N/A return (asr_getprop_strd(ah, ASR_PROP_DATA_DIR, "."));
2N/A}
2N/A
2N/A/*
2N/A * Gets the registered message signing keys.
2N/A */
2N/Achar *
2N/Aasr_get_privkey(asr_handle_t *ah)
2N/A{
2N/A return (asr_getprop_strd(ah, ASR_PROP_REG_MSG_KEY, (char *)NULL));
2N/A}
2N/A
2N/A/*
2N/A * Gets the current phone-home configuration properties. If the properties
2N/A * or handle haven't been initialized then NULL is returned.
2N/A */
2N/Anvlist_t *
2N/Aasr_get_config(asr_handle_t *ah)
2N/A{
2N/A return (ah == NULL ? NULL : ah->asr_cfg);
2N/A}
2N/A
2N/A/*
2N/A * Gets the log file handle used for debugging
2N/A */
2N/AFILE *
2N/Aasr_get_logfile(asr_handle_t *ah)
2N/A{
2N/A return (ah == NULL ? NULL : ah->asr_log);
2N/A}
2N/A
2N/A/*
2N/A * Sets the log file used for debugging
2N/A */
2N/Avoid
2N/Aasr_set_logfile(asr_handle_t *ah, FILE *log)
2N/A{
2N/A ah->asr_log = log;
2N/A}
2N/A
2N/A/*
2N/A * Sets the configuration name used to save the configuration. The name
2N/A * can either be a filename (for debugging) or a service FMRI.
2N/A */
2N/Aint
2N/Aasr_set_config_name(asr_handle_t *ah, const char *name)
2N/A{
2N/A if (ah->asr_cfg_name != NULL)
2N/A free(ah->asr_cfg_name);
2N/A if (name == NULL) {
2N/A ah->asr_cfg_name = NULL;
2N/A return (0);
2N/A }
2N/A ah->asr_cfg_name = asr_strdup(name);
2N/A return (ah->asr_cfg_name == NULL ? ASR_FAILURE : ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Prints the ASR Phone Home configuration properties to the given stream.
2N/A * None zero is returned if there is an error.
2N/A */
2N/Aint
2N/Aasr_print_config(asr_handle_t *ah, FILE *out)
2N/A{
2N/A if (ah == NULL || ah->asr_cfg == NULL || out == NULL) {
2N/A asr_log_errno(ah, EASR_NULLDATA);
2N/A return (NULL);
2N/A }
2N/A return (asr_nvl_print_properties(out, ah->asr_cfg));
2N/A}
2N/A
2N/A/*
2N/A * Determines if the config is a service FMRI (true) or a file name.
2N/A */
2N/Astatic boolean_t
2N/Aasr_cfg_is_file(char *config)
2N/A{
2N/A boolean_t is_file = B_FALSE;
2N/A
2N/A if (config != NULL) {
2N/A char *svc = "svc:/";
2N/A int i;
2N/A for (i = 0; svc[i] != '\0'; i++) {
2N/A if (config[i] != svc[i]) {
2N/A is_file = B_TRUE;
2N/A break;
2N/A }
2N/A }
2N/A }
2N/A return (is_file);
2N/A}
2N/A
2N/A/*
2N/A * Saves the ASR configuration properties.
2N/A */
2N/Aint
2N/Aasr_save_config(asr_handle_t *ah)
2N/A{
2N/A int err = 0;
2N/A char *config = ah->asr_cfg_name;
2N/A boolean_t is_file = asr_cfg_is_file(config);
2N/A
2N/A asr_log_debug(ah, "Saving registration to (%s)", config);
2N/A
2N/A if (config == NULL) {
2N/A err = ASR_FAILURE;
2N/A } else if (is_file) {
2N/A FILE *cfile = fopen(config, "w");
2N/A if (cfile != NULL) {
2N/A err = asr_print_config(ah, cfile);
2N/A err |= fclose(cfile);
2N/A } else
2N/A err = ASR_FAILURE;
2N/A } else {
2N/A nvlist_t *old = asr_nvl_alloc();
2N/A nvlist_t *cfg = asr_get_config(ah);
2N/A if (old == NULL ||
2N/A asr_scf_load(config, old) != 0 ||
2N/A asr_scf_set_props(config, "reg", cfg, old) != 0)
2N/A err = ASR_FAILURE;
2N/A if (old != NULL)
2N/A nvlist_free(old);
2N/A }
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Initializes the ASR handle with the given configuration. If there is an
2N/A * error then NULL is returned and asr_errno is set.
2N/A */
2N/Aasr_handle_t *
2N/Aasr_hdl_initnv(nvlist_t *cfg, char *cfg_name)
2N/A{
2N/A char info[256];
2N/A asr_handle_t *ah;
2N/A
2N/A if (cfg == NULL) {
2N/A cfg = asr_nvl_alloc();
2N/A if (cfg == NULL)
2N/A return (NULL);
2N/A }
2N/A if ((ah = asr_zalloc(sizeof (asr_handle_t))) == NULL) {
2N/A asr_nvl_free(cfg);
2N/A return (NULL);
2N/A }
2N/A ah->asr_cfg = cfg;
2N/A if (asr_set_config_name(ah, cfg_name) != ASR_OK) {
2N/A asr_hdl_destroy(ah);
2N/A return (NULL);
2N/A }
2N/A ah->asr_debug = asr_getprop_bool(ah, ASR_PROP_DEBUG, B_FALSE);
2N/A
2N/A if (sysinfo(SI_HOSTNAME, info, sizeof (info)) == -1 ||
2N/A (ah->asr_host_id = asr_strdup(info)) == NULL) {
2N/A (void) asr_error(EASR_UNKNOWN, "System error (%s)",
2N/A strerror(errno));
2N/A asr_hdl_destroy(ah);
2N/A ah = NULL;
2N/A }
2N/A
2N/A return (ah);
2N/A}
2N/A
2N/A/*
2N/A * Creates an ASR handle from either a file path name or a service
2N/A * FMRI that has ASR properties defined.
2N/A * NULL is returned and asr_errno is set if there is an error.
2N/A */
2N/Aasr_handle_t *
2N/Aasr_hdl_init(char *config)
2N/A{
2N/A boolean_t is_file = asr_cfg_is_file(config);
2N/A nvlist_t *nvcfg;
2N/A
2N/A if ((nvcfg = asr_nvl_alloc()) == NULL)
2N/A return (NULL);
2N/A
2N/A if (config == NULL)
2N/A return (asr_hdl_initnv(NULL, NULL));
2N/A
2N/A if (is_file) {
2N/A FILE *in = fopen(config, "r");
2N/A if (in == NULL ||
2N/A asr_nvl_read_properties(in, nvcfg) != 0) {
2N/A asr_nvl_free(nvcfg);
2N/A return (NULL);
2N/A }
2N/A (void) fclose(in);
2N/A } else {
2N/A if (asr_scf_load(config, nvcfg) != 0) {
2N/A asr_nvl_free(nvcfg);
2N/A return (NULL);
2N/A }
2N/A }
2N/A return (asr_hdl_initnv(nvcfg, config));
2N/A}
2N/A
2N/A/*
2N/A * Creates an empty registration request structure used for registering a
2N/A * client with ASR.
2N/A */
2N/Aasr_regreq_t *
2N/Aasr_regreq_init()
2N/A{
2N/A asr_regreq_t *regreq = asr_zalloc(sizeof (asr_regreq_t));
2N/A if ((regreq->asr_regcfg = asr_nvl_alloc()) == NULL) {
2N/A free(regreq);
2N/A regreq = NULL;
2N/A }
2N/A return (regreq);
2N/A}
2N/A
2N/A/*
2N/A * Sets the registration transport endpoint which is an optional field.
2N/A */
2N/Aint
2N/Aasr_regreq_set_endpoint(asr_regreq_t *regreq, const char *endpoint)
2N/A{
2N/A if (regreq == NULL) {
2N/A (void) asr_set_errno(EASR_NULLDATA);
2N/A return (ASR_FAILURE);
2N/A }
2N/A if (endpoint == NULL)
2N/A (void) nvlist_remove_all(
2N/A regreq->asr_regcfg, ASR_PROP_AREG_HUB_ENDPOINT);
2N/A else if (asr_nvl_add_str(
2N/A regreq->asr_regcfg, ASR_PROP_AREG_HUB_ENDPOINT, endpoint) != 0)
2N/A return (ASR_FAILURE);
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Sets the registration user name which is a required field.
2N/A */
2N/Aint
2N/Aasr_regreq_set_user(asr_regreq_t *regreq, const char *user)
2N/A{
2N/A if (regreq == NULL || user == NULL) {
2N/A (void) asr_set_errno(EASR_NULLDATA);
2N/A return (ASR_FAILURE);
2N/A }
2N/A if (asr_nvl_add_str(regreq->asr_regcfg, ASR_PROP_AREG_USER, user) != 0)
2N/A return (ASR_FAILURE);
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Sets the registration users credential which is a required field.
2N/A */
2N/Aint
2N/Aasr_regreq_set_password(asr_regreq_t *regreq, const char *password)
2N/A{
2N/A if (regreq == NULL || password == NULL) {
2N/A (void) asr_set_errno(EASR_NULLDATA);
2N/A return (ASR_FAILURE);
2N/A }
2N/A if (asr_nvl_add_str(regreq->asr_regcfg, ASR_PROP_AREG_PASS,
2N/A password) != 0)
2N/A return (ASR_FAILURE);
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Sets the registration proxy host:port with optional credentials
2N/A */
2N/Aint
2N/Aasr_regreq_set_proxy(asr_regreq_t *regreq,
2N/A const char *host, const char *user, const char *pass)
2N/A{
2N/A nvlist_t *cfg;
2N/A if (regreq == NULL) {
2N/A (void) asr_set_errno(EASR_NULLDATA);
2N/A return (ASR_FAILURE);
2N/A }
2N/A cfg = regreq->asr_regcfg;
2N/A if (host == NULL) {
2N/A (void) nvlist_remove_all(cfg, ASR_PROP_AREG_PROXY_HOST);
2N/A (void) nvlist_remove_all(cfg, ASR_PROP_AREG_PROXY_USER);
2N/A (void) nvlist_remove_all(cfg, ASR_PROP_AREG_PROXY_PASS);
2N/A return (ASR_OK);
2N/A }
2N/A if (asr_nvl_add_str(cfg, ASR_PROP_AREG_PROXY_HOST, host) != 0)
2N/A return (ASR_FAILURE);
2N/A if (user == NULL)
2N/A (void) asr_nvl_rm_str(cfg, ASR_PROP_AREG_PROXY_USER);
2N/A else if (asr_nvl_add_str(cfg, ASR_PROP_AREG_PROXY_USER, user) != 0)
2N/A return (ASR_FAILURE);
2N/A if (pass == NULL)
2N/A (void) asr_nvl_rm_str(cfg, ASR_PROP_AREG_PROXY_PASS);
2N/A else if (asr_nvl_add_str(cfg, ASR_PROP_AREG_PROXY_PASS, pass) != 0)
2N/A return (ASR_FAILURE);
2N/A
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Gets the transport URL endpoint for an ASR registration request.
2N/A */
2N/Achar *
2N/Aasr_regreq_get_endpoint(const asr_regreq_t *regreq)
2N/A{
2N/A return (asr_nvl_strd(regreq->asr_regcfg, ASR_PROP_AREG_HUB_ENDPOINT,
2N/A NULL));
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Gets the name of the user requesting an ASR registration.
2N/A */
2N/Achar *
2N/Aasr_regreq_get_user(const asr_regreq_t *regreq)
2N/A{
2N/A return (asr_nvl_strd(regreq->asr_regcfg, ASR_PROP_AREG_USER, NULL));
2N/A}
2N/A
2N/A/*
2N/A * Gets the password of the user requesting an ASR registration.
2N/A */
2N/Achar *
2N/Aasr_regreq_get_password(const asr_regreq_t *regreq)
2N/A{
2N/A return (asr_nvl_strd(regreq->asr_regcfg, ASR_PROP_AREG_PASS, NULL));
2N/A}
2N/A
2N/Aint
2N/Aasr_regreq_get_proxy(const asr_regreq_t *regreq,
2N/A char **host, char **user, char **pass)
2N/A{
2N/A nvlist_t *cfg;
2N/A if (regreq == NULL || (cfg = regreq->asr_regcfg) == NULL) {
2N/A (void) asr_set_errno(EASR_NULLDATA);
2N/A return (ASR_FAILURE);
2N/A }
2N/A *host = asr_nvl_strd(cfg, ASR_PROP_AREG_PROXY_HOST, NULL);
2N/A *user = asr_nvl_strd(cfg, ASR_PROP_AREG_PROXY_USER, NULL);
2N/A *pass = asr_nvl_strd(cfg, ASR_PROP_AREG_PROXY_PASS, NULL);
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Frees up all resources used for a registration request.
2N/A */
2N/Avoid
2N/Aasr_regreq_destroy(asr_regreq_t *regreq)
2N/A{
2N/A if (regreq != NULL) {
2N/A asr_nvl_free(regreq->asr_regcfg);
2N/A free(regreq);
2N/A }
2N/A}
2N/A
2N/Astatic void asr_tprt_destroy(asr_transport_t *tprt)
2N/A{
2N/A if (tprt == NULL)
2N/A return;
2N/A if (tprt->asr_tprt_name != NULL)
2N/A free(tprt->asr_tprt_name);
2N/A free(tprt);
2N/A}
2N/A
2N/A/*
2N/A * Initializes the transport functions needed to transmit ASR messages.
2N/A */
2N/Aint
2N/Aasr_set_transport(asr_handle_t *ah, char *name,
2N/A int (*asr_register_client)(
2N/A asr_handle_t *ah, const asr_regreq_t *req, nvlist_t *rsp),
2N/A int (*asr_unregister_client)(asr_handle_t *ah),
2N/A int (*asr_send_msg)(
2N/A asr_handle_t *ah, const asr_message_t *msg, nvlist_t *rsp))
2N/A{
2N/A asr_transport_t *tprt = NULL;
2N/A
2N/A tprt = asr_zalloc(sizeof (asr_transport_t));
2N/A if (tprt == NULL)
2N/A return (ASR_FAILURE);
2N/A tprt->asr_register_client = asr_register_client;
2N/A tprt->asr_unregister_client = asr_unregister_client;
2N/A tprt->asr_send_msg = asr_send_msg;
2N/A tprt->asr_tprt_name = asr_strdup(name);
2N/A asr_tprt_destroy(ah->asr_tprt);
2N/A ah->asr_tprt = tprt;
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Cleans up the ASR handle when done.
2N/A */
2N/Avoid
2N/Aasr_hdl_destroy(asr_handle_t *ah)
2N/A{
2N/A if (ah != NULL) {
2N/A if (ah->asr_cfg != NULL) {
2N/A nvlist_free(ah->asr_cfg);
2N/A ah->asr_cfg = NULL;
2N/A }
2N/A if (ah->asr_log != NULL) {
2N/A if (ah->asr_log != stdout && ah->asr_log != stderr)
2N/A (void) fclose(ah->asr_log);
2N/A ah->asr_log = NULL;
2N/A }
2N/A asr_tprt_destroy(ah->asr_tprt);
2N/A if (ah->asr_cfg_name != NULL)
2N/A free(ah->asr_cfg_name);
2N/A if (ah->asr_host_id != NULL)
2N/A free(ah->asr_host_id);
2N/A free(ah);
2N/A } else {
2N/A (void) asr_set_errno(EASR_NULLFREE);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Cleans up all cached data inside the ASR library.
2N/A */
2N/Avoid
2N/Aasr_cleanup()
2N/A{
2N/A (void) pthread_mutex_lock(&asr_sysprops_lock);
2N/A if (asr_sysprops != NULL) {
2N/A asr_nvl_free(asr_sysprops);
2N/A asr_sysprops = NULL;
2N/A }
2N/A (void) pthread_mutex_unlock(&asr_sysprops_lock);
2N/A}
2N/A
2N/A/*
2N/A * Cleans up an ASR message and its contents.
2N/A */
2N/Avoid
2N/Aasr_free_msg(asr_message_t *msg)
2N/A{
2N/A if (msg != NULL) {
2N/A if (msg->asr_msg_data != NULL)
2N/A free(msg->asr_msg_data);
2N/A free(msg);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Converts a new ASR message from a buffer and the given type.
2N/A * Returns NULL and frees data if there is an error.
2N/A */
2N/Aasr_message_t *
2N/Aasr_message_alloc(asr_buf_t *data, asr_msgtype_t type)
2N/A{
2N/A asr_message_t *msg;
2N/A
2N/A if ((msg = asr_zalloc(sizeof (asr_message_t))) == NULL) {
2N/A asr_buf_free(data);
2N/A return (NULL);
2N/A }
2N/A msg->asr_msg_type = type;
2N/A msg->asr_msg_len = data->asrb_length;
2N/A msg->asr_msg_data = asr_buf_free_struct(data);
2N/A
2N/A return (msg);
2N/A}
2N/A
2N/A/*
2N/A * Saves the registration properties into the ASR handle for all future
2N/A * message transmission on that handle.
2N/A * The name value properties are from a previous call to asr_reg
2N/A * Returns non-zero on error.
2N/A */
2N/Astatic int
2N/Aasr_reg_save(asr_handle_t *ah, nvlist_t *reg)
2N/A{
2N/A int i, err = 0;
2N/A nvlist_t *cfg = ah->asr_cfg;
2N/A char *r, *val;
2N/A
2N/A for (i = 0; (r = asr_reg_props[i]) != NULL && err == 0; i++) {
2N/A if (nvlist_lookup_string(reg, r, &val) == 0)
2N/A err = nvlist_add_string(cfg, r, val);
2N/A else
2N/A (void) nvlist_remove_all(cfg, r);
2N/A }
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Fills in the registration response properties taken from the users
2N/A * registration request structure and system information.
2N/A * Returns ASR_FAILURE if there is an error or ASR_OK if successful.
2N/A */
2N/Aint
2N/Aasr_reg_fill(asr_handle_t *ah, const asr_regreq_t *regreq, nvlist_t *reg)
2N/A{
2N/A int err = ASR_OK;
2N/A
2N/A err = asr_nvl_add_str(reg, ASR_PROP_SYSTEM_ID, asr_get_systemid(ah));
2N/A err |= asr_nvl_add_str(reg, ASR_PROP_PRODUCT_ID, asr_get_productid(ah));
2N/A err |= asr_nvl_add_str(reg, ASR_PROP_PRODUCT_NAME,
2N/A asr_get_product_name(ah));
2N/A err |= asr_nvl_add_str(reg, ASR_PROP_REG_USER_ID,
2N/A asr_regreq_get_user(regreq));
2N/A
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Registers the ASR client and saves the configuration if successful
2N/A * to the ASR handle properties.
2N/A * Returns non-zero if there is an error.
2N/A */
2N/Aint
2N/Aasr_reg(asr_handle_t *ah, asr_regreq_t *request, nvlist_t **out_rsp)
2N/A{
2N/A int err = 0;
2N/A nvlist_t *rsp = NULL;
2N/A char *index;
2N/A
2N/A if ((rsp = asr_nvl_alloc()) == NULL) {
2N/A *out_rsp = NULL;
2N/A (void) asr_set_errno(EASR_NOMEM);
2N/A return (ASR_FAILURE);
2N/A }
2N/A
2N/A if ((index = asr_getprop_strd(ah, ASR_PROP_REG_INDEX, NULL)) != NULL)
2N/A if (nvlist_add_string(rsp, ASR_PROP_REG_INDEX, index) != 0)
2N/A return (ASR_FAILURE);
2N/A
2N/A if (ah->asr_tprt != NULL && ah->asr_tprt->asr_register_client != NULL)
2N/A err = ah->asr_tprt->asr_register_client(ah, request, rsp);
2N/A else
2N/A err = asr_error(EASR_PROP_USAGE, "Transport not defined.");
2N/A
2N/A if (err != 0) {
2N/A asr_nvl_free(rsp);
2N/A rsp = NULL;
2N/A } else {
2N/A char *msg = asr_nvl_str(rsp, ASR_PROP_REG_MESSAGE);
2N/A if (msg == NULL || msg[0] == '\0') {
2N/A char time[80];
2N/A asr_time(time, sizeof (time));
2N/A (void) asr_nvl_add_strf(rsp, ASR_PROP_REG_MESSAGE,
2N/A "Registered %s", time);
2N/A }
2N/A err = asr_reg_save(ah, rsp);
2N/A }
2N/A *out_rsp = rsp;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Resets all ASR registration properties
2N/A */
2N/Aint
2N/Aasr_unconfigure(asr_handle_t *ah)
2N/A{
2N/A int i;
2N/A char *r;
2N/A nvlist_t *cfg = ah->asr_cfg;
2N/A for (i = 0; (r = asr_reg_props[i]) != NULL; i++) {
2N/A (void) nvlist_remove_all(cfg, r);
2N/A }
2N/A return (ASR_OK);
2N/A}
2N/A
2N/A/*
2N/A * Deactivates and unregisters ASR for this system.
2N/A */
2N/Aint
2N/Aasr_unreg(asr_handle_t *ah)
2N/A{
2N/A int err = 0;
2N/A char *regid = asr_get_regid(ah);
2N/A char *status = asr_getprop_str(ah, ASR_PROP_REG_STATUS);
2N/A
2N/A if (regid == NULL)
2N/A return (0); /* Already unreg'ed */
2N/A
2N/A if ((status == NULL ||
2N/A strcmp(status, ASR_REG_STATUS_REGISTERED) == 0) &&
2N/A ah->asr_tprt != NULL && ah->asr_tprt->asr_unregister_client != NULL)
2N/A err = ah->asr_tprt->asr_unregister_client(ah);
2N/A
2N/A if (err == 0)
2N/A err = asr_unconfigure(ah);
2N/A
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Sends the given telemetry data. If the message isn't already signed
2N/A * then the signature will be created.
2N/A * The output nvlist will have to be freed by the caller even if an error is
2N/A * returned since error properties can be returned in out_rsp.
2N/A */
2N/Aint
2N/Aasr_send_msg(asr_handle_t *ah, const asr_message_t *msg, nvlist_t **out_rsp)
2N/A{
2N/A int err = 0;
2N/A nvlist_t *rsp = NULL;
2N/A
2N/A if ((rsp = asr_nvl_alloc()) == NULL)
2N/A return (ASR_FAILURE);
2N/A
2N/A if (ah->asr_tprt != NULL && ah->asr_tprt->asr_send_msg != NULL)
2N/A err = ah->asr_tprt->asr_send_msg(ah, msg, rsp);
2N/A
2N/A if (out_rsp != NULL)
2N/A *out_rsp = rsp;
2N/A else if (rsp != NULL)
2N/A nvlist_free(rsp);
2N/A
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Creates an name value list containing ASR common message header properties.
2N/A */
2N/Aint
2N/Aasr_msg_start(asr_handle_t *ah, asr_buf_t *buf)
2N/A{
2N/A char timebuf[64];
2N/A return (asr_msg_tstart(ah, buf, timebuf, sizeof (timebuf)));
2N/A}
2N/A
2N/Achar *
2N/Aasr_get_schema(asr_handle_t *ah)
2N/A{
2N/A return (asr_getprop_strd(
2N/A ah, ASR_PROP_SCHEMA_VERSION, ASR_SCHEMA_VERSION));
2N/A}
2N/A
2N/Aboolean_t
2N/Aasr_use_schema_2_1(asr_handle_t *ah)
2N/A{
2N/A boolean_t use21 = B_FALSE;
2N/A char *schema = asr_get_schema(ah);
2N/A if (strcmp(ASR_SCHEMA_VERSION_2_1, schema) == 0)
2N/A use21 = B_TRUE;
2N/A return (use21);
2N/A}
2N/A
2N/A/*
2N/A * Creates an name value list containing ASR common message header properties
2N/A * and sets the time of the message in the supplied time buffer.
2N/A */
2N/Aint
2N/Aasr_msg_tstart(asr_handle_t *ah, asr_buf_t *buf, char *timebuf, size_t tlen)
2N/A{
2N/A int err = 0;
2N/A uuid_t uuid;
2N/A time_t now;
2N/A struct tm *gmnow;
2N/A char *asset_id, *site_id, *system_id, *product_name, *product_id;
2N/A char uuidbuf[UUID_PRINTABLE_STRING_LENGTH];
2N/A boolean_t use_schema_2_1 = asr_use_schema_2_1(ah);
2N/A
2N/A if ((asset_id = asr_get_assetid(ah)) == NULL)
2N/A return (asr_error(EASR_PROP_NOPROP, "Property %s not set",
2N/A ASR_PROP_ASSET_ID));
2N/A
2N/A if ((system_id = asr_get_systemid(ah)) == NULL)
2N/A return (asr_error(EASR_PROP_NOPROP,
2N/A "failed to get system serial number"));
2N/A site_id = asr_get_siteid(ah);
2N/A product_name = asr_get_product_name(ah);
2N/A product_id = asr_get_productid(ah);
2N/A if (product_name == NULL || product_id == NULL)
2N/A return (asr_error(EASR_PROP_NOPROP,
2N/A "failed to get product information"));
2N/A
2N/A
2N/A (void) strcpy(uuidbuf, "0");
2N/A uuid_generate(uuid);
2N/A uuid_unparse(uuid, uuidbuf);
2N/A
2N/A (void) time(&now);
2N/A gmnow = gmtime(&now);
2N/A (void) strftime(timebuf, tlen, "%FT%T", gmnow);
2N/A
2N/A err = asr_buf_append_str(buf,
2N/A "<?xml version='1.0' encoding='UTF-8'?>\n");
2N/A err |= asr_buf_append_str(buf,
2N/A "<message xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n");
2N/A if (use_schema_2_1) {
2N/A err |= asr_buf_append_str(buf,
2N/A " xsi:noNamespaceSchemaLocation='message_21.xsd'>\n");
2N/A } else {
2N/A err |= asr_buf_append_str(buf,
2N/A " xsi:noNamespaceSchemaLocation='message_20.xsd'>\n");
2N/A }
2N/A err |= asr_buf_append_xml_nv(buf, 1, "site-id", site_id);
2N/A err |= asr_buf_append_xml_nv(buf, 1, "host-id", ah->asr_host_id);
2N/A err |= asr_buf_append_xml_nvtoken(buf, 1, "message-uuid", uuidbuf);
2N/A err |= asr_buf_append_xml_anv(buf, 1,
2N/A "timezone", "UTC", "message-time", timebuf);
2N/A err |= asr_buf_append_xml_nvtoken(buf, 1, "system-id", system_id);
2N/A if (use_schema_2_1) {
2N/A char info[80];
2N/A if (sysinfo(SI_HOSTNAME, info, sizeof (info)) > 0)
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, 1, "system-name", info);
2N/A if (sysinfo(SI_RELEASE, info, sizeof (info)) > 0) {
2N/A int ilen = strlen(info);
2N/A int freelen = sizeof (info) - ilen;
2N/A if (freelen > 1) {
2N/A info[ilen++] = ' ';
2N/A if (sysinfo(SI_VERSION,
2N/A info + ilen, freelen - 1) > 0)
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, 1, "system-version", info);
2N/A }
2N/A }
2N/A }
2N/A err |= asr_buf_append_xml_nvtoken(buf, 1, "asset-id", asset_id);
2N/A err |= asr_buf_append_xml_nvtoken(buf, 1, "product-id", product_id);
2N/A err |= asr_buf_append_xml_nv(buf, 1, "product-name", product_name);
2N/A if (use_schema_2_1) {
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, 1, "schema-version", asr_get_schema(ah));
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, 1, "client-name", ASR_CLIENT_NAME);
2N/A err |= asr_buf_append_xml_nv(
2N/A buf, 1, "client-version", ASR_CLIENT_VERSION);
2N/A }
2N/A return (err);
2N/A}
2N/A
2N/Aint
2N/Aasr_msg_end(asr_buf_t *msg)
2N/A{
2N/A int err = 0;
2N/A err |= asr_buf_append_xml_ai(msg, 1, "telemetry_source",
2N/A ASR_TELEMETRY_SOURCE);
2N/A err |= asr_buf_append_xml_ai(msg, 1, "receiver_id", ASR_RECEIVER_ID);
2N/A err |= asr_buf_append_xml_ai(msg, 1, "client-name", ASR_CLIENT_NAME);
2N/A err |= asr_buf_append_xml_ai(msg, 1, "client-version",
2N/A ASR_CLIENT_VERSION);
2N/A err |= asr_buf_append_xml_ainvl(msg, 1, asr_sysprops);
2N/A err |= asr_buf_append_xml_end(msg, 0, "message");
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Creates an ASR activation message.
2N/A */
2N/Aint
2N/Aasr_activate(asr_handle_t *ah, asr_message_t **out_msg)
2N/A{
2N/A int err;
2N/A asr_message_t *msg = NULL;
2N/A int pad = 1;
2N/A char *na = "NA";
2N/A char *user = asr_getprop_strd(ah, ASR_PROP_REG_USER_ID,
2N/A ASR_ANONYMOUS_USER);
2N/A asr_buf_t *buf = asr_buf_alloc(ASR_ACTIVATE_BUFSIZE);
2N/A
2N/A if (buf == NULL)
2N/A return (asr_set_errno(EASR_NOMEM));
2N/A
2N/A err = asr_msg_start(ah, buf);
2N/A err |= asr_buf_append_xml_elem(buf, pad, "monitoring-activation");
2N/A pad++;
2N/A err |= asr_buf_append_xml_elem(buf, pad, "activation-user");
2N/A pad++;
2N/A err |= asr_buf_append_xml_nv(buf, pad, "company", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "email", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "first-name", user);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "last-name", user);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "organization", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "phone", na);
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "activation-user");
2N/A err |= asr_buf_append_xml_elem(buf, pad, "site-address");
2N/A pad++;
2N/A err |= asr_buf_append_xml_nv(buf, pad, "line", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "company", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "city", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "state", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "postal-code", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "country", na);
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "site-address");
2N/A err |= asr_buf_append_xml_elem(buf, pad, "contact");
2N/A pad++;
2N/A err |= asr_buf_append_xml_nv(buf, pad, "company", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "email", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "first-name", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "last-name", na);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "phone", na);
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "contact");
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "monitoring-activation");
2N/A err |= asr_msg_end(buf);
2N/A
2N/A if (err == 0) {
2N/A if ((msg = asr_message_alloc(buf, ASR_MSG_ACTIVATE)) == NULL)
2N/A err = EASR_NOMEM;
2N/A } else {
2N/A asr_buf_free(buf);
2N/A }
2N/A *out_msg = msg;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Creates an ASR deactivation message. This message gets sent if registration
2N/A * is cleared and ASR should be turned off for the system.
2N/A */
2N/Aint
2N/Aasr_deactivate(asr_handle_t *ah, asr_message_t **out_msg)
2N/A{
2N/A int err;
2N/A asr_message_t *msg = NULL;
2N/A asr_buf_t *buf = asr_buf_alloc(1024);
2N/A
2N/A if (buf == NULL)
2N/A return (asr_set_errno(EASR_NOMEM));
2N/A
2N/A err = asr_msg_start(ah, buf);
2N/A err |= asr_buf_append_xml_nv(buf, 1, "monitoring-deactivation", "");
2N/A err |= asr_msg_end(buf);
2N/A
2N/A if (err == 0) {
2N/A msg = asr_message_alloc(buf, ASR_MSG_DEACTIVATE);
2N/A if (msg == NULL) {
2N/A err = EASR_NOMEM;
2N/A }
2N/A } else {
2N/A asr_buf_free(buf);
2N/A }
2N/A *out_msg = msg;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Creates and ASR heartbeat message.
2N/A */
2N/Aint
2N/Aasr_heartbeat(asr_handle_t *ah, asr_message_t **out_msg)
2N/A{
2N/A int err;
2N/A asr_message_t *msg = NULL;
2N/A char time[64];
2N/A asr_buf_t *buf = asr_buf_alloc(1024);
2N/A
2N/A if (buf == NULL)
2N/A return (asr_set_errno(EASR_NOMEM));
2N/A
2N/A err = asr_msg_tstart(ah, buf, time, sizeof (time));
2N/A err |= asr_buf_append_xml_elem(buf, 1, "heartbeat");
2N/A err |= asr_buf_append_xml_anv(buf, 2, "timezone", "UTC", "time", time);
2N/A err |= asr_buf_append_xml_end(buf, 1, "heartbeat");
2N/A err |= asr_msg_end(buf);
2N/A
2N/A if (err == 0) {
2N/A if ((msg = asr_message_alloc(buf, ASR_MSG_HEARTBEAT)) == NULL)
2N/A err = EASR_NOMEM;
2N/A } else {
2N/A asr_buf_free(buf);
2N/A }
2N/A *out_msg = msg;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Creates an ASR test message that simulates a fault on the back end and
2N/A * sends an email to the given address.
2N/A */
2N/Aint
2N/Aasr_test(asr_handle_t *ah, char *email, asr_message_t **out_msg)
2N/A{
2N/A int err = 0;
2N/A asr_message_t *msg = NULL;
2N/A int pad = 1;
2N/A asr_buf_t *mailto, *buf;
2N/A uuid_t uuid;
2N/A char uuidbuf[UUID_PRINTABLE_STRING_LENGTH];
2N/A char time[64];
2N/A
2N/A *out_msg = NULL;
2N/A if (email == NULL || email[0] == '\0')
2N/A return (asr_set_errno(EASR_PROP_USAGE));
2N/A
2N/A if ((mailto = asr_buf_alloc(8+strlen(email))) == NULL)
2N/A return (ASR_FAILURE);
2N/A if (asr_buf_append(mailto, "mailto:%s", email) != 0) {
2N/A asr_buf_free(mailto);
2N/A return (ASR_FAILURE);
2N/A }
2N/A
2N/A (void) strcpy(uuidbuf, "0");
2N/A uuid_generate(uuid);
2N/A uuid_unparse(uuid, uuidbuf);
2N/A
2N/A if ((buf = asr_buf_alloc(1280)) == NULL)
2N/A return (asr_set_errno(EASR_NOMEM));
2N/A
2N/A err |= asr_msg_tstart(ah, buf, time, sizeof (time));
2N/A err |= asr_buf_append_xml_elem(buf, pad, "event");
2N/A pad++;
2N/A err |= asr_buf_append_xml_elem(buf, pad, "primary-event-information");
2N/A pad++;
2N/A err |= asr_buf_append_xml_nv(buf, pad, "message-id", "TESTCREATE");
2N/A err |= asr_buf_append_xml_nv(buf, pad, "event-uuid", uuidbuf);
2N/A err |= asr_buf_append_xml_anv(buf, pad,
2N/A "timezone", "UTC", "event-time", time);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "severity", "Minor");
2N/A err |= asr_buf_append_xml_elem(buf, pad, "component");
2N/A err |= asr_buf_append_xml_nv(buf, pad+1, "uncategorized", "");
2N/A err |= asr_buf_append_xml_end(buf, pad, "component");
2N/A err |= asr_buf_append_xml_nv(buf, pad, "summary", asr_buf_data(mailto));
2N/A err |= asr_buf_append_xml_nv(buf, pad, "description",
2N/A "Test Message Used for Testing End to End Connection");
2N/A err |= asr_buf_append_xml_nv(buf, pad, "required-action", "None");
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "primary-event-information");
2N/A
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "event");
2N/A err |= asr_msg_end(buf);
2N/A
2N/A if (err == 0) {
2N/A if ((msg = asr_message_alloc(buf, ASR_MSG_TEST)) == NULL)
2N/A err = EASR_NOMEM;
2N/A } else {
2N/A asr_buf_free(buf);
2N/A }
2N/A asr_buf_free(mailto);
2N/A *out_msg = msg;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Creates a message that can get the activation status of the devices for
2N/A * ASR monitoring validation
2N/A */
2N/Aint
2N/Aasr_status(asr_handle_t *ah, char *method, asr_message_t **out_msg)
2N/A{
2N/A int err;
2N/A int pad = 1;
2N/A asr_message_t *msg = NULL;
2N/A char *user, *serial, *host;
2N/A asr_buf_t *buf = asr_buf_alloc(1024);
2N/A
2N/A if (buf == NULL)
2N/A return (asr_set_errno(EASR_NOMEM));
2N/A
2N/A user = asr_getprop_strd(ah, ASR_PROP_REG_USER_ID, ASR_ANONYMOUS_USER);
2N/A serial = asr_getprop_str(ah, ASR_PROP_REG_SYSTEM_ID);
2N/A host = ah->asr_host_id;
2N/A
2N/A err = asr_msg_start(ah, buf);
2N/A err |= asr_buf_append_xml_elem(buf, pad, "asr-status");
2N/A pad++;
2N/A err |= asr_buf_append_xml_nv(buf, pad, "soa_username", user);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "method", method);
2N/A err |= asr_buf_append_xml_elem(buf, pad, "device");
2N/A pad++;
2N/A err |= asr_buf_append_xml_nv(buf, pad, "serial-number", serial);
2N/A err |= asr_buf_append_xml_nv(buf, pad, "host-name", host);
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "device");
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "asr-status");
2N/A err |= asr_msg_end(buf);
2N/A
2N/A if (err == 0) {
2N/A if ((msg = asr_message_alloc(buf, ASR_MSG_STATUS)) == NULL)
2N/A err = EASR_NOMEM;
2N/A } else {
2N/A asr_buf_free(buf);
2N/A }
2N/A *out_msg = msg;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Creates a message that identifies a proactive change to the device state.
2N/A * This may have an impact on how Sun views the device.
2N/A * This is used for putting a device into maintenance mode and telling Sun that
2N/A * a device will go offline (implying it will not send heartbeats for the time
2N/A * being).
2N/A */
2N/Aint
2N/Aasr_state_change(asr_handle_t *ah, boolean_t online, boolean_t maintenance,
2N/A asr_message_t **out_msg)
2N/A{
2N/A int err;
2N/A int pad = 1;
2N/A asr_message_t *msg = NULL;
2N/A asr_buf_t *buf = asr_buf_alloc(1024);
2N/A
2N/A if (buf == NULL)
2N/A return (asr_set_errno(EASR_NOMEM));
2N/A
2N/A err = asr_msg_start(ah, buf);
2N/A err |= asr_buf_append_xml_elem(buf, pad, "state-change");
2N/A pad++;
2N/A err |= asr_buf_append_xml_nb(buf, pad, "online", online);
2N/A err |= asr_buf_append_xml_nb(buf, pad, "maintenance", maintenance);
2N/A pad--;
2N/A err |= asr_buf_append_xml_end(buf, pad, "state-change");
2N/A err |= asr_msg_end(buf);
2N/A
2N/A if (err == 0) {
2N/A if ((msg = asr_message_alloc(buf, ASR_MSG_STATUS)) == NULL)
2N/A err = EASR_NOMEM;
2N/A } else {
2N/A asr_buf_free(buf);
2N/A }
2N/A *out_msg = msg;
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Internal ASR logging. Logs debug messages, warnings and errors to the
2N/A * configured ASR log file.
2N/A */
2N/Astatic void
2N/Aasr_log(asr_handle_t *ah, const char *level, const char *message)
2N/A{
2N/A FILE *logfile = ah->asr_log;
2N/A char timebuf[80];
2N/A
2N/A if (logfile == NULL)
2N/A logfile = stderr;
2N/A
2N/A asr_time(timebuf, sizeof (timebuf));
2N/A (void) fprintf(logfile, "[ %s %s ] %s\n", level, timebuf, message);
2N/A}
2N/A
2N/A/*
2N/A * Variable arg version of the internal ASR logger.
2N/A */
2N/A/* PRINTFLIKE3 */
2N/Astatic int
2N/Aasr_vlog(asr_handle_t *ah, char *level, char *fmt, va_list ap)
2N/A{
2N/A int err = 0;
2N/A char timebuf[80];
2N/A
2N/A if (ah == NULL || ah->asr_log == NULL)
2N/A return (ASR_FAILURE);
2N/A
2N/A asr_time(timebuf, sizeof (timebuf));
2N/A if (fprintf(ah->asr_log, "[ %s %s ] ", level, timebuf) < 0 ||
2N/A vfprintf(ah->asr_log, fmt, ap) < 0 ||
2N/A fprintf(ah->asr_log, "\n") < 0)
2N/A err = -1;
2N/A
2N/A return (err);
2N/A}
2N/A
2N/A/*
2N/A * Logs the ASR error. If there is no internal error state this function
2N/A * does nothing.
2N/A */
2N/Avoid
2N/Aasr_log_err(asr_handle_t *ah)
2N/A{
2N/A if (asr_get_errno())
2N/A asr_log(ah, "ERROR", asr_errmsg());
2N/A}
2N/A
2N/A/*
2N/A * Sets the ASR errno and log the error.
2N/A */
2N/Avoid
2N/Aasr_log_errno(asr_handle_t *ah, asr_err_t err)
2N/A{
2N/A (void) asr_set_errno(err);
2N/A asr_log(ah, "ERROR", asr_errmsg());
2N/A}
2N/A
2N/A/*
2N/A * Logs the ASR error with the given errno and message.
2N/A */
2N/Avoid
2N/Aasr_log_error(asr_handle_t *ah, asr_err_t err, char *fmt, ...)
2N/A{
2N/A va_list ap;
2N/A
2N/A va_start(ap, fmt);
2N/A (void) asr_verror(err, fmt, ap);
2N/A va_end(ap);
2N/A asr_log(ah, "ERROR", asr_errmsg());
2N/A}
2N/A
2N/A/*
2N/A * Logs a warning to the ASR log.
2N/A */
2N/Avoid
2N/Aasr_log_warn(asr_handle_t *ah, char *fmt, ...)
2N/A{
2N/A va_list ap;
2N/A va_start(ap, fmt);
2N/A (void) asr_vlog(ah, "WARNING", fmt, ap);
2N/A va_end(ap);
2N/A}
2N/A
2N/A/*
2N/A * Logs an informational message to the ASR log.
2N/A */
2N/Avoid
2N/Aasr_log_info(asr_handle_t *ah, char *fmt, ...)
2N/A{
2N/A va_list ap;
2N/A va_start(ap, fmt);
2N/A (void) asr_vlog(ah, "INFO", fmt, ap);
2N/A va_end(ap);
2N/A}
2N/A
2N/A/*
2N/A * Logs a debug message to the ASR log.
2N/A */
2N/Avoid
2N/Aasr_log_debug(asr_handle_t *ah, char *fmt, ...)
2N/A{
2N/A va_list ap;
2N/A if (ah && ah->asr_debug) {
2N/A va_start(ap, fmt);
2N/A (void) asr_vlog(ah, "DEBUG", fmt, ap);
2N/A va_end(ap);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Gets the current ASR debug level.
2N/A */
2N/Aboolean_t
2N/Aasr_get_debug(asr_handle_t *ah)
2N/A{
2N/A return (ah ? ah->asr_debug : B_FALSE);
2N/A}
2N/A
2N/A/*
2N/A * Sets the current ASR debug level.
2N/A */
2N/Avoid
2N/Aasr_set_debug(asr_handle_t *ah, boolean_t debug)
2N/A{
2N/A if (ah != NULL) {
2N/A (void) asr_setprop_str(
2N/A ah, ASR_PROP_DEBUG, debug == B_TRUE ?
2N/A ASR_VALUE_TRUE : ASR_VALUE_FALSE);
2N/A ah->asr_debug = debug;
2N/A }
2N/A}