/*
 * mysql.c	Functions to access the MYSQL database. 
 *
 * Much of the Mysql connection and accounting code was taken from 
 * Wim Bonis's (bonis@kiss.de) accounting patch to livingston radius
 * 2.01. His patch can be found at:
 *
 *       ftp://ftp.kiss.de/pub/unix/livingston/mysql-patches.tgz
 *
 * Version:	@(#)mysql.c  1.10  25-Sep-1998  oyarzun@wilmington.net
 * 
 * mysqlRadius OpenISP Project modifications:
 *
 * $Id: mysql.c 1 2006-03-06 22:05:41Z root $
 * sql.log turned off
 * via define SQL_LOG
 *
 * 12/2002 ggw SMTP_RELAY option. Has compile time login info for mysqlSendmail db!
 * uSource=3,72 hrs.  uSource=2,30mins for qualcomm qpopper mysqlSendmail version
 *
 * 8/2004 ggw Got rid of nasty strcpy security and error generating data
 *
 */

//No please...
//#define SQL_LOG
//
//Use with mysqlSendmail.tAccess subsystem
//#define SMTP_RELAY

//Usually you can run in production mode without this
//After verification
//#define LOGFILE_DEBUG

#ifdef USEMYSQL 

#include	<sys/types.h>
#include	<sys/socket.h>
#include	<sys/time.h>
#include	<netinet/in.h>

#include	<stdio.h>
#include	<stdlib.h>
#include	<netdb.h>
#include	<pwd.h>
#include	<time.h>
#include	<ctype.h>
#include	<strings.h>

#include        <mysql/mysql.h>


#include	"radiusd.h"

#define MYSQL_AUTH 1
#define MYSQL_ACCT 2

MYSQL	*mysql_Reconnect(int);
int	my_mysql_query(const char *,MYSQL *,int);

MYSQL real_mysql_auth, *mysql_auth = NULL;
MYSQL real_mysql_acct, *mysql_acct = NULL;

char mysql_server[40];
char mysql_login[20];
char mysql_password[20];
char acct_db[20];
char auth_db[20];
char auth_query[MAX_AUTH_QUERY_LEN];
char mysql_auth_table[20];
char mysql_acct_table[20];
int  mysql_keepopen;
int  use_mysql_acct;
int  use_mysql_auth;

#ifdef SMTP_RELAY
//See modified qualcomm qpopper 4.0.4 mysqlSendmail.c
MYSQL mysql;
static char query[2048];

//local in order of appearance in file
void ConnectDb();
void mysqlSendmail_Relay(char *cDomainIP);
void mysqlSendmail_RemoveRelay(char *cDomainIP);
void ScheduleJob(unsigned uUser, unsigned uServer, char *cJobName, char *cJobData);
char *ClassC(char *cInput);

#endif


//Reads <raddb dir>/sqlserver file
int mysql_rad_init()
{
	FILE    *sqlfd;
	char    dummystr[64];
	char    namestr[64];
	int     line_no;
	char    buffer[256];
	char    sqlfile[256];

	//These are not a security or overflow issue. Clean up later.
	strcpy(mysql_server,"");
	strcpy(mysql_login,"");
	strcpy(mysql_password,"");
	strcpy(acct_db,"");
	strcpy(auth_db,"");
	strcpy(mysql_auth_table,"passwd");
	strcpy(mysql_acct_table,"usertime");
	mysql_keepopen = 0;
	use_mysql_acct = 0;
	use_mysql_auth = 0;

        sprintf(sqlfile, "%s/%s", radius_dir, "sqlserver");
        if((sqlfd = fopen(sqlfile, "r")) == (FILE *)NULL)
	{
                log(L_ERR,"could not read sqlserver file %s",sqlfile);
                return(-1);
        }

        line_no = 0;
        while(fgets(buffer, sizeof(buffer), sqlfd) != (char *)NULL)
	{
                line_no++;

                // Skip empty space
                if(*buffer == '#' || *buffer == '\0' || *buffer == '\n')
                        continue;

                if(strncasecmp(buffer, "server", 6) == 0)
		{
                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2)
			{
log(L_ERR,"Invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
                         use_mysql_acct = 0;
                         use_mysql_auth = 0;
			}
			else
			{
				sprintf(mysql_server,"%.39s",namestr);
			}
               }

		if(strncasecmp(buffer, "login", 5) == 0)
		{
			if(sscanf(buffer, "%s%s", dummystr, namestr) != 2)
			{
log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
			}
			else
			{
				sprintf(mysql_login,"%.19s",namestr);
			}
		}

                if(strncasecmp(buffer, "password", 8) == 0)
		{
			if(sscanf(buffer, "%s%s", dummystr, namestr) != 2)
			{
log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
			}
			else
			{
				sprintf(mysql_password,"%.19s",namestr);
			}
		}

                if(strncasecmp(buffer, "acct_db", 7) == 0)
		{
			if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
                         	use_mysql_acct = 0;
			}
			else
			{
				sprintf(acct_db,"%.19s",namestr);
			}
		}

		if(strncasecmp(buffer, "acct_table", 10) == 0)
		{
			if(sscanf(buffer, "%s%s", dummystr, namestr) != 2)
			{
log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
				use_mysql_acct = 0;
			}
			else
			{
				sprintf(mysql_acct_table,"%.19s",namestr);
			}
		}

		if(strncasecmp(buffer, "keepopen", 8) == 0)
		{
			if(sscanf(buffer, "%s%s", dummystr, namestr) != 2)
			{
log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
			}
			else
			{
				if(strncasecmp(namestr, "yes", 3) == 0)
                           		mysql_keepopen = 1;
				else
                           		mysql_keepopen = 0;
			}
		}

		if(strncasecmp(buffer, "doacct", 6) == 0)
		{
			if(sscanf(buffer, "%s%s", dummystr, namestr) != 2)
			{
                       log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
			}
			else
			{
				if(strncasecmp(namestr, "yes", 3) == 0)
					use_mysql_acct = 1;
				else
					use_mysql_acct = 0;
			}
		}
	}
       fclose(sqlfd);
       
	log(L_INFO,"mysql_rad_init(): using: %s,%s,%s,%s,%d,%d",
					mysql_server,
					mysql_login,
					acct_db,
					mysql_acct_table,
					mysql_keepopen,
					use_mysql_acct); 
           
	return 0;

}//int mysql_rad_init ()

/*
typedef struct mysql_rec
{
        char            cSessionID[33];
        char            cLogin[101];
        char            cNAS[20];
        char            cIP[20];
        unsigned        uStatus;
        unsigned        uPort;
        unsigned        uPortType;
        unsigned        uProtocol;
        unsigned long   uDelay;
        unsigned long   uConnectTime;
        unsigned        uService;
        unsigned long   uInBytes;
        unsigned long   uOutBytes;
        unsigned        uTermCause;
        char            cLine[20];
        char            cCallerID[20];
        char            cInfo[20];
} MYSQL_RECORD;
*/

//Builds accounting record for MySQL 
void build_mysql_record(VALUE_PAIR * pair, MYSQL_RECORD * rec)
{
	char buffer[100];
	char *str;
       
	if (use_mysql_acct == 0) return;

	switch (pair->attribute)
	{
		case PW_ACCT_SESSION_ID:
			strncpy(rec->cSessionID, pair->strvalue,32);
		break;

		case PW_USER_NAME:
			if (pair->strvalue[0] <= 'Z')
			{
				/* Strip first Upper case Letter --why? (ggw)*/
				str = pair->strvalue + 1;
				strncpy(rec->cLogin,str,100);
			}
			else
			{
				strncpy(rec->cLogin,pair->strvalue,100);
			}
		break;

		case PW_ACCT_STATUS_TYPE:
			rec->uStatus= pair->lvalue;
		break;

		case PW_NAS_IP_ADDRESS:
			ipaddr2str(buffer, pair->lvalue);
			sprintf(rec->cNAS,"%.19s",buffer);
		break;

		case PW_FRAMED_IP_ADDRESS:
			ipaddr2str(buffer, pair->lvalue);
			sprintf(rec->cIP,"%.19s",buffer);
		break;

		case PW_NAS_PORT:
			rec->uPort = pair->lvalue;
		break;

		case PW_SERVICE_TYPE:
			rec->uService= pair->lvalue;
		break;

		case PW_FRAMED_PROTOCOL:
			rec->uProtocol = pair->lvalue;
		break;

		case PW_LOGIN_SERVICE:
			rec->uProtocol = pair->lvalue + 100;
		break;

		case PW_ACCT_SESSION_TIME:
			rec->uConnectTime = pair->lvalue;
		break;

		case PW_ACCT_AUTHENTIC:
			//rec->uAuth = pair->lvalue;
		break;

		case PW_ACCT_OUTPUT_OCTETS:
			rec->uOutBytes = pair->lvalue;
		break;

		case PW_ACCT_INPUT_OCTETS:
			rec->uInBytes = pair->lvalue;
		break;

		case PW_LOGIN_IP_HOST:
			if(!rec->cIP[0])
			{
				ipaddr2str(buffer, pair->lvalue);
				sprintf(rec->cIP,"%.19s",buffer);
			}
		break;

		case PW_ACCT_DELAY_TIME:
			rec->uDelay = pair->lvalue;
		break;

		case PW_FRAMED_COMPRESSION:
		break;

		case PW_ACCT_INPUT_PACKETS:			   
		break;

		case PW_ACCT_OUTPUT_PACKETS:			   
		break;

		case PW_NAS_PORT_TYPE:			   
			rec->uPortType = pair->lvalue;
		break;

		case PW_CONNECT_INFO:			   
			sprintf(rec->cInfo,"%.19s",pair->strvalue);
		break;

		default:

			if(!strcasecmp(pair->name, "called-station-id"))
			{
				sprintf(rec->cLine,"%.19s",pair->strvalue);
			}
			else if(!strcasecmp(pair->name, "calling-station-id"))
			{
				register int count = 0;
				register int i = 0;
				str = pair->strvalue;
				while ( (*str != '\0') && (i < 3) )
				{
					if ((*str >= '\200') && (*str <= '\205'))
					{     
						count++;
					}
					str++;
					i++;
				}
				sprintf(rec->cCallerID,"%.19s",pair->strvalue+count);
			}
			else if(!strcasecmp(pair->name, "Acct-Terminate-Cause"))
			{
				rec->uTermCause = pair->lvalue;
			}

#ifdef LOGFILE_DEBUG
			else if(!strcasecmp(pair->name, "NAS_Identifier"))
			{
				/*elminate error below. Show up w/ a USR TC?*/
			}
			else if(!strcasecmp(pair->name, "Client-IP-Address"))
			{
				/*Elminate error below. For Cisco*/
			}
			else if(!strcasecmp(pair->name, "Acct-Multi-Session-Id"))
			{
				/*Elminate error below.*/
			}

			//All Ascend/Lucent pairs no matter what full name
			else if(!strncasecmp(pair->name, "Ascend",6))
			{
				/*Elminate error below. For Ascend*/
			}

			else if(!strcasecmp(pair->name, "Vendor-Specific"))
			{
				/*Elminate error below. For Ascend*/
			}

			else if(!strcasecmp(pair->name, "Acct-Link-Count"))
			{
				/*Elminate error below.*/
			}
			else if(!strcasecmp(pair->name, "Login-TCP-Port"))
			{
				/*Elminate error below.*/
			}
			else if(!strcasecmp(pair->name, "Realm"))
			{
				/*Elminate error below.*/
			}
			else
			{
				log(L_ERR,"Unknown Pair: %s", pair->name);
			}
#endif
	}//switch()

}//void build_mysql_record(VALUE_PAIR * pair, MYSQL_RECORD * rec)


//FIXME: There is probably a better way of implenting this function to
//		connect to two db's.
//		Changed for mySQL 4 support @ openisp . net
MYSQL *mysql_Reconnect(int type)
{

	int i=0;
	MYSQL * mysql = NULL;


	//This should handle the looped calls this crazy patch guy makes.
	if(type == MYSQL_AUTH)
	{
		//if(!mysql_ping(&real_mysql_auth))
		//	return &real_mysql_auth;
		mysql_init(&real_mysql_auth);
	}
	else
	{
		//if(!mysql_ping(&real_mysql_acct))
		//	return &real_mysql_acct;
		mysql_init(&real_mysql_acct);
	}

	if (type == MYSQL_AUTH)
	{
		if(!(mysql_real_connect(&real_mysql_auth,mysql_server,mysql_login,mysql_password,acct_db,0,NULL,0))) {
			log(L_ERR,"MYSQL AUTH: Cannot Connect to %s.%s as %s",mysql_server,mysql_login);
			mysql = NULL;
		}
		else
		{
			log(L_INFO,"MYSQL AUTH Connected to %s",mysql_server);
			mysql = &real_mysql_auth;
		}
	}
	else
	{
		if (!(mysql_real_connect(&real_mysql_acct,mysql_server,mysql_login,mysql_password,acct_db,0,NULL,0)))
		{
			log(L_ERR,"MYSQL ACCT: Cannot Connect to %s.%s as %s/%s",mysql_server,acct_db,mysql_login,mysql_password);
			mysql = NULL;
		}
		else
		{
			log(L_INFO,"MYSQL ACCT Connected to %s",mysql_server);
			mysql = &real_mysql_acct;
		}
	}

	return mysql;

}//MYSQL *mysql_Reconnect(int type)


//Purpose: Query MySQL database 
int my_mysql_query(const char *q, MYSQL *mysql, int type)
{
  int ret;
  int i;
#ifdef STOP_SIGNALS
  sigset_t set,old_set;
#endif

  i = 0; 
  while(i<10) { // Try it 10 Times 
       if (mysql == NULL) mysql = mysql_Reconnect(type);
#ifdef STOP_SIGNALS
       /* Try to not catch any signals during mysql_query 
        * We need this if mysql is less than 3.20.25 or 3.21.3 */
       sigemptyset(&set);
       sigaddset(&set,SIGALRM);                  
       sigprocmask(SIG_BLOCK,&set,&old_set);
#endif
       ret = mysql_query(mysql,q);
#ifdef STOP_SIGNALS
       sigprocmask(SIG_SETMASK,&old_set,NULL);
#endif
       if(!ret) {
         DEBUG("MYSQL query OK");
         return ret;
       }
       if (!strcasecmp(mysql_error(mysql),"mysql server has gone away")) {
               log(L_ERR,"MYSQL Error (retrying %d): Cannot Query:%s",ret,q);
               log(L_ERR,"MYSQL error: %s",mysql_error(mysql));
               mysql_close(mysql);
               mysql = NULL;
       } else {
               log(L_ERR,"MYSQL Error (%d): Cannot Query:%s",ret,q);
               log(L_ERR,"MYSQL error: %s",mysql_error(mysql));
               return ret;
       }
       i++;
  }
  log(L_ERR,"MYSQL Error (giving up): Cannot Query:%s",q);
  return ret;

}//int my_mysql_query(const char *q, MYSQL *mysql, int type)


//Purpose: Saves Account record to MySQL database 
void save_mysql_record(MYSQL_RECORD * rec)
{
	char		buf[500];
	int		err;
	int		num;
	unsigned long 	time_on;
	int		i = 0;
	time_t		curtime;
#ifdef SQL_LOG
	FILE		*sqloutfd;
#endif
	MYSQL_RES	*result;
	MYSQL_ROW	row;

	if(use_mysql_acct == 0) return;

#ifdef SQL_LOG
	sprintf(buf, "%s/sql.log", radacct_dir);
	if((sqloutfd = fopen(buf, "a")) == (FILE *) NULL)
		log(L_ERR,"accounting: could not append to file %s", buf);
#endif

	if(mysql_acct == NULL)
		mysql_acct = mysql_Reconnect(MYSQL_ACCT);
       
	curtime = time(0) - rec->uDelay;

	//Special case when NAS was rebooted
	if(rec->uStatus == PW_STATUS_ACCOUNTING_ON 
			|| rec->uStatus == PW_STATUS_ACCOUNTING_OFF)
	{
		//The Terminal server informed us that it was rebooted 
		// -> delete all records (ggw: ? update all you mean)
		if (mysql_acct != NULL)
		{
sprintf(buf, "SELECT cSessionID,cLogin,uStartTime FROM %s WHERE cNAS='%s' AND uStopTime=0 AND uConnectTime=0", mysql_acct_table, rec->cNAS);

			DEBUG("%s",buf);
			(void) my_mysql_query(buf, mysql_acct, MYSQL_ACCT);
			if(!(result = mysql_store_result(mysql_acct)))
			{
				log(L_ERR,"MYSQL Error: Cannot get result");
				log(L_ERR,"MYSQL error: %s",mysql_error(mysql_acct));
				mysql_close(mysql_acct);
				mysql_acct = NULL;
			}
			else
			{
				num = mysql_num_rows(result);
				while(i < num)
				{
					row = mysql_fetch_row(result);
					time_on = difftime(curtime,
							((time_t) atoi(row[2])));
sprintf(buf, "UPDATE %s SET uStopTime=%lu,uConnectTime=%lu,uTermCause=7 WHERE uConnectTime=0 AND uStopTime=0 AND cNAS='%s' AND cSessionID='%s' AND cLogin='%s'", mysql_acct_table,curtime,time_on,rec->cNAS,row[0],row[1]);

					my_mysql_query(buf, mysql_acct, MYSQL_ACCT);

#ifdef SQL_LOG
					if(sqloutfd)
					{
						fputs(buf, sqloutfd);
						fputs(";\n", sqloutfd);
						fflush(sqloutfd);
					}
#endif

					i++;
				}
				mysql_free_result(result);
			}
			return;
		}
		log(L_ERR,"MYSQL Error: Cannot update after %s rebooted",rec->cNAS);
		return;

	}//Special NAS Rebbot case


	//Normal case
	if(mysql_acct != NULL)
	{
sprintf(buf, "SELECT cSessionID FROM %s WHERE cSessionID='%s' AND cNAS='%s' AND cLogin='%s'", mysql_acct_table, rec->cSessionID, rec->cNAS, rec->cLogin);

		DEBUG("%s",buf);
		my_mysql_query(buf, mysql_acct, MYSQL_ACCT);
		if(!(result = mysql_store_result(mysql_acct)))
		{
			log(L_ERR,"MYSQL Error: Cannot get result");
			log(L_ERR,"MYSQL error: %s",mysql_error(mysql_acct));
			mysql_close(mysql_acct);
			mysql_acct = NULL;
		}
		else
		{
			num = mysql_num_rows(result);
			mysql_free_result(result);
		}
	}


	//Only insert it if its not there
	if((mysql_acct != NULL) && (num == 0))
	{
		//unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length)

		char cLogin[256];
		mysql_real_escape_string(mysql_acct,cLogin,rec->cLogin,strlen(rec->cLogin));

sprintf(buf, "INSERT INTO %s SET cSessionId='%s', uConnectTime=%lu, cLogin='%s', cNAS='%s', uPort=%u, uPortType=%u, uService=%u, uProtocol=%u, cIP='%s', cLine='%s', cCallerID='%s', uInBytes=%lu, uOutBytes=%lu, uTermCause=%u",
					mysql_acct_table,
					rec->cSessionID,
					rec->uConnectTime,
					cLogin,
					rec->cNAS,
					rec->uPort,
					rec->uPortType,
					rec->uService,
					rec->uProtocol,
					rec->cIP,
					rec->cLine,
					rec->cCallerID,
					rec->uInBytes,
					rec->uOutBytes,
					rec->uTermCause);
		DEBUG("%s",buf);

#ifdef SQL_LOG
		if(sqloutfd)
		{
			fputs(buf, sqloutfd);
			fputs(";\n", sqloutfd);
			fflush(sqloutfd);
		}
#endif

		err = my_mysql_query(buf, mysql_acct, MYSQL_ACCT);
		if((rec->uStatus == 1) && err)
			log(L_ERR,"MYSQL Error: Cannot insert");
	}

	//Start record?
	if(rec->uStatus == 1)
	{
		sprintf(buf, "UPDATE %s SET uStartTime=%lu,cInfo='%s' WHERE cSessionID='%s' AND cNAS='%s' AND cLogin='%s'",
						mysql_acct_table,
						curtime,
						rec->cInfo,
						rec->cSessionID,
						rec->cNAS,
						rec->cLogin);
#ifdef SMTP_RELAY
		//Add async entry to access file for sendmail relay access
		//See modified qualcomm qpopper 4.0.4
		if(rec->cIP[0])
			mysqlSendmail_Relay(rec->cIP);
#endif
	}
	//Alive record, Stop, etc.
	else
	{
		sprintf(buf,"UPDATE %s SET uConnectTime=%lu,uStopTime=%lu,uInBytes=%lu,uOutBytes=%lu,uTermCause=%u,cIP='%s' WHERE cSessionID='%s' AND cNAS='%s' AND cLogin='%s'",
						mysql_acct_table,
						rec->uConnectTime,
						curtime,
						rec->uInBytes,
						rec->uOutBytes,
						rec->uTermCause,
						rec->cIP,
						rec->cSessionID,
						rec->cNAS, 
						rec->cLogin);
#ifdef SMTP_RELAY
		//Stop record only
		if(rec->uStatus == 2 && rec->cIP[0])
			mysqlSendmail_RemoveRelay(rec->cIP);
#endif

	}
	DEBUG("%s",buf);

#ifdef SQL_LOG
	if(sqloutfd)
	{
		if( (rec->uStatus != 1) && (num == 0) )
			fprintf(sqloutfd,"-- Record is missing\n");
		fputs(buf, sqloutfd);
		fputs(";\n", sqloutfd);
		fflush(sqloutfd);
	}
#endif

	if(mysql_acct != NULL)
	{ 
		if(my_mysql_query(buf, mysql_acct, MYSQL_ACCT))
		{
		}
		else
		{ 
			if (mysql_affected_rows(mysql_acct) > 1)
			{
				log(L_ERR,"MYSQL %s (%s) %d rows changed",rec->cLogin,
				rec->cSessionID,mysql_affected_rows(mysql_acct));
			}
		}
	}
#ifdef SQL_LOG
	if(sqloutfd) fclose(sqloutfd);
#endif

	if(mysql_keepopen == 0)
	{ 
		//Close the connection after each record
		if (mysql_acct != NULL)
		mysql_close(mysql_acct);
		mysql_acct = NULL;
	}

}//void save_mysql_record(MYSQL_RECORD * rec)

#ifdef SMTP_RELAY

void ConnectDb()
{
	char cDbIp[256]={""};
	char *cEffectiveDbIp=NULL;
	char cDbName[256]={"mysqlsendmail"};
	char cDbPwd[256]={"wsxedc"};
	char cDbLogin[256]={"mysqlsendmail"};

	//Already connected? Connect only once
	if(!mysql_ping(&mysql))
		return;

	if(cDbIp[0]) cEffectiveDbIp=cDbIp;

        mysql_init(&mysql);
        if (!mysql_real_connect(&mysql,cEffectiveDbIp,
				cDbLogin,cDbPwd,cDbName,0,NULL,0))
        {
		sprintf(query,"ConnectDb %s.%s",cDbIp,cDbName);
                log(L_ERR,"[SMTP_RELAY] (%s) %s",mysql_error(&mysql),query);
		return;
        }
	log(L_INFO, "[SMTP_RELAY] connected to mysqlsendmail");

}//end of void ConnectDb(void)


void mysqlSendmail_RemoveRelay(char *cDomainIP)
{
	ConnectDb();//Connects only once. Check

	sprintf(query,"DELETE FROM tAccess WHERE cDomainIP='%s' AND cRelayAttr='RELAY' AND uSource=3 AND uOwner=1 AND uCreatedBy=1 AND uServer=1",cDomainIP);
        mysql_query(&mysql,query);
        if(mysql_errno(&mysql))
                log(L_ERR,"[SMTP_RELAY] %s",mysql_error(&mysql));

	//Create job for deletion
	if(mysql_affected_rows(&mysql))
		ScheduleJob(1,1,"DelAccess",cDomainIP);

}//void mysqlSendmail_RemoveRelay(char *cDomainIP)


//Add entry to tAccess: Expire in 72 hrs
void mysqlSendmail_Relay(char *cDomainIP)
{
	MYSQL_RES *res;

	char cClasscIP[33]={""};
	time_t ulClock,ulExpire;

	ConnectDb();//Connects only once. Check

	//Check against tAccess to see if needed. Check class c and complete IP
	//Note that other entries with cRelayAttr are also noted. so even
	//blocks are counted.
	sprintf(query,"SELECT uAccess FROM tAccess WHERE cDomainIP='%s'",cDomainIP);
        mysql_query(&mysql,query);
        if(mysql_errno(&mysql))
	{
                log(L_ERR,"[SMTP_RELAY] %s",mysql_error(&mysql));
		return;
	}
	res=mysql_store_result(&mysql);
	if(mysql_num_rows(res)>0)
	{
		mysql_free_result(res);
		return;
	}
	mysql_free_result(res);

	sprintf(cClasscIP,"%32s",cDomainIP);
	sprintf(query,"SELECT uAccess FROM tAccess WHERE cDomainIP='%s'",ClassC(cClasscIP));
        mysql_query(&mysql,query);
        if(mysql_errno(&mysql))
	{
                log(L_ERR,"[SMTP_RELAY] %s",mysql_error(&mysql));
		return;
	}
	res=mysql_store_result(&mysql);
	if(mysql_num_rows(res)>0)
	{
		mysql_free_result(res);
		return;
	}
	mysql_free_result(res);

	time(&ulClock);
	ulExpire=ulClock+259200;//72 hrs

	sprintf(query,"REPLACE INTO tAccess SET cDomainIP='%s',cRelayAttr='RELAY',uSource=3,uExpireDate=%lu,uOwner=1,uCreatedBy=1,uCreatedDate=%lu,uServer=1",
			cDomainIP,
			ulExpire,
			ulClock);
        mysql_query(&mysql,query);
        if(mysql_errno(&mysql))
                log(L_ERR,"[SMTP_RELAY] %s",mysql_error(&mysql));

	//Create job for addition
	ScheduleJob(1,1,"NewAccess",cDomainIP);

}//void mysqlSendmail_Relay()


void ScheduleJob(unsigned uUser, unsigned uServer, char *cJobName, char *cJobData)
{
	time_t clock;
	
	time(&clock);

        sprintf(query,"INSERT INTO tJob (cServer,cLabel,cJobData,cJobName,uUser,uJobDate,uJobStatus,uOwner,uCreatedBy,uCreatedDate) SELECT cLabel,'%s','%s','%s',%u,%lu,%u,%u,%u,%lu FROM tServer WHERE uServer=%u",
			"Priority=Normal",
			cJobData,
			cJobName,
			uUser,
			(unsigned long)clock,
			1,//uJobStatus 1=waiting
			1,
			1,
			(unsigned long)clock,
			uServer);
	mysql_query(&mysql,query);
	if(mysql_errno(&mysql))
                log(L_ERR,"[SMTP_RELAY] %s",mysql_error(&mysql));

}//void ScheduleJob()


char *ClassC(char *cInput)
{
	unsigned a=0,b=0,c=0,d=0;

	sscanf(cInput,"%u.%u.%u.%u",&a,&b,&c,&d);
	sprintf(cInput,"%u.%u.%u",a,b,c);

	return(cInput);

}//char *ClassC(char *cInput)

#endif //SMTP_RELAY

#endif //USEMYSQL
