/**************************************************
OpengateM - a MAC address authentication system
 module to control management database

 table for the list of mac addresses
 table for the list of usage log
 implemented with MySql 

Copyright (C) 2011 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"
#include <mysql.h>


MYSQL mysql;

/******************************************
initialize management db
******************************************/
int initMngDb(void){

  /* set parameters */
  char *server = GetConfValue("MySqlDb/Server");
  char *user =  GetConfValue("MySqlDb/User");
  char *password = GetConfValue("MySqlDb/Password");
  char *database = GetConfValue("MySqlDb/Database");
  my_bool reconnect;

/* initialize mysql */
  mysql_library_init(-1,NULL,NULL);
  if(mysql_init(&mysql)==NULL){
     err_msg("ERR at %s#%d: mysql init: %s",__FILE__,__LINE__,
	     mysql_error(&mysql));
     terminateProg(0);
  }

  /* Connect to database */
  if (!mysql_real_connect(&mysql, server,
			   user, password, database, 0, NULL, 0)) {
    err_msg("ERR at %s#%d: mysql connect: %s",__FILE__,__LINE__,
	     mysql_error(&mysql));
    terminateProg(0);
  }

  /* set auto-reconnect true */
  reconnect = TRUE;
  mysql_options(&mysql, MYSQL_OPT_RECONNECT, &reconnect);  

  return TRUE;
}

/******************************************
close management db
******************************************/
void closeMngDb(void){
  mysql_close(&mysql);
  mysql_library_end();
}

/******************************************
query data from management db
input=macAddress
return value: 1=found,0=not found,-1=query error
******************************************/
int queryMacFromMngDb(char* macAddress, char* userId, char* extraId){
  MYSQL_RES *res;
  MYSQL_ROW row;
  int found=FALSE;
  char queryStr[BUFFMAXLN];

  /* set default values userId="?", extraId=""  */
  userId[0]='?'; userId[1]='\0'; extraId[0]='\0';
 
  /* prepare query string */
  snprintf(queryStr, BUFFMAXLN, 
	   "select userId,extraId from macaddrs "
	   "where macAddress='%s' and status='A' and limitDate>now()",
	   macAddress);

  /* send SQL query */
  if (mysql_query(&mysql, queryStr)){
     err_msg("ERR at %s#%d: mysql query: %s",__FILE__,__LINE__,
	     mysql_error(&mysql));
     return ERROR;
  }

  res = mysql_use_result(&mysql);
  
  /* output table name */
  row = mysql_fetch_row(res);

  /* if not found, return false */
  if(row==NULL)  found=FALSE;

  /* if found */
  else {
    strcpy(userId, row[0]);
    strcpy(extraId,row[1]);
    found=TRUE;
  }

  mysql_free_result(res);
  return found;
}

/******************************************
put gate-open log to management db 
******************************************/
int putOpenToMngDb(char* macAddress){

  char queryStr[BUFFMAXLN];
  struct utsname uts;

  /* get domain name */
  uname(&uts);

  /* prepare query string */
  snprintf(queryStr, BUFFMAXLN, 
	   "insert into sessionmd "
	   "(macAddress, gatewayName, openTime, closeTime) "
	   "values ('%s','%s', now(), 0)",
	   macAddress, uts.nodename);

  /* send SQL query */
  if (mysql_query(&mysql, queryStr)){
     err_msg("ERR at %s#%d: mysql query: %s",__FILE__,__LINE__,
	     mysql_error(&mysql));
     return FALSE;
  }

  return TRUE;
}

/******************************************
put gate-close log to management db
******************************************/
int putCloseToMngDb(char* macAddress){

  char queryStr[BUFFMAXLN];

  /* prepare query string */
  snprintf(queryStr, BUFFMAXLN, 
	   "update sessionmd set closeTime=now() "
	   "where macAddress='%s' and closeTime=0", macAddress);

  /* send SQL query */
  if (mysql_query(&mysql, queryStr)){
     err_msg("ERR at %s#%d: mysql query: %s",__FILE__,__LINE__,
	     mysql_error(&mysql));
     return FALSE;
  }

  return TRUE;

}

/******************************************
put MAC-IP pair to management db
******************************************/
int putMacIpPairToMngDb(char* macAddress, char* ipAddress){

  char queryStr[BUFFMAXLN];
  struct utsname uts;

  /* get domain name */
  uname(&uts);

  /* prepare query string */
  snprintf(queryStr, BUFFMAXLN, 
	   "insert into macippair "
	   "(macAddress, ipAddress, findTime) "
	   "values ('%s','%s', now())",
	   macAddress, ipAddress);

  /* send SQL query */
  if (mysql_query(&mysql, queryStr)){
     err_msg("ERR at %s#%d: mysql query: %s",__FILE__,__LINE__,
	     mysql_error(&mysql));
     return FALSE;
  }

  return TRUE;
}

/*******************************************
 get next mac address from watchlist table in management db
 (watchlist is the list of mac addresses needed specific reporting, 
  it is needless in normal condition. )
 the first call of this fuction executes query command and gets the first row 
 the following call gets the next row of the first call result
 if end of row, return false
*******************************************/
int getNextRecordFromWatchlistTableInMngDb(char* macAddress){

  static MYSQL_RES *res=NULL;
  MYSQL_ROW row;
  char queryStr[BUFFMAXLN];

  /* set default values */
  macAddress[0]='\0';

  /* if do not get result yet */
  if(res==NULL){

    /* prepare query string */
    snprintf(queryStr, BUFFMAXLN, 
	     "select macAddress from watchlist where reporting='Y'" );

    /* send SQL query */
    if (mysql_query(&mysql, queryStr)){
      err_msg("ERR at %s#%d: mysql query: %s",__FILE__,__LINE__,
	      mysql_error(&mysql));
      return FALSE;
    }
    
    /* store result */
    res = mysql_store_result(&mysql);
  }

  /* output table name */
  row = mysql_fetch_row(res);

  /* if found, return values */
  if(row!=NULL){
    strlcpy(macAddress, row[0],ADDRMAXLN);
    return TRUE;
  }
  /* if not found, free memory area */
  else{
    mysql_free_result(res);
    return FALSE;
  }
}

/***************************************
If the watchlist table includes a record matched to ALL, return TRUE.
***************************************/
int isAllFoundInWatchlistTable(void){
  MYSQL_RES *res;
  MYSQL_ROW row;
  char queryStr[BUFFMAXLN];
  int found=FALSE;

  /**** search "ALL" ****/
  /* prepare query string */
  snprintf(queryStr, BUFFMAXLN, 
	   "select macAddress from watchlist "
	   "where macAddress='ALL'");

  /* send SQL query */
  if (mysql_query(&mysql, queryStr)){

    /* lost of 'watchlist table' is ignored */ 
    if(strcmp(mysql_error(&mysql), 
	      "Table 'opengatem.watchlist' doesn't exist")!=0){
     err_msg("ERR at %s#%d: mysql query: %s",__FILE__,__LINE__,
	     mysql_error(&mysql));
    }
    return ERROR;
  }


  res = mysql_use_result(&mysql);

  /* output table name */
  row = mysql_fetch_row(res);

  /* if not found, row is NULL */
  if(row==NULL)  found=FALSE;
  else found=TRUE;

  mysql_free_result(res);

  /* if any one found, return TRUE, */
  return found;
}

/********************************************
 routines for debugging output
********************************************/
int QueryMacFromMngDb(char* macAddress, char* userId, char* extraId){
  int ret;
  if(debug>1) err_msg("DEBUG:=>queryMacFromMngDb(%s)", macAddress);
  ret = queryMacFromMngDb(macAddress, userId, extraId);
  if(debug>1) err_msg("DEBUG:(%d)<=queryMacFromMngDb(,%s,%s)",ret,userId,extraId);
  return ret;
}
int InitMngDb(void){
  int ret;
  if(debug>1) err_msg("DEBUG:=>initMngDb()");
  ret=initMngDb();
  if(debug>1) err_msg("DEBUG:(%d)<=closeMngDb()",ret);
  return ret;
}
void CloseMngDb(void){
  if(debug>1) err_msg("DEBUG:=>closeMngDb()");
  closeMngDb();
  if(debug>1) err_msg("DEBUG:<=closeMngDb()");
}

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

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

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

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

int IsAllFoundInWatchlistTable(void){
  int ret;
  if(debug>1) err_msg("DEBUG:=>isAllFoundInWatchlistTable()");
  ret = isAllFoundInWatchlistTable();
  if(debug>1) err_msg("DEBUG:(%d)<=isAllFoundInWatchlistTable()", ret);
  return ret;
}

