/*
	製作者　　安田　聖　7m3tjz/ad6gz
	
	変更履歴　　 2013.05.03　分散型管理サーバーシステム

	リターンコード
	正常				0x00
	コールサインが空白		0x01
	最初が空白			0x02
	英数字以外が含まれている		0x03
	機器名が空白か英字でない		0x04
	制限されているコールサイン		0x05
*/


#include	"dsgwd_pi.h"
#include	"callcheck.h"

	struct	CallCheckACL	*CallChkACLPnt;	/* コールサインチェック用ＡＣＬの開始ポインター */

char	callcheck(char callsign[])
{
	struct	CallCheckACL	*next;
	int	i;

	if (!memcmp (callsign, "       ", 7)) return 0x01;			/* コールサインのが空白 */
	if (!memcmp (callsign, "*******", 7)) return 0x03;		/* コールサインのが******* */
	if (callsign[0] == 0x20)	return 0x02;			/* 最初が空白 */
	if (!isalpha(callsign[7]) && (callsign[7] != 0x20)) return 0x04;	/* 空白もしくは英字でない */

	if (!CallCheck) return 0x00;
 
	if (!CallChkACLPnt) return 0x00;

	next = CallChkACLPnt;
	while (next)
	{
		for (i = 0 ; i < 8 ; i++)	/* 自局コールサインの１から７文字目を検査 */
		{
			if (next->callsign[i] == '$')				/* 数字のみ */
			{
				if (!isdigit(callsign[i])) goto next_check;		/* 数字でない */
			}
			else if (next->callsign[i] == '*')			/* 英字のみ */
			{
				if (!isalpha(callsign[i])) goto next_check;;	/* 英字でない */
			}
			else if (next->callsign[i] == '&')			/* 英数字 */
			{
				if (!isalnum(callsign[i])) goto next_check;;	/* 英数字でない */
			}
			else if (next->callsign[i] == '%')			/* 英字か空白 */
			{
				if (!isalpha(callsign[i]) && (callsign[i] != 0x20)) goto next_check;;	/* 英字でも空白でもない */
			}
			else if (next->callsign[i] != callsign[i])			/* 実際の文字で比較 */
			{
				goto next_check;;				/* 一致しない */
			}
		}
		if (next->acl == 'D') return 0x05;		/* Deny */
		if (next->acl == 'A') return 0x00;		/* Accept */
next_check:
		next = next->next_pnt;
	}
	return 0x05;
}

/*
	コールサインチェックのACLの読み込み
*/
void	loadCallCheckACL(void)
{
	char	buff[20];
	FILE	*acl;
	struct	CallCheckACL	*next;
	struct	CallCheckACL	*before;

	CallChkACLPnt = NULL;
	acl = fopen ("/etc/dsgwd_pi/callcheck.acl","r");
	if (!acl)
	{
		printf ("ERROR File not open /etc/dsgwd_pi/callcheck.acl\n");
		return;
	}
	next = NULL;

	while (fgets (buff, 19, acl))
	{
		if (buff[0] != '#')
		{
			before = next;
			next = malloc (sizeof (struct CallCheckACL));
			memcpy (next->callsign, buff, 9);
			next->next_pnt = NULL;
			if (before)
			{
				before->next_pnt = next;
			}
			else
			{
				CallChkACLPnt = next;
			}
		}
	}
	fclose (acl);
}

/*
	コールサインチェックのACLの再読み込み
*/
void	ReloadCallCheckACL(void)
{
	char	buff[20];
	FILE	*acl;
	struct	CallCheckACL	*next;
	struct	CallCheckACL	*before;
	struct	CallCheckACL	*old;


	acl = fopen ("/etc/dsgwd_pi/callcheck.acl","r");
	next = NULL;
	old = CallChkACLPnt;

	while (fgets (buff, 19, acl))
	{
		if (buff[0] != '#')
		{
			before = next;
			next = malloc (sizeof (struct CallCheckACL));
			memcpy (next->callsign, buff, 9);
			next->next_pnt = NULL;
			if (before)
			{
				before->next_pnt = next;
			}
			else
			{
				CallChkACLPnt = next;
			}
		}
	}
	fclose (acl);

	while (old)
	{
		next = old->next_pnt;
		free (old);
		old = next;
	}
}

