/* vi: set tabstop=4 nocindent noautoindent: */

/**  
	IP Address Tool
		
				by Fumi Iseki '05 09/21
*/



#include "ipaddr_tool.h"




/**
tList*  read_ipaddr_file(char* fn)

	機能：ファイルから IPアドレスを読み込んで，[IPアドレス]/[ネットマスク]　の形式に
		  変換して，リストに格納する．FQDNはIPアドレスに変換される
		  FQDNでないドメイン名，文字列は / 以後を無視して文字列のままリストに格納する．

		  データの読み取り時に次の処理が行なわれる．
			前後の空白,CR,LFは削除される
			空行は無視される．
			# 以降は無視される．

	引数：fn  -- ファイル名

	戻り値：リストへのポインタ
*/
tList*  read_ipaddr_file(char* fn)
{
	tList* lp;
	tList* lt;

	lp = read_tList_file(fn, 2);
	if (lp==NULL) return NULL;

	lt = to_ipaddress_list(lp);
	del_all_tList(&lp);

	return lt;
}





/**
tList*  read_ipaddr_fp(FILE* fp)

	機能：ファイルから IPアドレスを読み込んで，[IPアドレス]/[ネットマスク]　の形式に
		  変換して，リストに格納する．FQDNはIPアドレスに変換される
		  FQDNでないドメイン名，文字列は / 以後を無視して文字列のままリストに格納する．

		  データの読み取り時に次の処理が行なわれる．
			前後の空白,CR,LFは削除される
			空行は無視される．
			# で始まる，または 空白(複数)# で始まる行は無視される．

	引数：fp  -- ファイルポインタ

	戻り値：リストへのポインタ
*/
tList*  read_ipaddr_fp(FILE* fp)
{
	tList* lp;
	tList* lt;

	lp = read_tList_fp(fp, 1);
	if (lp==NULL) return NULL;

	lt = to_ipaddress_list(lp);
	del_all_tList(&lp);

	return lt;
}




/**
tList*  to_ipaddress_list(tList* lp)

	機能：リスト中の IPアドレスを [IPアドレス]/[ネットマスク]　の形式に
		  変換して，新しいリストに格納する．FQDNはIPアドレスに変換される
		  変換に to_address_num8() を使用．CIDER対応．
		  FQDNでないドメイン名，文字列は / 以後を無視して文字列のまま
		  新しいリストに格納する．
		  後の is_host_in_list()などを高速に行なうための前処理

	引数：変換前（ファイルなどから読み込んだまま）のデータの入ったリスト

	戻り値：変換して新しく生成したリスト．

*/
tList*  to_ipaddress_list(tList* lp)
{
	unsigned char* num;
	char*          addr;
	tList* ls = NULL;
	tList* lt = NULL;

	if (lp==NULL) return NULL;
	if (lp->ldat.key.buf==NULL) return NULL;

	while (lp!=NULL) {
		if (lp->ldat.key.buf!=NULL && strlen((const char*)lp->ldat.key.buf)>0) {
			if ((lp->ldat.key.buf)[0]!='#') {
				num = to_address_num8((char*)lp->ldat.key.buf, 1);
				if (num!=NULL) {
					addr = to_address_char8(num);
					free(num);
					if (addr!=NULL) {
						ls = add_tList_node_str(ls, addr, NULL);
						free(addr);
					}	// ここで addr==NULL となる場合はメモリ不足のみ
				}
				else {
					addr = awk((char*)lp->ldat.key.buf, '/', 1);
					if (addr!=NULL) {
						int i = 0;
						while(addr[i]!='\0' && addr[i]!=',' && addr[i]!=' ') i++;
						addr[i] = '\0';
						ls = add_tList_node_str(ls, addr, NULL);
						free(addr);
					}
				}
				if (lt==NULL) lt = ls;
			}
		}
		lp = lp->next;
	}
	
	return lt;
}






/**
int  is_host_in_list(tList* lp, unsigned char* num, char* hname)

	機能：リストlpの キー部に格納されている ホスト情報と num, hname が同じネットワークに属するか
		　どうかをチェックする．num と hname はどちらか一方が指定されていれば十分である．
		  先ず，lpのキー部（FQDN）と hname が比較される．つまり，キー部がドメイン名の一部の
		  場合は hnameと比較する（後方一致）．
		　次に，lpのキー部がドメイン名でない場合（IPアドレスの場合）は num と比較される．
	
	引数：lp    -- チェックするIPアドレス（文字列）の格納されているリスト．
		  num   -- 比較するIPアドレス（1byte unsigned 整数型）4Byte
			       8Byte型(addr/mask)でも作動するが，ネットマスク部は無視する．
		  hname -- 比較するホスト名（文字列）．通常は numから逆引きされたもの．

	戻り値：FALSE -- リスト中に同じネットワークに属するエントリは存在しない．
			TRUE  -- リスト中に同じネットワークに属するエントリが存在する．
*/
int  is_host_in_list(tList* lp, unsigned char* num, char* hname)
{
	unsigned char* addr;

	if (lp==NULL) return FALSE;
	if (lp->ldat.key.buf==NULL) return FALSE;
	if (hname==NULL && num==NULL) return FALSE;

	while (lp!=NULL) {
		if (lp->ldat.key.buf!=NULL && strlen((const char*)lp->ldat.key.buf)>0) {
			addr = to_address_num8((char*)lp->ldat.key.buf, 0);
			if (addr==NULL && hname!=NULL) {
				if (!strnrvscmp((const char*)lp->ldat.key.buf, hname, strlen((const char*)lp->ldat.key.buf))) return TRUE;
			}
			else if(addr!=NULL && num!=NULL) {
				if (is_same_network_num(addr, num, &(addr[4]))) return TRUE;
			}
		}
		lp = lp->next;
	}
	
	return FALSE;
}







/**
int  is_ipaddr_num_in_list(tList* lp, unsigned char* num)

	機能：リストlpの キー部に格納されている ホスト情報と num が同じネットワークに属するか
		　どうかをチェックする．
		  リストのキー部がFQDNであってもチェック可能．
	
	引数：lp  -- チェックするIPアドレス（文字列）の格納されているリスト．
		  num -- 比較するIPアドレス（1byte unsigned 整数型）4Byte
			     8Byte型(addr/mask)でも作動するが，ネットマスク部は無視する．

	戻り値：FALSE -- リスト中に同じネットワークに属するエントリは存在しない．
			TRUE  -- リスト中に同じネットワークに属するエントリが存在する．

*/
int  is_ipaddr_num_in_list(tList* lp, unsigned char* num)
{
	unsigned char* addr;

	if (lp==NULL || num==NULL) return FALSE;
	if (lp->ldat.key.buf==NULL) return FALSE;

	while (lp!=NULL) {
		if (lp->ldat.key.buf!=NULL && strlen((const char*)lp->ldat.key.buf)>0) {
			addr = to_address_num8((char*)lp->ldat.key.buf, 1);
			if (addr!=NULL) {
				if (is_same_network_num(num, addr, &(addr[4]))) return TRUE;
			}
		}
		lp = lp->next;
	}
	
	return FALSE;
}






/**
void  print_address_in_list(FILE* fp, tList* lp)

	機能：リスト中のドメイン名，またはIPアドレスを表示する．
		  FQDNはIPアドレスに変換して表示する．

	引数：ドメイン名またはIPアドレスをキー部に格納したリストへのポインタ

*/
void  print_address_in_list(FILE* fp, tList* lp)
{
	unsigned char* addr;

	while (lp!=NULL) {
		if (lp->ldat.key.buf!=NULL && strlen((const char*)lp->ldat.key.buf)>0) {
			addr = to_address_num8((char*)lp->ldat.key.buf, 1);
			if (addr!=NULL) {	
				fprintf(fp, "[%d.%d.%d.%d/%d.%d.%d.%d]\n", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],addr[6],addr[7]);
			}
			else { 		// 恐らくドメイン名
				fprintf(fp, "[%s]\n", lp->ldat.key.buf);
			}
		}
		lp = lp->next;
	}
	return;
}





