aboutsummaryrefslogtreecommitdiffstats
path: root/src/libimcv
diff options
context:
space:
mode:
Diffstat (limited to 'src/libimcv')
-rw-r--r--src/libimcv/ietf/ietf_attr_pa_tnc_error.c94
-rw-r--r--src/libimcv/ietf/ietf_attr_remediation_instr.c16
-rw-r--r--src/libimcv/imc/imc_agent.c2
-rw-r--r--src/libimcv/imc/imc_msg.c8
-rw-r--r--src/libimcv/imc/imc_msg.h7
-rw-r--r--src/libimcv/imv/imv_agent.c111
-rw-r--r--src/libimcv/imv/imv_msg.c7
-rw-r--r--src/libimcv/imv/imv_msg.h7
-rw-r--r--src/libimcv/os_info/os_info.c2
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.c12
-rw-r--r--src/libimcv/plugins/imv_os/imv_os.c22
-rw-r--r--src/libimcv/plugins/imv_os/imv_os_state.c19
-rw-r--r--src/libimcv/plugins/imv_os/imv_os_state.h15
13 files changed, 242 insertions, 80 deletions
diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
index f92022fe0..cc3ec28c5 100644
--- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
+++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c
@@ -325,22 +325,12 @@ METHOD(ietf_attr_pa_tnc_error_t, get_offset, u_int32_t,
}
/**
- * Described in header.
+ * Generic constructor
*/
-pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code,
- chunk_t msg_info)
+static private_ietf_attr_pa_tnc_error_t* create_generic()
{
private_ietf_attr_pa_tnc_error_t *this;
- if (error_code.vendor_id == PEN_IETF)
- {
- msg_info.len = PA_ERROR_MSG_INFO_SIZE;
- }
- else if (msg_info.len > PA_ERROR_MSG_INFO_MAX_SIZE)
- {
- msg_info.len = PA_ERROR_MSG_INFO_MAX_SIZE;
- }
-
INIT(this,
.public = {
.pa_tnc_attribute = {
@@ -360,11 +350,33 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code,
.get_offset = _get_offset,
},
.type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
- .error_code = error_code,
- .msg_info = chunk_clone(msg_info),
.ref = 1,
);
+ return this;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code,
+ chunk_t msg_info)
+{
+ private_ietf_attr_pa_tnc_error_t *this;
+
+ if (error_code.vendor_id == PEN_IETF)
+ {
+ msg_info.len = PA_ERROR_MSG_INFO_SIZE;
+ }
+ else if (msg_info.len > PA_ERROR_MSG_INFO_MAX_SIZE)
+ {
+ msg_info.len = PA_ERROR_MSG_INFO_MAX_SIZE;
+ }
+
+ this = create_generic();
+ this->error_code = error_code;
+ this->msg_info = chunk_clone(msg_info);
+
return &this->public.pa_tnc_attribute;
}
@@ -380,30 +392,10 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code,
/* the first 8 bytes of the erroneous PA-TNC message are sent back */
msg_info.len = PA_ERROR_MSG_INFO_SIZE;
- INIT(this,
- .public = {
- .pa_tnc_attribute = {
- .get_type = _get_type,
- .get_value = _get_value,
- .get_noskip_flag = _get_noskip_flag,
- .set_noskip_flag = _set_noskip_flag,
- .build = _build,
- .process = _process,
- .get_ref = _get_ref,
- .destroy = _destroy,
- },
- .get_error_code = _get_error_code,
- .get_msg_info = _get_msg_info,
- .get_attr_info = _get_attr_info,
- .set_attr_info = _set_attr_info,
- .get_offset = _get_offset,
- },
- .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
- .error_code = error_code,
- .msg_info = chunk_clone(msg_info),
- .error_offset = error_offset,
- .ref = 1,
- );
+ this = create_generic();
+ this->error_code = error_code;
+ this->msg_info = chunk_clone(msg_info);
+ this->error_offset = error_offset;
return &this->public.pa_tnc_attribute;
}
@@ -415,30 +407,8 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(chunk_t data)
{
private_ietf_attr_pa_tnc_error_t *this;
- INIT(this,
- .public = {
- .pa_tnc_attribute = {
- .get_type = _get_type,
- .get_value = _get_value,
- .get_noskip_flag = _get_noskip_flag,
- .set_noskip_flag = _set_noskip_flag,
- .build = _build,
- .process = _process,
- .get_ref = _get_ref,
- .destroy = _destroy,
- },
- .get_error_code = _get_error_code,
- .get_msg_info = _get_msg_info,
- .get_attr_info = _get_attr_info,
- .set_attr_info = _set_attr_info,
- .get_offset = _get_offset,
- },
- .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR },
- .value = chunk_clone(data),
- .ref = 1,
- );
+ this = create_generic();
+ this->value = chunk_clone(data);
return &this->public.pa_tnc_attribute;
}
-
-
diff --git a/src/libimcv/ietf/ietf_attr_remediation_instr.c b/src/libimcv/ietf/ietf_attr_remediation_instr.c
index f3b4e83dd..d28631ec7 100644
--- a/src/libimcv/ietf/ietf_attr_remediation_instr.c
+++ b/src/libimcv/ietf/ietf_attr_remediation_instr.c
@@ -194,14 +194,16 @@ METHOD(pa_tnc_attr_t, process, status_t,
DBG1(DBG_TNC, "insufficient data for IETF remediation string");
goto end;
}
+ *offset += 4;
+
pos = memchr(this->string.ptr, '\0', this->string.len);
if (pos)
{
DBG1(DBG_TNC, "nul termination in IETF remediation string");
- *offset += 1 + (pos - this->string.ptr);
+ *offset += (pos - this->string.ptr);
goto end;
}
- *offset += 4 + this->string.len;
+ *offset += this->string.len;
if (!reader->read_data8(reader, &this->lang_code))
{
@@ -246,12 +248,6 @@ METHOD(ietf_attr_remediation_instr_t, get_parameters, chunk_t,
return this->parameters;
}
-METHOD(ietf_attr_remediation_instr_t, get_uri, chunk_t,
- private_ietf_attr_remediation_instr_t *this)
-{
- return this->parameters;
-}
-
METHOD(ietf_attr_remediation_instr_t, get_string, chunk_t,
private_ietf_attr_remediation_instr_t *this, chunk_t *lang_code)
{
@@ -284,7 +280,7 @@ pa_tnc_attr_t *ietf_attr_remediation_instr_create(pen_type_t parameters_type,
},
.get_parameters_type = _get_parameters_type,
.get_parameters = _get_parameters,
- .get_uri = _get_uri,
+ .get_uri = _get_parameters,
.get_string = _get_string,
},
.type = { PEN_IETF, IETF_ATTR_REMEDIATION_INSTRUCTIONS },
@@ -350,7 +346,7 @@ pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_data(chunk_t data)
},
.get_parameters_type = _get_parameters_type,
.get_parameters = _get_parameters,
- .get_uri = _get_uri,
+ .get_uri = _get_parameters,
.get_string = _get_string,
},
.type = { PEN_IETF, IETF_ATTR_REMEDIATION_INSTRUCTIONS },
diff --git a/src/libimcv/imc/imc_agent.c b/src/libimcv/imc/imc_agent.c
index 161623477..f309abe74 100644
--- a/src/libimcv/imc/imc_agent.c
+++ b/src/libimcv/imc/imc_agent.c
@@ -190,8 +190,6 @@ METHOD(imc_agent_t, bind_functions, TNC_Result,
{
this->reserve_additional_id = NULL;
}
- DBG2(DBG_IMC, "IMC %u \"%s\" provided with bind function",
- this->id, this->name);
if (this->report_message_types_long)
{
diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c
index 050e63f32..1fc3d3be5 100644
--- a/src/libimcv/imc/imc_msg.c
+++ b/src/libimcv/imc/imc_msg.c
@@ -91,6 +91,12 @@ METHOD(imc_msg_t, get_dst_id, TNC_UInt32,
return this->dst_id;
}
+METHOD(imc_msg_t, get_msg_type, pen_type_t,
+ private_imc_msg_t *this)
+{
+ return this->msg_type;
+}
+
METHOD(imc_msg_t, send_, TNC_Result,
private_imc_msg_t *this, bool excl)
{
@@ -380,6 +386,7 @@ imc_msg_t *imc_msg_create(imc_agent_t *agent, imc_state_t *state,
.public = {
.get_src_id = _get_src_id,
.get_dst_id = _get_dst_id,
+ .get_msg_type = _get_msg_type,
.send = _send_,
.receive = _receive,
.add_attribute = _add_attribute,
@@ -454,4 +461,3 @@ imc_msg_t *imc_msg_create_from_long_data(imc_agent_t *agent, imc_state_t *state,
return &this->public;
}
-
diff --git a/src/libimcv/imc/imc_msg.h b/src/libimcv/imc/imc_msg.h
index 6dd712e84..9a4623ae9 100644
--- a/src/libimcv/imc/imc_msg.h
+++ b/src/libimcv/imc/imc_msg.h
@@ -48,6 +48,13 @@ struct imc_msg_t {
TNC_UInt32 (*get_dst_id)(imc_msg_t *this);
/**
+ * Get the PA-TNC message type.
+ *
+ * @return message type
+ */
+ pen_type_t (*get_msg_type)(imc_msg_t *this);
+
+ /**
* Sends one or multiple PA-TNC messages
*
* @param excl set the excl message flag if supported
diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c
index 6a33e396c..78e584dfb 100644
--- a/src/libimcv/imv/imv_agent.c
+++ b/src/libimcv/imv/imv_agent.c
@@ -18,8 +18,11 @@
#include "ietf/ietf_attr_assess_result.h"
#include <tncif_names.h>
+#include <tncif_identity.h>
#include <utils/debug.h>
+#include <collections/linked_list.h>
+#include <bio/bio_reader.h>
#include <threading/rwlock.h>
typedef struct private_imv_agent_t private_imv_agent_t;
@@ -210,8 +213,6 @@ METHOD(imv_agent_t, bind_functions, TNC_Result,
{
this->reserve_additional_id = NULL;
}
- DBG2(DBG_IMV, "IMV %u \"%s\" provided with bind function",
- this->id, this->name);
if (this->report_message_types_long)
{
@@ -352,12 +353,59 @@ static u_int32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID
return 0;
}
+/**
+ * Read a TNC identity attribute
+ */
+static linked_list_t* get_identity_attribute(private_imv_agent_t *this,
+ TNC_ConnectionID id,
+ TNC_AttributeID attribute_id)
+{
+ TNC_UInt32 len;
+ char buf[2048];
+ u_int32_t count;
+ tncif_identity_t *tnc_id;
+ bio_reader_t *reader;
+ linked_list_t *list;
+
+ list = linked_list_create();
+
+ if (!this->get_attribute ||
+ this->get_attribute(this->id, id, attribute_id, sizeof(buf), buf, &len)
+ != TNC_RESULT_SUCCESS || len > sizeof(buf))
+ {
+ return list;
+ }
+
+ reader = bio_reader_create(chunk_create(buf, len));
+ if (!reader->read_uint32(reader, &count))
+ {
+ goto end;
+ }
+ while (count--)
+ {
+ tnc_id = tncif_identity_create_empty();
+ if (!tnc_id->process(tnc_id, reader))
+ {
+ tnc_id->destroy(tnc_id);
+ goto end;
+ }
+ list->insert_last(list, tnc_id);
+ }
+
+end:
+ reader->destroy(reader);
+ return list;
+ }
+
METHOD(imv_agent_t, create_state, TNC_Result,
private_imv_agent_t *this, imv_state_t *state)
{
TNC_ConnectionID conn_id;
char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL;
bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE;
+ linked_list_t *ar_identities;
+ enumerator_t *enumerator;
+ tncif_identity_t *tnc_id;
u_int32_t max_msg_len;
conn_id = state->get_connection_id(state);
@@ -378,6 +426,7 @@ METHOD(imv_agent_t, create_state, TNC_Result,
t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL);
t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION);
max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE);
+ ar_identities = get_identity_attribute(this, conn_id, TNC_ATTRIBUTEID_AR_IDENTITIES);
state->set_flags(state, has_long, has_excl);
state->set_max_msg_len(state, max_msg_len);
@@ -389,6 +438,64 @@ METHOD(imv_agent_t, create_state, TNC_Result,
DBG2(DBG_IMV, " over %s %s with maximum PA-TNC message size of %u bytes",
t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len);
+ enumerator = ar_identities->create_enumerator(ar_identities);
+ while (enumerator->enumerate(enumerator, &tnc_id))
+ {
+ pen_type_t id_type, subject_type, auth_type;
+ int tcg_id_type, tcg_subject_type, tcg_auth_type;
+ chunk_t id_value;
+ id_type_t ike_type;
+ identification_t *id;
+
+ id_type = tnc_id->get_identity_type(tnc_id);
+ id_value = tnc_id->get_identity_value(tnc_id);
+ subject_type = tnc_id->get_subject_type(tnc_id);
+ auth_type = tnc_id->get_auth_type(tnc_id);
+
+ tcg_id_type = (id_type.vendor_id == PEN_TCG) ?
+ id_type.type : TNC_ID_UNKNOWN;
+ tcg_subject_type = (subject_type.vendor_id == PEN_TCG) ?
+ subject_type.type : TNC_SUBJECT_UNKNOWN;
+ tcg_auth_type = (auth_type.vendor_id == PEN_TCG) ?
+ auth_type.type : TNC_AUTH_UNKNOWN;
+
+ switch (tcg_id_type)
+ {
+ case TNC_ID_IPV4_ADDR:
+ ike_type = ID_IPV4_ADDR;
+ break;
+ case TNC_ID_IPV6_ADDR:
+ ike_type = ID_IPV6_ADDR;
+ break;
+ case TNC_ID_FQDN:
+ case TNC_ID_USER_NAME:
+ ike_type = ID_FQDN;
+ break;
+ case TNC_ID_RFC822_ADDR:
+ ike_type = ID_RFC822_ADDR;
+ break;
+ case TNC_ID_DER_ASN1_DN:
+ ike_type = ID_DER_ASN1_DN;
+ break;
+ case TNC_ID_DER_ASN1_GN:
+ ike_type = ID_IPV4_ADDR;
+ break;
+ case TNC_ID_UNKNOWN:
+ default:
+ ike_type = ID_KEY_ID;
+ break;
+ }
+
+ id = identification_create_from_encoding(ike_type, id_value);
+ DBG2(DBG_IMV, "%N identity '%Y' authenticated by %N",
+ TNC_Subject_names, tcg_subject_type, id,
+ TNC_Authentication_names, tcg_auth_type);
+ id->destroy(id);
+ }
+ enumerator->destroy(enumerator);
+
+ ar_identities->destroy_offset(ar_identities,
+ offsetof(tncif_identity_t, destroy));
free(tnccs_p);
free(tnccs_v);
free(t_p);
diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c
index 4ed19dd13..496d0ee1c 100644
--- a/src/libimcv/imv/imv_msg.c
+++ b/src/libimcv/imv/imv_msg.c
@@ -102,6 +102,12 @@ METHOD(imv_msg_t, set_msg_type, void,
}
}
+METHOD(imv_msg_t, get_msg_type, pen_type_t,
+ private_imv_msg_t *this)
+{
+ return this->msg_type;
+}
+
METHOD(imv_msg_t, add_attribute, void,
private_imv_msg_t *this, pa_tnc_attr_t *attr)
{
@@ -352,6 +358,7 @@ imv_msg_t *imv_msg_create(imv_agent_t *agent, imv_state_t *state,
.get_src_id = _get_src_id,
.get_dst_id = _get_dst_id,
.set_msg_type = _set_msg_type,
+ .get_msg_type = _get_msg_type,
.send = _send_,
.send_assessment = _send_assessment,
.receive = _receive,
diff --git a/src/libimcv/imv/imv_msg.h b/src/libimcv/imv/imv_msg.h
index b639712e8..2a2810170 100644
--- a/src/libimcv/imv/imv_msg.h
+++ b/src/libimcv/imv/imv_msg.h
@@ -55,6 +55,13 @@ struct imv_msg_t {
void (*set_msg_type)(imv_msg_t *this, pen_type_t msg_type);
/**
+ * Get the type of a PA-TNC message.
+ *
+ * @return message type
+ */
+ pen_type_t (*get_msg_type)(imv_msg_t *this);
+
+ /**
* Sends one or multiple PA-TNC messages
*
* @param excl set the excl message flag if supported
diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c
index 13374c876..2c49cb01d 100644
--- a/src/libimcv/os_info/os_info.c
+++ b/src/libimcv/os_info/os_info.c
@@ -156,7 +156,7 @@ METHOD(os_info_t, get_uptime, time_t,
{
const char proc_uptime[] = "/proc/uptime";
FILE *file;
- time_t uptime;
+ u_int uptime;
file = fopen(proc_uptime, "r");
if (!file)
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c
index 63445f3a1..d3aceee06 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.c
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.c
@@ -284,6 +284,18 @@ METHOD(pa_tnc_msg_t, process, status_t,
}
DBG3(DBG_TNC, "%B", &value);
+ if (vendor_id == PEN_RESERVED)
+ {
+ error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ this->encoding, offset + 1);
+ goto err;
+ }
+ if (type == IETF_ATTR_RESERVED)
+ {
+ error = ietf_attr_pa_tnc_error_create_with_offset(error_code,
+ this->encoding, offset + 4);
+ goto err;
+ }
attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes,
vendor_id, type, value);
if (!attr)
diff --git a/src/libimcv/plugins/imv_os/imv_os.c b/src/libimcv/plugins/imv_os/imv_os.c
index 65538df07..ecc6cfc4f 100644
--- a/src/libimcv/plugins/imv_os/imv_os.c
+++ b/src/libimcv/plugins/imv_os/imv_os.c
@@ -360,7 +360,9 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
out_msg->add_attribute(out_msg, attr);
}
- if (fatal_error)
+ if (fatal_error ||
+ (os_state->get_attribute_request(os_state) &&
+ os_state->get_info(os_state, NULL, NULL, NULL) == NULL))
{
state->set_recommendation(state,
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
@@ -371,7 +373,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
/* If all Installed Packages attributes were received, go to assessment */
if (!assessment &&
!os_state->get_package_request(os_state) &&
- !os_state->get_angel_count(os_state))
+ !os_state->get_angel_count(os_state) &&
+ os_state->get_info(os_state, NULL, NULL, NULL))
{
int device_id, count, count_update, count_blacklist, count_ok;
u_int os_settings;
@@ -518,6 +521,8 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
{
imv_state_t *state;
imv_os_state_t *os_state;
+ TNC_IMV_Action_Recommendation rec;
+ TNC_IMV_Evaluation_Result eval;
TNC_Result result = TNC_RESULT_SUCCESS;
if (!imv_os)
@@ -531,6 +536,18 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
}
os_state = (imv_os_state_t*)state;
+ state->get_recommendation(state, &rec, &eval);
+
+ /*
+ * Don't send an attribute request if an evaluation is available
+ * or if an attribute request has already been sent
+ */
+ if (eval != TNC_IMV_EVALUATION_RESULT_DONT_KNOW ||
+ os_state->get_attribute_request(os_state))
+ {
+ return TNC_RESULT_SUCCESS;
+ }
+
if (os_state->get_info(os_state, NULL, NULL, NULL) == NULL)
{
imv_msg_t *out_msg;
@@ -548,6 +565,7 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED);
attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED);
out_msg->add_attribute(out_msg, attr);
+ os_state->set_attribute_request(os_state, TRUE);
/* send PA-TNC message with excl flag not set */
result = out_msg->send(out_msg, FALSE);
diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c
index ca6e050f7..00e0424fb 100644
--- a/src/libimcv/plugins/imv_os/imv_os_state.c
+++ b/src/libimcv/plugins/imv_os/imv_os_state.c
@@ -137,6 +137,11 @@ struct private_imv_os_state_t {
int count_ok;
/**
+ * Attribute request sent - mandatory response expected
+ */
+ bool attribute_request;
+
+ /**
* OS Installed Package request sent - mandatory response expected
*/
bool package_request;
@@ -506,6 +511,18 @@ METHOD(imv_os_state_t, get_count, void,
}
}
+METHOD(imv_os_state_t, set_attribute_request, void,
+ private_imv_os_state_t *this, bool set)
+{
+ this->attribute_request = set;
+}
+
+METHOD(imv_os_state_t, get_attribute_request, bool,
+ private_imv_os_state_t *this)
+{
+ return this->attribute_request;
+}
+
METHOD(imv_os_state_t, set_package_request, void,
private_imv_os_state_t *this, bool set)
{
@@ -597,6 +614,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id)
.get_info = _get_info,
.set_count = _set_count,
.get_count = _get_count,
+ .set_attribute_request = _set_attribute_request,
+ .get_attribute_request = _get_attribute_request,
.set_package_request = _set_package_request,
.get_package_request = _get_package_request,
.set_device_id = _set_device_id,
diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h
index 05abdbb6c..d3e319171 100644
--- a/src/libimcv/plugins/imv_os/imv_os_state.h
+++ b/src/libimcv/plugins/imv_os/imv_os_state.h
@@ -87,6 +87,21 @@ struct imv_os_state_t {
*/
void (*get_count)(imv_os_state_t *this, int *count, int *count_update,
int *count_blacklist, int *count_ok);
+
+ /**
+ * Set/reset attribute request status
+ *
+ * @param set TRUE to set, FALSE to clear
+ */
+ void (*set_attribute_request)(imv_os_state_t *this, bool set);
+
+ /**
+ * Get attribute request status
+ *
+ * @return TRUE if set, FALSE if unset
+ */
+ bool (*get_attribute_request)(imv_os_state_t *this);
+
/**
* Set/reset OS Installed Packages request status
*