ClearBox Server™ v1.2 Developer's Guide

Step 7. Processing Accounting Records

In this step you will make server extension process accounting packets and store information about user sessions in the database. Implementation will be rather simple and will not process Update and Start records - Stop records only.

1. Implement ITACACSAccounting and IRADIUSAccounting interfaces. Right-click CMyFirst class in ClassView, select Implement Interface... from context menu. Click Add Typelib, Browse and select tacradserver.tlb from /SDK directory of ClearBox Server installation. Check IRADIUSAccounting and ITACACSAccounting interfaces and click OK.

2. Add protected member function FindRADAttribute to CMyFirst class. Its declaration must look like following:

int CMyFirst::FindRADAttribute(BYTE attrID, const RADIUS_ATTRIBUTE *pAttributes, int attrNum)
{
	for (int i=0;i<attrNum;i++)
	{
		if (pAttributes[i].type==attrID)
			return i;
	}

	return -1;
}

3. Add protected member function FindTACAttribute to CMyFirst class with the following declaration:

int CMyFirst::FindTACAttribute(LPCWSTR attr, const AVPAIR *avPairs, int pairsNum)
{
	for (int i=0;i<pairsNum;i++)
	{
		if (wcscmp(avPairs[i].attribute,attr)==0)
			return i;
	}

	return -1;
}

4. Add protected member function InsertStopRecord to CMyFirst class. It will be used by RADIUS and TACACS+ ProcessAccounting methods to insert new record in the Accounting table as this code is shared by both protocols.

HRESULT CMyFirst::InsertStopRecord(BSTR user, int elapsed, int bytesIn, int bytesOut)
{
	CCommand<CDynamicAccessor> cmd;
	TCHAR cmdBuf[200];

	_stprintf(cmdBuf,_T("SELECT ID FROM Users WHERE Name='%s'"),user);
	HRESULT hRes=cmd.Open(m_DB.Session(),cmdBuf);
	if (FAILED(hRes))
		return hRes;
	if (cmd.MoveFirst()!=S_OK)
		return E_FAIL;

	int userID=0;
	cmd.GetValue(1,&userID);

	_stprintf(cmdBuf,
		_T("insert into accounting (UserID, StopTime,  Elapsed, BytesIn, BytesOut)\
		values(%d,now(),%d,%d,%d)"),userID,elapsed, bytesIn,bytesOut);

	CCommand<CNoAccessor,CNoRowset> insCmd;
	hRes=insCmd.Open(m_DB.Session(),cmdBuf);
	if (FAILED(hRes))
		return hRes;
		
	return S_OK;
}

5. Find ProcessAccounting method with USERINFOLITE as second parameter type - that is member function of IRADIUSAccounting. Replace its declaration with the following code:

STDMETHOD(ProcessAccounting)(LONG tag, USERINFOLITE * userInf, ULONG attributesNum, 
	RADIUS_ATTRIBUTE * inpAttributes, USERADDRESS * userAddr, ACCOUNTINGSTATUS * status)
{
	if (userAddr == NULL)
		return E_POINTER;
		
	if (status == NULL)
		return E_POINTER;

	*status=A_ERROR;

	int ind=FindRADAttribute(40,inpAttributes,attributesNum);
	if (ind==-1)
		return S_OK;

	int acctType=inpAttributes[ind].dwValue;
	if (acctType!=2) // Accounting-Stop
	{
		*status=A_OK;
		return S_OK;
	}

	int bytesIn=0;
	// "Acct-Input-Octets"
	ind=FindRADAttribute(42,inpAttributes,attributesNum);
	if (ind!=-1)
		bytesIn=inpAttributes[ind].dwValue;

	int bytesOut=0;
	// "Acct-Output-Octets"
	ind=FindRADAttribute(43,inpAttributes,attributesNum);
	if (ind!=-1)
		bytesOut=inpAttributes[ind].dwValue;

	int sessionTime=0;
	// "Acct-Session-Time"
	ind=FindRADAttribute(46,inpAttributes,attributesNum);
	if (ind!=-1)
		sessionTime=inpAttributes[ind].dwValue;

	HRESULT hRes=InsertStopRecord(userInf->userName,sessionTime,bytesIn,bytesOut);
	if (FAILED(hRes))
		return hRes;
		
	*status=A_OK;	
	return S_OK;
}

6. Find another ProcessAccounting method belonging to ITACACSAccounting. Replace its declaration with the following lines of code:

STDMETHOD(ProcessAccounting)(LONG tag, TAC_AUTHORPARAMS * accParams, ULONG avSize, AVPAIR * avPairs, 
	VARIANT_BOOL start, VARIANT_BOOL update, USERADDRESS * userAddr, ACCOUNTINGSTATUS * status)
{
	if (userAddr == NULL)
		return E_POINTER;
			
	if (status == NULL)
		return E_POINTER;
	
	*status=A_ERROR;
	if (start!=VARIANT_FALSE)
	{
		*status=A_OK;
		return S_OK;
	}

	int bytesIn=0;
	int ind=FindTACAttribute(L"bytes_in",avPairs,avSize);
	if (ind!=-1)
		bytesIn=_wtoi(avPairs[ind].value);

	int bytesOut=0;
	ind=FindTACAttribute(L"bytes_out",avPairs,avSize);
	if (ind!=-1)
		bytesOut=_wtoi(avPairs[ind].value);

	int sessionTime=0;
	ind=FindTACAttribute(L"elapsed_time",avPairs,avSize);
	if (ind!=-1)
		sessionTime=_wtoi(avPairs[ind].value);

	HRESULT hRes=InsertStopRecord(accParams->user,sessionTime,bytesIn,bytesOut);
	if (FAILED(hRes))
		return hRes;
		
	*status=A_OK;	
	return S_OK;
}

Go to the next step.


© 2001-2003 XPerience Technologies. www.xperiencetech.com

Created by chm2web html help conversion utility.