tncs.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
14ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * EAP-TNC - TNCS (IF-IMV, IF-TNCCS, and IF-TNCCS-SOH)
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2007-2008, Jouni Malinen <j@w1.fi>
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This program is free software; you can redistribute it and/or modify
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it under the terms of the GNU General Public License version 2 as
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * published by the Free Software Foundation.
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alternatively, this software may be distributed under the terms of BSD
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See README and COPYING for more details.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "includes.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "common.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base64.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "tncs.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "eap_common/eap_tlv_common.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "eap_common/eap_defs.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TODO: TNCS must be thread-safe; review the code and add locking etc. if
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * needed.. */
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_CONFIG_FILE "/etc/tnc_config"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define IF_TNCCS_START \
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)"<?xml version=\"1.0\"?>\n" \
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"<TNCCS-Batch BatchId=\"%d\" Recipient=\"TNCS\" " \
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"xmlns=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#\" " \
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"xsi:schemaLocation=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/" \
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"IF_TNCCS# https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd\">\n"
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#define IF_TNCCS_END "\n</TNCCS-Batch>"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TNC IF-IMV */
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef unsigned long TNC_UInt32;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef unsigned char *TNC_BufferReference;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_IMVID;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_ConnectionID;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef TNC_UInt32 TNC_ConnectionState;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_RetryReason;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_IMV_Action_Recommendation;
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)typedef TNC_UInt32 TNC_IMV_Evaluation_Result;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_MessageType;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef TNC_MessageType *TNC_MessageTypeList;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef TNC_UInt32 TNC_VendorID;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_Subtype;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_Version;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_Result;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TNC_UInt32 TNC_AttributeID;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)typedef TNC_Result (*TNC_TNCS_BindFunctionPointer)(
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMVID imvID,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	char *functionName,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	void **pOutfunctionPointer);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_RESULT_SUCCESS 0
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_RESULT_NOT_INITIALIZED 1
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_RESULT_ALREADY_INITIALIZED 2
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_RESULT_NO_COMMON_VERSION 3
66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#define TNC_RESULT_CANT_RETRY 4
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_RESULT_WONT_RETRY 5
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_RESULT_INVALID_PARAMETER 6
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define TNC_RESULT_CANT_RESPOND 7
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TNC_RESULT_ILLEGAL_OPERATION 8
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TNC_RESULT_OTHER 9
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_RESULT_FATAL 10
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_CONNECTION_STATE_CREATE 0
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TNC_CONNECTION_STATE_HANDSHAKE 1
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#define TNC_CONNECTION_STATE_ACCESS_NONE 4
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_CONNECTION_STATE_DELETE 5
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TNC_IFIMV_VERSION_1 1
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_SUBTYPE_ANY ((TNC_Subtype) 0xff)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TNCC-TNCS Message Types */
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#define TNC_TNCCS_RECOMMENDATION		0x00000001
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_TNCCS_ERROR				0x00000002
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TNC_TNCCS_PREFERREDLANGUAGE		0x00000003
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define TNC_TNCCS_REASONSTRINGS			0x00000004
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Possible TNC_IMV_Action_Recommendation values: */
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum IMV_Action_Recommendation {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS,
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	TNC_IMV_ACTION_RECOMMENDATION_ISOLATE,
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Possible TNC_IMV_Evaluation_Result values: */
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum IMV_Evaluation_Result {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMV_EVALUATION_RESULT_COMPLIANT,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMV_EVALUATION_RESULT_ERROR,
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	TNC_IMV_EVALUATION_RESULT_DONT_KNOW
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct tnc_if_imv {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct tnc_if_imv *next;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	char *name;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	char *path;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	void *dlhandle; /* from dlopen() */
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMVID imvID;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_MessageTypeList supported_types;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	size_t num_supported_types;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	/* Functions implemented by IMVs (with TNC_IMV_ prefix) */
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Result (*Initialize)(
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		TNC_IMVID imvID,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		TNC_Version minVersion,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_Version maxVersion,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_Version *pOutActualVersion);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Result (*NotifyConnectionChange)(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_IMVID imvID,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_ConnectionID connectionID,
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		TNC_ConnectionState newState);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Result (*ReceiveMessage)(
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		TNC_IMVID imvID,
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		TNC_ConnectionID connectionID,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_BufferReference message,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_UInt32 messageLength,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_MessageType messageType);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Result (*SolicitRecommendation)(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_IMVID imvID,
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		TNC_ConnectionID connectionID);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Result (*BatchEnding)(
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_IMVID imvID,
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		TNC_ConnectionID connectionID);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_Result (*Terminate)(TNC_IMVID imvID);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_Result (*ProvideBindFunction)(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_IMVID imvID,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		TNC_TNCS_BindFunctionPointer bindFunction);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TNC_MAX_IMV_ID 10
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct tncs_data {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct tncs_data *next;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct tnc_if_imv *imv; /* local copy of tncs_global_data->imv */
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_ConnectionID connectionID;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int last_batchid;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	enum IMV_Action_Recommendation recommendation;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int done;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	struct conn_imv {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		u8 *imv_send;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		size_t imv_send_len;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		enum IMV_Action_Recommendation recommendation;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		int recommendation_set;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} imv_data[TNC_MAX_IMV_ID];
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	char *tncs_message;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct tncs_global {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct tnc_if_imv *imv;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_ConnectionID next_conn_id;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct tncs_data *connections;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct tncs_global *tncs_global_data = NULL;
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static struct tnc_if_imv * tncs_get_imv(TNC_IMVID imvID)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct tnc_if_imv *imv;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imvID >= TNC_MAX_IMV_ID || tncs_global_data == NULL)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv = tncs_global_data->imv;
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	while (imv) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (imv->imvID == imvID)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return imv;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		imv = imv->next;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static struct tncs_data * tncs_get_conn(TNC_ConnectionID connectionID)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct tncs_data *tncs;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs_global_data == NULL)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs = tncs_global_data->connections;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (tncs) {
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		if (tncs->connectionID == connectionID)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return tncs;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		tncs = tncs->next;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Connection ID %lu not found",
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   (unsigned long) connectionID);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* TNCS functions that IMVs can call */
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TNC_Result TNC_TNCS_ReportMessageTypes(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMVID imvID,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_MessageTypeList supportedTypes,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_UInt32 typeCount)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	TNC_UInt32 i;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct tnc_if_imv *imv;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_ReportMessageTypes(imvID=%lu "
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   "typeCount=%lu)",
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   (unsigned long) imvID, (unsigned long) typeCount);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < typeCount; i++) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu",
229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			   i, supportedTypes[i]);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	imv = tncs_get_imv(imvID);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (imv == NULL)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNC_RESULT_INVALID_PARAMETER;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(imv->supported_types);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->supported_types =
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_malloc(typeCount * sizeof(TNC_MessageType));
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	if (imv->supported_types == NULL)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNC_RESULT_FATAL;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	os_memcpy(imv->supported_types, supportedTypes,
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		  typeCount * sizeof(TNC_MessageType));
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	imv->num_supported_types = typeCount;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TNC_RESULT_SUCCESS;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TNC_Result TNC_TNCS_SendMessage(
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_IMVID imvID,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_ConnectionID connectionID,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_BufferReference message,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_UInt32 messageLength,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_MessageType messageType)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct tncs_data *tncs;
256010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	unsigned char *b64;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	size_t b64len;
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage(imvID=%lu "
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   "connectionID=%lu messageType=%lu)",
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   imvID, connectionID, messageType);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage",
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  message, messageLength);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs_get_imv(imvID) == NULL)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNC_RESULT_INVALID_PARAMETER;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	tncs = tncs_get_conn(connectionID);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs == NULL)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return TNC_RESULT_INVALID_PARAMETER;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	b64 = base64_encode(message, messageLength, &b64len);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (b64 == NULL)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNC_RESULT_FATAL;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(tncs->imv_data[imvID].imv_send);
277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	tncs->imv_data[imvID].imv_send_len = 0;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->imv_data[imvID].imv_send = os_zalloc(b64len + 100);
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (tncs->imv_data[imvID].imv_send == NULL) {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		os_free(b64);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNC_RESULT_OTHER;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->imv_data[imvID].imv_send_len =
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_snprintf((char *) tncs->imv_data[imvID].imv_send,
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			    b64len + 100,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    "<IMC-IMV-Message><Type>%08X</Type>"
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			    "<Base64>%s</Base64></IMC-IMV-Message>",
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			    (unsigned int) messageType, b64);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(b64);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TNC_RESULT_SUCCESS;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TNC_Result TNC_TNCS_RequestHandshakeRetry(
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_IMVID imvID,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_ConnectionID connectionID,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_RetryReason reason)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_RequestHandshakeRetry");
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* TODO */
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TNC_RESULT_SUCCESS;
305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TNC_Result TNC_TNCS_ProvideRecommendation(
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_IMVID imvID,
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_ConnectionID connectionID,
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_IMV_Action_Recommendation recommendation,
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_IMV_Evaluation_Result evaluation)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	struct tncs_data *tncs;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_ProvideRecommendation(imvID=%lu "
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		   "connectionID=%lu recommendation=%lu evaluation=%lu)",
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   (unsigned long) imvID, (unsigned long) connectionID,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   (unsigned long) recommendation, (unsigned long) evaluation);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs_get_imv(imvID) == NULL)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNC_RESULT_INVALID_PARAMETER;
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	tncs = tncs_get_conn(connectionID);
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (tncs == NULL)
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return TNC_RESULT_INVALID_PARAMETER;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->imv_data[imvID].recommendation = recommendation;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->imv_data[imvID].recommendation_set = 1;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TNC_RESULT_SUCCESS;
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TNC_Result TNC_TNCS_GetAttribute(
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMVID imvID,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_ConnectionID connectionID,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_AttributeID attribureID,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_UInt32 bufferLength,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_BufferReference buffer,
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	TNC_UInt32 *pOutValueLength)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_GetAttribute");
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* TODO */
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TNC_RESULT_SUCCESS;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TNC_Result TNC_TNCS_SetAttribute(
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMVID imvID,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_ConnectionID connectionID,
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)	TNC_AttributeID attribureID,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_UInt32 bufferLength,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_BufferReference buffer)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SetAttribute");
357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	/* TODO */
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TNC_RESULT_SUCCESS;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TNC_Result TNC_TNCS_BindFunction(
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_IMVID imvID,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	char *functionName,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	void **pOutFunctionPointer)
366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles){
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_BindFunction(imcID=%lu, "
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		   "functionName='%s')", (unsigned long) imvID, functionName);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs_get_imv(imvID) == NULL)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNC_RESULT_INVALID_PARAMETER;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pOutFunctionPointer == NULL)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNC_RESULT_INVALID_PARAMETER;
375010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (os_strcmp(functionName, "TNC_TNCS_ReportMessageTypes") == 0)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		*pOutFunctionPointer = TNC_TNCS_ReportMessageTypes;
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	else if (os_strcmp(functionName, "TNC_TNCS_SendMessage") == 0)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*pOutFunctionPointer = TNC_TNCS_SendMessage;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else if (os_strcmp(functionName, "TNC_TNCS_RequestHandshakeRetry") ==
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 0)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*pOutFunctionPointer = TNC_TNCS_RequestHandshakeRetry;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else if (os_strcmp(functionName, "TNC_TNCS_ProvideRecommendation") ==
384010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		 0)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*pOutFunctionPointer = TNC_TNCS_ProvideRecommendation;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	else if (os_strcmp(functionName, "TNC_TNCS_GetAttribute") == 0)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		*pOutFunctionPointer = TNC_TNCS_GetAttribute;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else if (os_strcmp(functionName, "TNC_TNCS_SetAttribute") == 0)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*pOutFunctionPointer = TNC_TNCS_SetAttribute;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*pOutFunctionPointer = NULL;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	return TNC_RESULT_SUCCESS;
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void * tncs_get_sym(void *handle, char *func)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	void *fptr;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	fptr = dlsym(handle, func);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	return fptr;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int tncs_imv_resolve_funcs(struct tnc_if_imv *imv)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	void *handle = imv->dlhandle;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* Mandatory IMV functions */
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->Initialize = tncs_get_sym(handle, "TNC_IMV_Initialize");
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imv->Initialize == NULL) {
414010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: IMV does not export "
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   "TNC_IMV_Initialize");
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return -1;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->SolicitRecommendation = tncs_get_sym(
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		handle, "TNC_IMV_SolicitRecommendation");
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imv->SolicitRecommendation == NULL) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: IMV does not export "
423010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			   "TNC_IMV_SolicitRecommendation");
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return -1;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->ProvideBindFunction =
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs_get_sym(handle, "TNC_IMV_ProvideBindFunction");
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imv->ProvideBindFunction == NULL) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: IMV does not export "
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   "TNC_IMV_ProvideBindFunction");
432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		return -1;
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* Optional IMV functions */
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	imv->NotifyConnectionChange =
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs_get_sym(handle, "TNC_IMV_NotifyConnectionChange");
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->ReceiveMessage = tncs_get_sym(handle, "TNC_IMV_ReceiveMessage");
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->BatchEnding = tncs_get_sym(handle, "TNC_IMV_BatchEnding");
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->Terminate = tncs_get_sym(handle, "TNC_IMV_Terminate");
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int tncs_imv_initialize(struct tnc_if_imv *imv)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Result res;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Version imv_ver;
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_Initialize for IMV '%s'",
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   imv->name);
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	res = imv->Initialize(imv->imvID, TNC_IFIMV_VERSION_1,
454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			      TNC_IFIMV_VERSION_1, &imv_ver);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_Initialize: res=%lu imv_ver=%lu",
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		   (unsigned long) res, (unsigned long) imv_ver);
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return res == TNC_RESULT_SUCCESS ? 0 : -1;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tncs_imv_terminate(struct tnc_if_imv *imv)
463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Result res;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	if (imv->Terminate == NULL)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return 0;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_Terminate for IMV '%s'",
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   imv->name);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	res = imv->Terminate(imv->imvID);
472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_Terminate: %lu",
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   (unsigned long) res);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	return res == TNC_RESULT_SUCCESS ? 0 : -1;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tncs_imv_provide_bind_function(struct tnc_if_imv *imv)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	TNC_Result res;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_ProvideBindFunction for "
484010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		   "IMV '%s'", imv->name);
485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	res = imv->ProvideBindFunction(imv->imvID, TNC_TNCS_BindFunction);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_ProvideBindFunction: res=%lu",
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		   (unsigned long) res);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return res == TNC_RESULT_SUCCESS ? 0 : -1;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tncs_imv_notify_connection_change(struct tnc_if_imv *imv,
494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)					     TNC_ConnectionID conn,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					     TNC_ConnectionState state)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
497010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	TNC_Result res;
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (imv->NotifyConnectionChange == NULL)
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return 0;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_NotifyConnectionChange(%d)"
503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		   " for IMV '%s'", (int) state, imv->name);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	res = imv->NotifyConnectionChange(imv->imvID, conn, state);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu",
506010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		   (unsigned long) res);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return res == TNC_RESULT_SUCCESS ? 0 : -1;
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tncs_load_imv(struct tnc_if_imv *imv)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imv->path == NULL) {
515010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: No IMV configured");
516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return -1;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Opening IMV: %s (%s)",
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   imv->name, imv->path);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->dlhandle = dlopen(imv->path, RTLD_LAZY);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imv->dlhandle == NULL) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: Failed to open IMV '%s' (%s): %s",
524a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			   imv->name, imv->path, dlerror());
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return -1;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
527010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (tncs_imv_resolve_funcs(imv) < 0) {
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMV functions");
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return -1;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
533a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (tncs_imv_initialize(imv) < 0 ||
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    tncs_imv_provide_bind_function(imv) < 0) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMV");
536010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		return -1;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return 0;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tncs_free_imv(struct tnc_if_imv *imv)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	os_free(imv->name);
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	os_free(imv->path);
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	os_free(imv->supported_types);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tncs_unload_imv(struct tnc_if_imv *imv)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs_imv_terminate(imv);
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imv->dlhandle)
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		dlclose(imv->dlhandle);
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs_free_imv(imv);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tncs_supported_type(struct tnc_if_imv *imv, unsigned int type)
562010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles){
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	size_t i;
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	unsigned int vendor, subtype;
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imv == NULL || imv->supported_types == NULL)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return 0;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	vendor = type >> 8;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	subtype = type & 0xff;
571010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
572010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	for (i = 0; i < imv->num_supported_types; i++) {
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		unsigned int svendor, ssubtype;
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		svendor = imv->supported_types[i] >> 8;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ssubtype = imv->supported_types[i] & 0xff;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if ((vendor == svendor || svendor == TNC_VENDORID_ANY) &&
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY))
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return 1;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
580010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tncs_send_to_imvs(struct tncs_data *tncs, unsigned int type,
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      const u8 *msg, size_t len)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct tnc_if_imv *imv;
589010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	TNC_Result res;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMV(s)", msg, len);
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (imv = tncs->imv; imv; imv = imv->next) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (imv->ReceiveMessage == NULL ||
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    !tncs_supported_type(imv, type))
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			continue;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
598010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMV '%s'",
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   imv->name);
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		res = imv->ReceiveMessage(imv->imvID, tncs->connectionID,
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  (TNC_BufferReference) msg, len,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  type);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu",
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   (unsigned long) res);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tncs_batch_ending(struct tncs_data *tncs)
610010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles){
611010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	struct tnc_if_imv *imv;
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_Result res;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (imv = tncs->imv; imv; imv = imv->next) {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (imv->BatchEnding == NULL)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			continue;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: Call BatchEnding for IMV '%s'",
619010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			   imv->name);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		res = imv->BatchEnding(imv->imvID, tncs->connectionID);
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: BatchEnding: %lu",
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			   (unsigned long) res);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tncs_solicit_recommendation(struct tncs_data *tncs)
628010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles){
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct tnc_if_imv *imv;
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_Result res;
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (imv = tncs->imv; imv; imv = imv->next) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (tncs->imv_data[imv->imvID].recommendation_set)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			continue;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: Call SolicitRecommendation for "
637010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			   "IMV '%s'", imv->name);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		res = imv->SolicitRecommendation(imv->imvID,
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 tncs->connectionID);
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: SolicitRecommendation: %lu",
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   (unsigned long) res);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
646010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void tncs_init_connection(struct tncs_data *tncs)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct tnc_if_imv *imv;
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	int i;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (imv = tncs->imv; imv; imv = imv->next) {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs_imv_notify_connection_change(
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			imv, tncs->connectionID, TNC_CONNECTION_STATE_CREATE);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs_imv_notify_connection_change(
655010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			imv, tncs->connectionID,
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			TNC_CONNECTION_STATE_HANDSHAKE);
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < TNC_MAX_IMV_ID; i++) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(tncs->imv_data[i].imv_send);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs->imv_data[i].imv_send = NULL;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs->imv_data[i].imv_send_len = 0;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
664010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
665a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
666a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
667a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)size_t tncs_total_send_len(struct tncs_data *tncs)
668a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
669a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	int i;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size_t len = 0;
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	for (i = 0; i < TNC_MAX_IMV_ID; i++)
673a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		len += tncs->imv_data[i].imv_send_len;
674a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (tncs->tncs_message)
675a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		len += os_strlen(tncs->tncs_message);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return len;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
680010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)u8 * tncs_copy_send_buf(struct tncs_data *tncs, u8 *pos)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	int i;
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
684a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	for (i = 0; i < TNC_MAX_IMV_ID; i++) {
685a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (tncs->imv_data[i].imv_send == NULL)
686a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			continue;
687a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_memcpy(pos, tncs->imv_data[i].imv_send,
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  tncs->imv_data[i].imv_send_len);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		pos += tncs->imv_data[i].imv_send_len;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(tncs->imv_data[i].imv_send);
692010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		tncs->imv_data[i].imv_send = NULL;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs->imv_data[i].imv_send_len = 0;
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
696a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (tncs->tncs_message) {
697a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		size_t len = os_strlen(tncs->tncs_message);
698a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		os_memcpy(pos, tncs->tncs_message, len);
699a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		pos += len;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(tncs->tncs_message);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs->tncs_message = NULL;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
704010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	return pos;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
708a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)char * tncs_if_tnccs_start(struct tncs_data *tncs)
709a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
710a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	char *buf = os_malloc(1000);
711a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (buf == NULL)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->last_batchid++;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_snprintf(buf, 1000, IF_TNCCS_START, tncs->last_batchid);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return buf;
716010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
717a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
719a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)char * tncs_if_tnccs_end(void)
720a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	char *buf = os_malloc(100);
722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (buf == NULL)
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return NULL;
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	os_snprintf(buf, 100, IF_TNCCS_END);
725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	return buf;
726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tncs_get_type(char *start, unsigned int *type)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
731010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	char *pos = os_strstr(start, "<Type>");
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pos == NULL)
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return -1;
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	pos += 6;
735a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	*type = strtoul(pos, NULL, 16);
736a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	return 0;
737a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned char * tncs_get_base64(char *start, size_t *decoded_len)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	char *pos, *pos2;
743010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	unsigned char *decoded;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	pos = os_strstr(start, "<Base64>");
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (pos == NULL)
747a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return NULL;
748a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
749a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	pos += 8;
750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	pos2 = os_strstr(pos, "</Base64>");
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pos2 == NULL)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*pos2 = '\0';
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				decoded_len);
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	*pos2 = '<';
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (decoded == NULL) {
759a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
760a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
761a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
762cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)	return decoded;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static enum tncs_process_res tncs_derive_recommendation(struct tncs_data *tncs)
767010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles){
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	enum IMV_Action_Recommendation rec;
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct tnc_if_imv *imv;
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	TNC_ConnectionState state;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	char *txt;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: No more messages from IMVs");
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs->done)
776010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		return TNCCS_PROCESS_OK_NO_RECOMMENDATION;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs_solicit_recommendation(tncs);
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Select the most restrictive recommendation */
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (imv = tncs->imv; imv; imv = imv->next) {
783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		TNC_IMV_Action_Recommendation irec;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		irec = tncs->imv_data[imv->imvID].recommendation;
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (irec == TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (irec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE &&
788010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		    rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (irec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW &&
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Recommendation: %d", rec);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->recommendation = rec;
797010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	tncs->done = 1;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	txt = NULL;
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	switch (rec) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		txt = "allow";
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
806010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		txt = "isolate";
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		break;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		txt = "none";
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		state = TNC_CONNECTION_STATE_ACCESS_NONE;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	default:
815010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (txt) {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(tncs->tncs_message);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs->tncs_message = os_zalloc(200);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (tncs->tncs_message) {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			os_snprintf(tncs->tncs_message, 199,
824010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)				    "<TNCC-TNCS-Message><Type>%08X</Type>"
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    "<XML><TNCCS-Recommendation type=\"%s\">"
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    "</TNCCS-Recommendation></XML>"
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    "</TNCC-TNCS-Message>",
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    TNC_TNCCS_RECOMMENDATION, txt);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
832a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	for (imv = tncs->imv; imv; imv = imv->next) {
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs_imv_notify_connection_change(imv, tncs->connectionID,
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						  state);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
837010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	switch (rec) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case TNC_IMV_ACTION_RECOMMENDATION_ALLOW:
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return TNCCS_RECOMMENDATION_ALLOW;
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS:
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return TNCCS_RECOMMENDATION_NO_ACCESS;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE:
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNCCS_RECOMMENDATION_ISOLATE;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION:
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNCCS_RECOMMENDATION_NO_RECOMMENDATION;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	default:
847010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		return TNCCS_PROCESS_ERROR;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum tncs_process_res tncs_process_if_tnccs(struct tncs_data *tncs,
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					    const u8 *msg, size_t len)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
855a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	char *buf, *start, *end, *pos, *pos2, *payload;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int batch_id;
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	unsigned char *decoded;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	size_t decoded_len;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
860010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	buf = os_malloc(len + 1);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (buf == NULL)
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return TNCCS_PROCESS_ERROR;
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	os_memcpy(buf, msg, len);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	buf[len] = '\0';
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	start = os_strstr(buf, "<TNCCS-Batch ");
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	end = os_strstr(buf, "</TNCCS-Batch>");
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (start == NULL || end == NULL || start > end) {
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(buf);
870010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		return TNCCS_PROCESS_ERROR;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	start += 13;
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	while (*start == ' ')
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		start++;
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	*end = '\0';
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	pos = os_strstr(start, "BatchId=");
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pos == NULL) {
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		os_free(buf);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNCCS_PROCESS_ERROR;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
883010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pos += 8;
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (*pos == '"')
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		pos++;
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	batch_id = atoi(pos);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u",
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		   batch_id);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (batch_id != tncs->last_batchid + 1) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId "
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   "%u (expected %u)",
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   batch_id, tncs->last_batchid + 1);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(buf);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNCCS_PROCESS_ERROR;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->last_batchid = batch_id;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (*pos != '\0' && *pos != '>')
900010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		pos++;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (*pos == '\0') {
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(buf);
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return TNCCS_PROCESS_ERROR;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	pos++;
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	payload = start;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * <IMC-IMV-Message>
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 * <Type>01234567</Type>
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * <Base64>foo==</Base64>
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * </IMC-IMV-Message>
913a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	 */
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (*start) {
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		char *endpos;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		unsigned int type;
918010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		pos = os_strstr(start, "<IMC-IMV-Message>");
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (pos == NULL)
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			break;
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		start = pos + 17;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		end = os_strstr(start, "</IMC-IMV-Message>");
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (end == NULL)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			break;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*end = '\0';
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		endpos = end;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		end += 18;
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (tncs_get_type(start, &type) < 0) {
931010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			*endpos = '<';
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			start = end;
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			continue;
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		decoded = tncs_get_base64(start, &decoded_len);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (decoded == NULL) {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			*endpos = '<';
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			start = end;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			continue;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
943010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tncs_send_to_imvs(tncs, type, decoded, decoded_len);
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		os_free(decoded);
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		start = end;
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * <TNCC-TNCS-Message>
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * <Type>01234567</Type>
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * <XML><TNCCS-Foo type="foo"></TNCCS-Foo></XML>
955010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	 * <Base64>foo==</Base64>
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 * </TNCC-TNCS-Message>
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 */
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	start = payload;
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	while (*start) {
961a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		unsigned int type;
962a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		char *xml, *xmlend, *endpos;
963a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
964a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		pos = os_strstr(start, "<TNCC-TNCS-Message>");
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (pos == NULL)
966a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			break;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		start = pos + 19;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		end = os_strstr(start, "</TNCC-TNCS-Message>");
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (end == NULL)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			break;
971010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		*end = '\0';
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		endpos = end;
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		end += 20;
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (tncs_get_type(start, &type) < 0) {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			*endpos = '<';
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			start = end;
978a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			continue;
979a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
980a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x",
981a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			   type);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Base64 OR XML */
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		decoded = NULL;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xml = NULL;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		xmlend = NULL;
987010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		pos = os_strstr(start, "<XML>");
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (pos) {
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			pos += 5;
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			pos2 = os_strstr(pos, "</XML>");
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			if (pos2 == NULL) {
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				*endpos = '<';
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				start = end;
994a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				continue;
995a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			}
996a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			xmlend = pos2;
997a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			xml = pos;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else {
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			decoded = tncs_get_base64(start, &decoded_len);
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if (decoded == NULL) {
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				*endpos = '<';
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				start = end;
1003010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)				continue;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			}
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (decoded) {
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			wpa_hexdump_ascii(MSG_MSGDUMP,
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  "TNC: TNCC-TNCS-Message Base64",
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  decoded, decoded_len);
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			os_free(decoded);
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (xml) {
1015010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			wpa_hexdump_ascii(MSG_MSGDUMP,
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  "TNC: TNCC-TNCS-Message XML",
10172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  (unsigned char *) xml,
10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  xmlend - xml);
10192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		start = end;
1022a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
1023a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1024a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	os_free(buf);
1025a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs_batch_ending(tncs);
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs_total_send_len(tncs) == 0)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return tncs_derive_recommendation(tncs);
1030010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return TNCCS_PROCESS_OK_NO_RECOMMENDATION;
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct tnc_if_imv * tncs_parse_imv(int id, char *start, char *end,
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  int *error)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct tnc_if_imv *imv;
1039010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	char *pos, *pos2;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (id >= TNC_MAX_IMV_ID) {
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		wpa_printf(MSG_DEBUG, "TNC: Too many IMVs");
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv = os_zalloc(sizeof(*imv));
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (imv == NULL) {
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*error = 1;
1049010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		return NULL;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->imvID = id;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	pos = start;
10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Configured IMV: %s", pos);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pos + 1 >= end || *pos != '"') {
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' "
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   "(no starting quotation mark)", start);
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		os_free(imv);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1062a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pos++;
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pos2 = pos;
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (pos2 < end && *pos2 != '"')
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		pos2++;
1067010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	if (pos2 >= end) {
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' "
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			   "(no ending quotation mark)", start);
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		os_free(imv);
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return NULL;
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	*pos2 = '\0';
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->name = os_strdup(pos);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pos = pos2 + 1;
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (pos >= end || *pos != ' ') {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' "
1080010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			   "(no space after name)", start);
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(imv);
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return NULL;
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pos++;
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpa_printf(MSG_DEBUG, "TNC: IMV file: '%s'", pos);
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	imv->path = os_strdup(pos);
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return imv;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1092010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tncs_read_config(struct tncs_global *global)
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	char *config, *end, *pos, *line_end;
10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size_t config_len;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct tnc_if_imv *imv, *last;
10982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	int id = 0;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	last = NULL;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	config = os_readfile(TNC_CONFIG_FILE, &config_len);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (config == NULL) {
1104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration "
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   "file '%s'", TNC_CONFIG_FILE);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return -1;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	end = config + config_len;
11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	for (pos = config; pos < end; pos = line_end + 1) {
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		line_end = pos;
1112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		while (*line_end != '\n' && *line_end != '\r' &&
1113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		       line_end < end)
1114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			line_end++;
1115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		*line_end = '\0';
1116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (os_strncmp(pos, "IMV ", 4) == 0) {
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			int error = 0;
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			imv = tncs_parse_imv(id++, pos + 4, line_end, &error);
1121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			if (error)
1122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				return -1;
1123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			if (imv) {
1124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				if (last == NULL)
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					global->imv = imv;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				else
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					last->next = imv;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				last = imv;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			}
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	os_free(config);
1134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return 0;
11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct tncs_data * tncs_init(void)
11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct tncs_data *tncs;
1142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (tncs_global_data == NULL)
1144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return NULL;
1145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs = os_zalloc(sizeof(*tncs));
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs == NULL)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->imv = tncs_global_data->imv;
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs->connectionID = tncs_global_data->next_conn_id++;
1151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	tncs->next = tncs_global_data->connections;
1152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	tncs_global_data->connections = tncs;
1153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
11542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return tncs;
11552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void tncs_deinit(struct tncs_data *tncs)
11592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	int i;
1161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct tncs_data *prev, *conn;
1162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (tncs == NULL)
1164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < TNC_MAX_IMV_ID; i++)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		os_free(tncs->imv_data[i].imv_send);
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	prev = NULL;
1170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	conn = tncs_global_data->connections;
1171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	while (conn) {
1172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (conn == tncs) {
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			if (prev)
11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				prev->next = tncs->next;
11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			else
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				tncs_global_data->connections = tncs->next;
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			break;
11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
1179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		prev = conn;
1180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		conn = conn->next;
1181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
1182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	os_free(tncs->tncs_message);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(tncs);
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)int tncs_global_init(void)
1189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
1190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct tnc_if_imv *imv;
11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	tncs_global_data = os_zalloc(sizeof(*tncs_global_data));
11932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (tncs_global_data == NULL)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return -1;
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (tncs_read_config(tncs_global_data) < 0) {
1197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration");
1198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		goto failed;
1199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
1200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	for (imv = tncs_global_data->imv; imv; imv = imv->next) {
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (tncs_load_imv(imv)) {
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			wpa_printf(MSG_ERROR, "TNC: Failed to load IMV '%s'",
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   imv->name);
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			goto failed;
1206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		}
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)failed:
12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	tncs_global_deinit();
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return -1;
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void tncs_global_deinit(void)
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct tnc_if_imv *imv, *prev;
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tncs_global_data == NULL)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)	imv = tncs_global_data->imv;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (imv) {
12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		tncs_unload_imv(imv);
12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		prev = imv;
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		imv = imv->next;
12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		os_free(prev);
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	os_free(tncs_global_data);
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tncs_global_data = NULL;
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct wpabuf * tncs_build_soh_request(void)
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct wpabuf *buf;
12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 * Build a SoH Request TLV (to be used inside SoH EAP Extensions
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * Method)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	buf = wpabuf_alloc(8 + 4);
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (buf == NULL)
1249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)		return NULL;
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* Vendor-Specific TLV (Microsoft) - SoH Request */
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpabuf_put_be16(buf, 8); /* Length */
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpabuf_put_be16(buf, 0x02); /* TLV Type - SoH Request TLV */
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpabuf_put_be16(buf, 0); /* Length */
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return buf;
1261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
12622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct wpabuf * tncs_process_soh(const u8 *soh_tlv, size_t soh_tlv_len,
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 int *failure)
12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	wpa_hexdump(MSG_DEBUG, "TNC: SoH TLV", soh_tlv, soh_tlv_len);
1268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	*failure = 0;
1269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	/* TODO: return MS-SoH Response TLV */
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	return NULL;
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)