/**************************************************
OpengateM - a MAC address authentication system
 module to control cache for watchlist

  the cache holds the temporary copy of watchlist table existing in Management DB.
  the cache is prepared at reloading the daemon.
  Implemented with HashTable.
  HashTable: Key= MAC Address, Val= none

 The watchlist table has the data for specific syslog reporting
 When a address in the list is used, syslog message with 'WARNING' property is write out.

Copyright (C) 2014 Opengate Project Team
Written by Yoshiaki Watanabe

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

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.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Email: watanaby@is.saga-u.ac.jp
**************************************************/
#include "opengatemd.h"

/* HashTable to store MacAddress->none */
static DB* watchlistHash;

/* specific record is included in the watchlist table */
static int foundAll=FALSE;
static int cacheItemCount=0;

/****************************************
initialize watchlist Cache and load from MySQL
****************************************/
void initWatchlistCache(void) {
  char macAddress[ADDRMAXLN];

  /* prepare hash table */
  if((watchlistHash = dbopen(NULL, O_CREAT | O_RDWR, 0644, DB_HASH, NULL)) == NULL) {
    err_msg("ERR at %s#%d: fail to open watchlist hash table",__FILE__,__LINE__);
    terminateProg(0);
  }

  /* if "ALL" record is included in the table, skip address loading */
  foundAll=IsAllFoundInWatchlistTable();    
  if(foundAll) return;

  /* read MySQL and insert to hash */
  while(GetNextRecordFromWatchlistTableInMngDb(macAddress)){
    AddWatchlistCacheItem(macAddress);
    cacheItemCount++;
  }
}

/****************************************
add an item to watchlist cache 
****************************************/
int addWatchlistCacheItem(char* macAddress) {

  DBT hashKey;
  DBT hashVal;
  char hashValueStr[]="";

  /* check address format */
  if(isNull(macAddress)) return FALSE;
  if(!ReFormatMacAddr(macAddress)) return FALSE;

  /** setup hash key **/
  /* hash key : string of mac address  */  
  hashKey.data = macAddress;
  hashKey.size = strlen(macAddress) + 1;

  /** setup hash value **/
  /* hash value : "" */
  hashVal.data = hashValueStr;
  hashVal.size = 1;    
  if(watchlistHash->put(watchlistHash, &hashKey, &hashVal, 0) == -1) {
    err_msg("ERR at %s#%d: fail to put into hash table",__FILE__,__LINE__);
    return FALSE;
  }

  return TRUE;
}

/****************************************
if address is found in cache return true,
else return error.
****************************************/
int isFoundInWatchlistCache(char* macAddress){

  DBT hashKey;
  DBT hashVal;
  int ret;

  /* if cache is empty, return false */
  if(cacheItemCount==0) return FALSE;

  /* if watchlist table includes 'ALL' record, return true */
  /* if searching the 'ALL' record is failed, return error */
  if(foundAll==TRUE) return TRUE;
  if(foundAll==ERROR) return ERROR;

  /* if null or illegal form, return */
  if(isNull(macAddress)) return ERROR;
  if(!ReFormatMacAddr(macAddress)) return ERROR;

  /***** get hashed item matched to the indicated mac */
  hashKey.data = macAddress;
  hashKey.size = strlen(macAddress) + 1;
  memset(&hashVal, 0, sizeof(DBT));
  ret=watchlistHash->get(watchlistHash, &hashKey, &hashVal, 0);

  /* get is failed, return false */
  if(ret!=0) return FALSE;

  /* get is successed */
  return TRUE;
}

/****************************************
Memory free for watchlist Cache
****************************************/
void freeWatchlistCache(void) {

  watchlistHash->close(watchlistHash);
}


/****************************************************
 routines for debugging putput
 ***************************************************/
void InitWatchlistCache(void) {
  if(debug>1) err_msg("DEBUG:=>initWatchlistCache( )");
  initWatchlistCache();
  if(debug>1) err_msg("DEBUG:<=initWatchlistCache( )");
}

int AddWatchlistCacheItem(char* macAddress) {
  int ret;
  if(debug>1) err_msg("DEBUG:=>addWatchlistCacheItem(%s)",
		      macAddress);
  ret = addWatchlistCacheItem(macAddress);
  if(debug>1) err_msg("DEBUG:(%d)<=addWatchlistCacheItem( )",ret);
  return ret;
}

int IsFoundInWatchlistCache(char* macAddress){
  int ret;
  if(debug>1) err_msg("DEBUG:=>isFoundInWatchlistCache(%s)", macAddress);
  ret = isFoundInWatchlistCache(macAddress);
  if(debug>1) err_msg("DEBUG:(%d)<=isFoundInWatchlistCache()",ret);
  return ret;
}

void FreeWatchlistCache(void) {
  if(debug>1) err_msg("DEBUG:=>freeWatchlistCache()");
  freeWatchlistCache();
  if(debug>1) err_msg("DEBUG:<=freeWatchlistCache()");
}
