2 * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "imv_agent.h"
18 #include <tncif_names.h>
21 #include <threading/rwlock.h>
23 typedef struct private_imv_agent_t private_imv_agent_t
;
26 * Private data of an imv_agent_t object.
28 struct private_imv_agent_t
{
31 * Public members of imv_agent_t
41 * message vendor ID of IMV
43 TNC_VendorID vendor_id
;
46 * message subtype of IMV
48 TNC_MessageSubtype subtype
;
51 * ID of IMV as assigned by TNCS
56 * List of additional IMV IDs assigned by TNCS
58 linked_list_t
*additional_ids
;
61 * list of TNCS connection entries
63 linked_list_t
*connections
;
66 * rwlock to lock TNCS connection entries
68 rwlock_t
*connection_lock
;
71 * Inform a TNCS about the set of message types the IMV is able to receive
73 * @param imv_id IMV ID assigned by TNCS
74 * @param supported_types list of supported message types
75 * @param type_count number of list elements
76 * @return TNC result code
78 TNC_Result (*report_message_types
)(TNC_IMVID imv_id
,
79 TNC_MessageTypeList supported_types
,
80 TNC_UInt32 type_count
);
83 * Inform a TNCS about the set of message types the IMV is able to receive
85 * @param imv_id IMV ID assigned by TNCS
86 * @param supported_vids list of supported message vendor IDs
87 * @param supported_subtypes list of supported message subtypes
88 * @param type_count number of list elements
89 * @return TNC result code
91 TNC_Result (*report_message_types_long
)(TNC_IMVID imv_id
,
92 TNC_VendorIDList supported_vids
,
93 TNC_MessageSubtypeList supported_subtypes
,
94 TNC_UInt32 type_count
);
97 * Call when an IMV-IMC message is to be sent
99 * @param imv_id IMV ID assigned by TNCS
100 * @param connection_id network connection ID assigned by TNCS
101 * @param msg message to send
102 * @param msg_len message length in bytes
103 * @param msg_type message type
104 * @return TNC result code
106 TNC_Result (*send_message
)(TNC_IMVID imv_id
,
107 TNC_ConnectionID connection_id
,
108 TNC_BufferReference msg
,
110 TNC_MessageType msg_type
);
113 * Call when an IMV-IMC message is to be sent with long message types
115 * @param imv_id IMV ID assigned by TNCS
116 * @param connection_id network connection ID assigned by TNCS
117 * @param msg_flags message flags
118 * @param msg message to send
119 * @param msg_len message length in bytes
120 * @param msg_vid message vendor ID
121 * @param msg_subtype message subtype
122 * @param dst_imc_id destination IMC ID
123 * @return TNC result code
125 TNC_Result (*send_message_long
)(TNC_IMVID imv_id
,
126 TNC_ConnectionID connection_id
,
127 TNC_UInt32 msg_flags
,
128 TNC_BufferReference msg
,
130 TNC_VendorID msg_vid
,
131 TNC_MessageSubtype msg_subtype
,
132 TNC_UInt32 dst_imc_id
);
135 * Deliver IMV Action Recommendation and IMV Evaluation Results to the TNCS
137 * @param imv_id IMV ID assigned by TNCS
138 # @param connection_id network connection ID assigned by TNCS
139 * @param rec IMV action recommendation
140 * @param eval IMV evaluation result
141 * @return TNC result code
143 TNC_Result (*provide_recommendation
)(TNC_IMVID imv_id
,
144 TNC_ConnectionID connection_id
,
145 TNC_IMV_Action_Recommendation rec
,
146 TNC_IMV_Evaluation_Result eval
);
149 * Get the value of an attribute associated with a connection
150 * or with the TNCS as a whole.
152 * @param imv_id IMV ID assigned by TNCS
153 * @param connection_id network connection ID assigned by TNCS
154 * @param attribute_id attribute ID
155 * @param buffer_len length of buffer in bytes
156 * @param buffer buffer
157 * @param out_value_len size in bytes of attribute stored in buffer
158 * @return TNC result code
160 TNC_Result (*get_attribute
)(TNC_IMVID imv_id
,
161 TNC_ConnectionID connection_id
,
162 TNC_AttributeID attribute_id
,
163 TNC_UInt32 buffer_len
,
164 TNC_BufferReference buffer
,
165 TNC_UInt32
*out_value_len
);
168 * Set the value of an attribute associated with a connection
169 * or with the TNCS as a whole.
171 * @param imv_id IMV ID assigned by TNCS
172 * @param connection_id network connection ID assigned by TNCS
173 * @param attribute_id attribute ID
174 * @param buffer_len length of buffer in bytes
175 * @param buffer buffer
176 * @return TNC result code
178 TNC_Result (*set_attribute
)(TNC_IMVID imv_id
,
179 TNC_ConnectionID connection_id
,
180 TNC_AttributeID attribute_id
,
181 TNC_UInt32 buffer_len
,
182 TNC_BufferReference buffer
);
185 * Reserve an additional IMV ID
187 * @param imv_id primary IMV ID assigned by TNCS
188 * @param out_imv_id additional IMV ID assigned by TNCS
189 * @return TNC result code
191 TNC_Result (*reserve_additional_id
)(TNC_IMVID imv_id
,
192 TNC_UInt32
*out_imv_id
);
196 METHOD(imv_agent_t
, bind_functions
, TNC_Result
,
197 private_imv_agent_t
*this, TNC_TNCS_BindFunctionPointer bind_function
)
201 DBG1(DBG_IMV
, "TNC server failed to provide bind function");
202 return TNC_RESULT_INVALID_PARAMETER
;
204 if (bind_function(this->id
, "TNC_TNCS_ReportMessageTypes",
205 (void**)&this->report_message_types
) != TNC_RESULT_SUCCESS
)
207 this->report_message_types
= NULL
;
209 if (bind_function(this->id
, "TNC_TNCS_ReportMessageTypesLong",
210 (void**)&this->report_message_types_long
) != TNC_RESULT_SUCCESS
)
212 this->report_message_types_long
= NULL
;
214 if (bind_function(this->id
, "TNC_TNCS_RequestHandshakeRetry",
215 (void**)&this->public.request_handshake_retry
) != TNC_RESULT_SUCCESS
)
217 this->public.request_handshake_retry
= NULL
;
219 if (bind_function(this->id
, "TNC_TNCS_SendMessage",
220 (void**)&this->send_message
) != TNC_RESULT_SUCCESS
)
222 this->send_message
= NULL
;
224 if (bind_function(this->id
, "TNC_TNCS_SendMessageLong",
225 (void**)&this->send_message_long
) != TNC_RESULT_SUCCESS
)
227 this->send_message_long
= NULL
;
229 if (bind_function(this->id
, "TNC_TNCS_ProvideRecommendation",
230 (void**)&this->provide_recommendation
) != TNC_RESULT_SUCCESS
)
232 this->provide_recommendation
= NULL
;
234 if (bind_function(this->id
, "TNC_TNCS_GetAttribute",
235 (void**)&this->get_attribute
) != TNC_RESULT_SUCCESS
)
237 this->get_attribute
= NULL
;
239 if (bind_function(this->id
, "TNC_TNCS_SetAttribute",
240 (void**)&this->set_attribute
) != TNC_RESULT_SUCCESS
)
242 this->set_attribute
= NULL
;
244 if (bind_function(this->id
, "TNC_TNCC_ReserveAdditionalIMVID",
245 (void**)&this->reserve_additional_id
) != TNC_RESULT_SUCCESS
)
247 this->reserve_additional_id
= NULL
;
249 DBG2(DBG_IMV
, "IMV %u \"%s\" provided with bind function",
250 this->id
, this->name
);
252 if (this->report_message_types_long
)
254 this->report_message_types_long(this->id
, &this->vendor_id
,
257 else if (this->report_message_types
&&
258 this->vendor_id
<= TNC_VENDORID_ANY
&&
259 this->subtype
<= TNC_SUBTYPE_ANY
)
261 TNC_MessageType type
;
263 type
= (this->vendor_id
<< 8) | this->subtype
;
264 this->report_message_types(this->id
, &type
, 1);
266 return TNC_RESULT_SUCCESS
;
270 * finds a connection state based on its Connection ID
272 static imv_state_t
* find_connection(private_imv_agent_t
*this,
275 enumerator_t
*enumerator
;
276 imv_state_t
*state
, *found
= NULL
;
278 this->connection_lock
->read_lock(this->connection_lock
);
279 enumerator
= this->connections
->create_enumerator(this->connections
);
280 while (enumerator
->enumerate(enumerator
, &state
))
282 if (id
== state
->get_connection_id(state
))
288 enumerator
->destroy(enumerator
);
289 this->connection_lock
->unlock(this->connection_lock
);
295 * delete a connection state with a given Connection ID
297 static bool delete_connection(private_imv_agent_t
*this, TNC_ConnectionID id
)
299 enumerator_t
*enumerator
;
303 this->connection_lock
->write_lock(this->connection_lock
);
304 enumerator
= this->connections
->create_enumerator(this->connections
);
305 while (enumerator
->enumerate(enumerator
, &state
))
307 if (id
== state
->get_connection_id(state
))
310 state
->destroy(state
);
311 this->connections
->remove_at(this->connections
, enumerator
);
315 enumerator
->destroy(enumerator
);
316 this->connection_lock
->unlock(this->connection_lock
);
322 * Read a boolean attribute
324 static bool get_bool_attribute(private_imv_agent_t
*this, TNC_ConnectionID id
,
325 TNC_AttributeID attribute_id
)
330 return this->get_attribute
&&
331 this->get_attribute(this->id
, id
, attribute_id
, 4, buf
, &len
) ==
332 TNC_RESULT_SUCCESS
&& len
== 1 && *buf
== 0x01;
336 * Read a string attribute
338 static char* get_str_attribute(private_imv_agent_t
*this, TNC_ConnectionID id
,
339 TNC_AttributeID attribute_id
)
344 if (this->get_attribute
&&
345 this->get_attribute(this->id
, id
, attribute_id
, BUF_LEN
, buf
, &len
) ==
346 TNC_RESULT_SUCCESS
&& len
<= BUF_LEN
)
353 METHOD(imv_agent_t
, create_state
, TNC_Result
,
354 private_imv_agent_t
*this, imv_state_t
*state
)
356 TNC_ConnectionID conn_id
;
357 char *tnccs_p
= NULL
, *tnccs_v
= NULL
, *t_p
= NULL
, *t_v
= NULL
;
358 bool has_long
= FALSE
, has_excl
= FALSE
, has_soh
= FALSE
;
360 conn_id
= state
->get_connection_id(state
);
361 if (find_connection(this, conn_id
))
363 DBG1(DBG_IMV
, "IMV %u \"%s\" already created a state for Connection ID %u",
364 this->id
, this->name
, conn_id
);
365 state
->destroy(state
);
366 return TNC_RESULT_OTHER
;
369 /* Get and display attributes from TNCS via IF-IMV */
370 has_long
= get_bool_attribute(this, conn_id
, TNC_ATTRIBUTEID_HAS_LONG_TYPES
);
371 has_excl
= get_bool_attribute(this, conn_id
, TNC_ATTRIBUTEID_HAS_EXCLUSIVE
);
372 has_soh
= get_bool_attribute(this, conn_id
, TNC_ATTRIBUTEID_HAS_SOH
);
373 tnccs_p
= get_str_attribute(this, conn_id
, TNC_ATTRIBUTEID_IFTNCCS_PROTOCOL
);
374 tnccs_v
= get_str_attribute(this, conn_id
, TNC_ATTRIBUTEID_IFTNCCS_VERSION
);
375 t_p
= get_str_attribute(this, conn_id
, TNC_ATTRIBUTEID_IFT_PROTOCOL
);
376 t_v
= get_str_attribute(this, conn_id
, TNC_ATTRIBUTEID_IFT_VERSION
);
378 state
->set_flags(state
, has_long
, has_excl
);
380 DBG2(DBG_IMV
, "IMV %u \"%s\" created a state for Connection ID %u: "
381 "%s %s with %slong %sexcl %ssoh over %s %s",
382 this->id
, this->name
, conn_id
, tnccs_p ? tnccs_p
:"?",
383 tnccs_v ? tnccs_v
:"?", has_long ?
"+":"-", has_excl ?
"+":"-",
384 has_soh ?
"+":"-", t_p ? t_p
:"?", t_v ? t_v
:"?");
390 this->connection_lock
->write_lock(this->connection_lock
);
391 this->connections
->insert_last(this->connections
, state
);
392 this->connection_lock
->unlock(this->connection_lock
);
393 return TNC_RESULT_SUCCESS
;
396 METHOD(imv_agent_t
, delete_state
, TNC_Result
,
397 private_imv_agent_t
*this, TNC_ConnectionID connection_id
)
399 if (!delete_connection(this, connection_id
))
401 DBG1(DBG_IMV
, "IMV %u \"%s\" has no state for Connection ID %u",
402 this->id
, this->name
, connection_id
);
403 return TNC_RESULT_FATAL
;
405 DBG2(DBG_IMV
, "IMV %u \"%s\" deleted the state of Connection ID %u",
406 this->id
, this->name
, connection_id
);
407 return TNC_RESULT_SUCCESS
;
410 METHOD(imv_agent_t
, change_state
, TNC_Result
,
411 private_imv_agent_t
*this, TNC_ConnectionID connection_id
,
412 TNC_ConnectionState new_state
,
413 imv_state_t
**state_p
)
419 case TNC_CONNECTION_STATE_HANDSHAKE
:
420 case TNC_CONNECTION_STATE_ACCESS_ALLOWED
:
421 case TNC_CONNECTION_STATE_ACCESS_ISOLATED
:
422 case TNC_CONNECTION_STATE_ACCESS_NONE
:
423 state
= find_connection(this, connection_id
);
426 DBG1(DBG_IMV
, "IMV %u \"%s\" has no state for Connection ID %u",
427 this->id
, this->name
, connection_id
);
428 return TNC_RESULT_FATAL
;
430 state
->change_state(state
, new_state
);
431 DBG2(DBG_IMV
, "IMV %u \"%s\" changed state of Connection ID %u to '%N'",
432 this->id
, this->name
, connection_id
,
433 TNC_Connection_State_names
, new_state
);
439 case TNC_CONNECTION_STATE_CREATE
:
440 DBG1(DBG_IMV
, "state '%N' should be handled by create_state()",
441 TNC_Connection_State_names
, new_state
);
442 return TNC_RESULT_FATAL
;
443 case TNC_CONNECTION_STATE_DELETE
:
444 DBG1(DBG_IMV
, "state '%N' should be handled by delete_state()",
445 TNC_Connection_State_names
, new_state
);
446 return TNC_RESULT_FATAL
;
448 DBG1(DBG_IMV
, "IMV %u \"%s\" was notified of unknown state %u "
449 "for Connection ID %u",
450 this->id
, this->name
, new_state
, connection_id
);
451 return TNC_RESULT_INVALID_PARAMETER
;
453 return TNC_RESULT_SUCCESS
;
456 METHOD(imv_agent_t
, get_state
, bool,
457 private_imv_agent_t
*this, TNC_ConnectionID connection_id
,
460 *state
= find_connection(this, connection_id
);
463 DBG1(DBG_IMV
, "IMV %u \"%s\" has no state for Connection ID %u",
464 this->id
, this->name
, connection_id
);
470 METHOD(imv_agent_t
, send_message
, TNC_Result
,
471 private_imv_agent_t
*this, TNC_ConnectionID connection_id
, bool excl
,
472 TNC_UInt32 src_imv_id
, TNC_UInt32 dst_imc_id
, linked_list_t
*attr_list
)
474 TNC_MessageType type
;
475 TNC_UInt32 msg_flags
;
478 pa_tnc_msg_t
*pa_tnc_msg
;
481 state
= find_connection(this, connection_id
);
484 DBG1(DBG_IMV
, "IMV %u \"%s\" has no state for Connection ID %u",
485 this->id
, this->name
, connection_id
);
486 return TNC_RESULT_FATAL
;
489 pa_tnc_msg
= pa_tnc_msg_create();
491 while (attr_list
->remove_first(attr_list
, (void**)&attr
) == SUCCESS
)
493 pa_tnc_msg
->add_attribute(pa_tnc_msg
, attr
);
495 pa_tnc_msg
->build(pa_tnc_msg
);
496 msg
= pa_tnc_msg
->get_encoding(pa_tnc_msg
);
498 if (state
->has_long(state
) && this->send_message_long
)
502 src_imv_id
= this->id
;
504 msg_flags
= excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE
: 0;
506 return this->send_message_long(src_imv_id
, connection_id
, msg_flags
,
507 msg
.ptr
, msg
.len
, this->vendor_id
,
508 this->subtype
, dst_imc_id
);
510 if (this->send_message
)
512 type
= (this->vendor_id
<< 8) | this->subtype
;
514 return this->send_message(this->id
, connection_id
, msg
.ptr
, msg
.len
,
517 return TNC_RESULT_FATAL
;
520 METHOD(imv_agent_t
, set_recommendation
, TNC_Result
,
521 private_imv_agent_t
*this, TNC_ConnectionID connection_id
,
522 TNC_IMV_Action_Recommendation rec
,
523 TNC_IMV_Evaluation_Result eval
)
527 state
= find_connection(this, connection_id
);
530 DBG1(DBG_IMV
, "IMV %u \"%s\" has no state for Connection ID %u",
531 this->id
, this->name
, connection_id
);
532 return TNC_RESULT_FATAL
;
535 state
->set_recommendation(state
, rec
, eval
);
536 return this->provide_recommendation(this->id
, connection_id
, rec
, eval
);
539 METHOD(imv_agent_t
, receive_message
, TNC_Result
,
540 private_imv_agent_t
*this, imv_state_t
*state
, chunk_t msg
,
541 TNC_VendorID msg_vid
, TNC_MessageSubtype msg_subtype
,
542 TNC_UInt32 src_imc_id
, TNC_UInt32 dst_imv_id
, pa_tnc_msg_t
**pa_tnc_msg
)
544 pa_tnc_msg_t
*pa_msg
, *error_msg
;
545 pa_tnc_attr_t
*error_attr
;
546 enumerator_t
*enumerator
;
547 TNC_MessageType msg_type
;
548 TNC_UInt32 msg_flags
, src_imv_id
, dst_imc_id
;
549 TNC_ConnectionID connection_id
;
552 connection_id
= state
->get_connection_id(state
);
554 if (state
->has_long(state
))
556 if (dst_imv_id
!= TNC_IMVID_ANY
)
558 DBG2(DBG_IMV
, "IMV %u \"%s\" received message for Connection ID %u "
559 "from IMC %u to IMV %u", this->id
, this->name
,
560 connection_id
, src_imc_id
, dst_imv_id
);
564 DBG2(DBG_IMV
, "IMV %u \"%s\" received message for Connection ID %u "
565 "from IMC %u", this->id
, this->name
, connection_id
,
571 DBG2(DBG_IMV
, "IMV %u \"%s\" received message for Connection ID %u",
572 this->id
, this->name
, connection_id
);
576 pa_msg
= pa_tnc_msg_create_from_data(msg
);
578 switch (pa_msg
->process(pa_msg
))
581 *pa_tnc_msg
= pa_msg
;
584 /* build error message */
585 error_msg
= pa_tnc_msg_create();
586 enumerator
= pa_msg
->create_error_enumerator(pa_msg
);
587 while (enumerator
->enumerate(enumerator
, &error_attr
))
589 error_msg
->add_attribute(error_msg
,
590 error_attr
->get_ref(error_attr
));
592 enumerator
->destroy(enumerator
);
593 error_msg
->build(error_msg
);
595 /* send error message */
596 msg
= error_msg
->get_encoding(error_msg
);
598 if (state
->has_long(state
) && this->send_message_long
)
600 if (state
->has_excl(state
))
602 msg_flags
= TNC_MESSAGE_FLAGS_EXCLUSIVE
;
603 dst_imc_id
= src_imc_id
;
608 dst_imc_id
= TNC_IMCID_ANY
;
610 src_imv_id
= (dst_imv_id
== TNC_IMVID_ANY
) ?
this->id
613 result
= this->send_message_long(src_imv_id
, connection_id
,
614 msg_flags
, msg
.ptr
, msg
.len
, msg_vid
,
615 msg_subtype
, dst_imc_id
);
617 else if (this->send_message
)
619 msg_type
= (msg_vid
<< 8) | msg_subtype
;
621 result
= this->send_message(this->id
, connection_id
,
622 msg
.ptr
, msg
.len
, msg_type
);
626 result
= TNC_RESULT_FATAL
;
630 error_msg
->destroy(error_msg
);
631 pa_msg
->destroy(pa_msg
);
635 pa_msg
->destroy(pa_msg
);
636 state
->set_recommendation(state
,
637 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
,
638 TNC_IMV_EVALUATION_RESULT_ERROR
);
639 return this->provide_recommendation(this->id
, connection_id
,
640 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
,
641 TNC_IMV_EVALUATION_RESULT_ERROR
);
643 return TNC_RESULT_SUCCESS
;
646 METHOD(imv_agent_t
, provide_recommendation
, TNC_Result
,
647 private_imv_agent_t
*this, TNC_ConnectionID connection_id
)
650 TNC_IMV_Action_Recommendation rec
;
651 TNC_IMV_Evaluation_Result eval
;
654 chunk_t pref_lang
= { buf
, 0 }, reason_string
, reason_lang
;
656 state
= find_connection(this, connection_id
);
659 DBG1(DBG_IMV
, "IMV %u \"%s\" has no state for Connection ID %u",
660 this->id
, this->name
, connection_id
);
661 return TNC_RESULT_FATAL
;
663 state
->get_recommendation(state
, &rec
, &eval
);
666 /* send a reason string if action recommendation is not allow */
667 if (rec
!= TNC_IMV_ACTION_RECOMMENDATION_ALLOW
)
669 /* check if there a preferred language has been requested */
670 if (this->get_attribute
&&
671 this->get_attribute(this->id
, connection_id
,
672 TNC_ATTRIBUTEID_PREFERRED_LANGUAGE
, BUF_LEN
,
673 buf
, &lang_len
) == TNC_RESULT_SUCCESS
&&
676 pref_lang
.len
= lang_len
;
677 DBG2(DBG_IMV
, "preferred language is '%.*s'",
678 pref_lang
.len
, pref_lang
.ptr
);
681 /* find a reason string for the preferred or default language and set it */
682 if (this->set_attribute
&&
683 state
->get_reason_string(state
, pref_lang
, &reason_string
,
686 this->set_attribute(this->id
, connection_id
,
687 TNC_ATTRIBUTEID_REASON_STRING
,
688 reason_string
.len
, reason_string
.ptr
);
689 this->set_attribute(this->id
, connection_id
,
690 TNC_ATTRIBUTEID_REASON_LANGUAGE
,
691 reason_lang
.len
, reason_lang
.ptr
);
695 return this->provide_recommendation(this->id
, connection_id
, rec
, eval
);
698 METHOD(imv_agent_t
, reserve_additional_ids
, TNC_Result
,
699 private_imv_agent_t
*this, int count
)
705 if (!this->reserve_additional_id
)
707 DBG1(DBG_IMV
, "IMV %u \"%s\" did not detect the capability to reserve "
708 "additional IMV IDs from the TNCS", this->id
, this->name
);
709 return TNC_RESULT_ILLEGAL_OPERATION
;
713 result
= this->reserve_additional_id(this->id
, &id
);
714 if (result
!= TNC_RESULT_SUCCESS
)
716 DBG1(DBG_IMV
, "IMV %u \"%s\" failed to reserve %d additional IMV IDs",
717 this->id
, this->name
, count
);
722 /* store the scalar value in the pointer */
724 this->additional_ids
->insert_last(this->additional_ids
, pointer
);
725 DBG2(DBG_IMV
, "IMV %u \"%s\" reserved additional ID %u",
726 this->id
, this->name
, id
);
728 return TNC_RESULT_SUCCESS
;
731 METHOD(imv_agent_t
, count_additional_ids
, int,
732 private_imv_agent_t
*this)
734 return this->additional_ids
->get_count(this->additional_ids
);
737 METHOD(imv_agent_t
, create_id_enumerator
, enumerator_t
*,
738 private_imv_agent_t
*this)
740 return this->additional_ids
->create_enumerator(this->additional_ids
);
743 METHOD(imv_agent_t
, destroy
, void,
744 private_imv_agent_t
*this)
746 DBG1(DBG_IMV
, "IMV %u \"%s\" terminated", this->id
, this->name
);
747 this->additional_ids
->destroy(this->additional_ids
);
748 this->connections
->destroy_offset(this->connections
,
749 offsetof(imv_state_t
, destroy
));
750 this->connection_lock
->destroy(this->connection_lock
);
753 /* decrease the reference count or terminate */
758 * Described in header.
760 imv_agent_t
*imv_agent_create(const char *name
,
761 pen_t vendor_id
, u_int32_t subtype
,
762 TNC_IMVID id
, TNC_Version
*actual_version
)
764 private_imv_agent_t
*this;
766 /* initialize or increase the reference count */
774 .bind_functions
= _bind_functions
,
775 .create_state
= _create_state
,
776 .delete_state
= _delete_state
,
777 .change_state
= _change_state
,
778 .get_state
= _get_state
,
779 .send_message
= _send_message
,
780 .receive_message
= _receive_message
,
781 .set_recommendation
= _set_recommendation
,
782 .provide_recommendation
= _provide_recommendation
,
783 .reserve_additional_ids
= _reserve_additional_ids
,
784 .count_additional_ids
= _count_additional_ids
,
785 .create_id_enumerator
= _create_id_enumerator
,
789 .vendor_id
= vendor_id
,
792 .additional_ids
= linked_list_create(),
793 .connections
= linked_list_create(),
794 .connection_lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
797 *actual_version
= TNC_IFIMV_VERSION_1
;
798 DBG1(DBG_IMV
, "IMV %u \"%s\" initialized", this->id
, this->name
);
800 return &this->public;