/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/

#include	<stdlib.h>

#include	<winsock2.h>
#include	<Ws2tcpip.h>

#include	"memory_debug.h"
#include    "task.h"
#include	"utils.h"
#include	"server.h"


extern SEM netutils_lock;


void
init_access_permission(ACCESS_PERMISSION * ap)
{
	ap->head = ap->tail = 0;
}

void
free_access_list(ACCESS_PERMISSION * ap)
{
ACCESS_LIST * al;
	for ( ; ap->head ; ) {
		al = ap->head;
		ap->head = al->next;

		if ( al->domain )
			d_f_ree(al->domain);
		d_f_ree(al);
	}
}

void
insert_access_list(
	ACCESS_PERMISSION * ap,
	int	ip,
	int	mask,
	char *	domain,
	int	type)
{
ACCESS_LIST * al;
	al = d_alloc(sizeof(*al),339);
	al->ip = ip;
	al->mask = mask;
	if ( ip )
		al->domain = 0;
	else if ( domain == 0 ) {
		al->ip = 0;
		al->mask = 0;
		al->domain = 0;
	}
	else {
		al->domain = copy_str(domain);
	}
	al->type = type;

	al->next = 0;
	if ( ap->head ) {
		ap->tail->next = al;
		ap->tail = al;
	}
	else {
		ap->head = ap->tail = al;
	}
}


int
check_permission(ACCESS_PERMISSION * ap,int ip)
{
struct hostent * hp;
char ** q;
ACCESS_LIST * al;
int ret;
int len1,len2;
char local_hostname[256];
	ip = htonl(ip);

//	if(ip==inet_addr("127.0.0.1")){
//		return AP_ALLOW;
//	}
	
	get_localhostname(local_hostname);

/*
	{
	struct sockaddr_in addr;
	char *host;
	char *serv;
	
	addr.sin_family = AF_INET;
	addr.sin_port = 0;
	addr.sin_addr.s_addr = ip;
	getnameinfo(
	  (const struct sockaddr *)&addr,
	  sizeof(addr),
	  host,
	  NI_MAXHOST,
	  serv,
	  NI_MAXSERV,
	  0);
	}
*/

	lock_task(netutils_lock);
	hp = gethostbyaddr((char*)&ip,sizeof(ip),AF_INET);
	for ( al = ap->head ; al ; al = al->next ) {
		if ( al->ip ) {
			if ( (ip&al->mask) == al->ip ){
				ret = al->type;
				goto end;
			}
			continue;
		}
		if ( al->domain == 0 )
			return al->type;
		if ( hp == 0 )
			continue;
		len1 = strlen(al->domain);
		q = hp->h_aliases;

		if ( *q == 0 )
			q = &hp->h_name;

		/*if(strcmp(al->domain,"localhost")==0){
			char **tmp;
			for(tmp=hp->h_addr_list; *tmp; ++tmp){
				if( ((*tmp)[0] == 127) && 
					((*tmp)[1] == 0) && 
					((*tmp)[2] == 0) && 
					((*tmp)[3] == 1) ){
					ret = al->type;
					goto end;
				}
			}
		}
		*/
		for ( ; ; ) {
			len2 = strlen(*q);
			if ( len2 < len1 )
				goto next;
			if ( strcmp(&(*q)[len2-len1], al->domain) == 0) {
				if ( len2 == len1 ){
					ret = al->type;
					goto end;
				}
				if ( (*q)[len2-len1-1] == '.' ){
					ret = al->type;
					goto end;
				}
			}
		next:
			if ( q == &hp->h_name )
				break;
			else {
				q ++;
				if ( *q == 0 )
					q = &hp->h_name;
			}
		}
	}
	ret = AP_DENY;
end:
	unlock_task(netutils_lock, "check_permission");
	return ret;

/*
int len1,len2;
int ip_addr;
int retry_cnt;
int delay,d;

	ip_addr = htonl(ip);
	delay = 0;
	retry_cnt = 3;
netutils_lock = 0;
retry:
	lock_task(netutils_lock);
	sethostent_rr(0);
	hp = gethostbyaddr_rr((char*)&ip_addr,sizeof(ip),AF_INET);
	endhostent_rr();
	unlock_task(netutils_lock,"check_permission");
	if ( hp == 0 && retry_cnt > 0 ) {
		if ( delay == 0 ) {
			if ( stream_gc )
				(*stream_gc)();
			delay = 1;
			goto retry;
		}
		retry_cnt --;
		sleep(delay);
		if ( stream_gc )
			(*stream_gc)();
		d = rand() % delay;
		delay = (delay << 1 ) + d;
		goto retry;
	}

	for ( al = ap->head ; al ; al = al->next ) {
		if ( al->ip ) {
			if ( (ip&al->mask) == al->ip ) {
				return al->type;
			}
			continue;
		}
		if ( al->domain == 0 ) {
			return al->type;
		}
		if ( hp == 0 )
			continue;
		len1 = strlen(al->domain);
		q = hp->h_aliases;
		if ( *q == 0 )
			q = &hp->h_name;
		for ( ; ; ) {
			len2 = strlen(*q);
			if ( len2 < len1 )
				goto next;
			if ( strcmp(&(*q)[len2-len1],al->domain)
				== 0 ) {
				if ( len2 == len1 ) {
					return al->type;
				}
				if ( (*q)[len2-len1-1] == '.' ) {
					return al->type;
				}
			}
	next:
			if ( q == &hp->h_name )
				break;
			else {
				q ++;
				if ( *q == 0 )
					q = &hp->h_name;
			}
		}
	}
return AP_DENY;
*/

}





