#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <time.h>
#include <sys/stat.h>

#define IP_LENGTH 16
const char *denied = "denied";
const char *file_name = "/var/log/named/security.log";

struct Unique_Ips{
	char ip[IP_LENGTH];
	uint32_t times;
};

int Is_Denied(char *linestring){
	uint8_t num1 = 0;
	const uint8_t denied_length = 6;
	while(linestring[num1] != '\0')
		num1++;
	num1--;
	return strncmp(denied, (const char *)(&linestring[num1-denied_length]), denied_length);
}

void Grab_Ip(char *linestring, char *ip){
	uint8_t num1 = 0;
	uint8_t tmp = 0;
	while(linestring[num1] != '\0' && linestring[num1] != '#')
		num1++;

	if(linestring[num1] == '\0'){
		printf("malformed line 1\n");
		exit(1);
	}
	while(linestring[num1-tmp] != ' ')
		tmp++;
	tmp--;
	(void)memset(ip, '\0', IP_LENGTH);
	(void)memcpy(ip, (const void *)(&linestring[num1-tmp]), tmp);
}

int Already_Denied(char *cur_ip, struct Unique_Ips *unique_ips, uint32_t ip_count){
	uint32_t num1 = 0;
	//uint32_t times = 0;
	while(num1 < ip_count){
		if(strncmp((const char *)cur_ip, (const char *)&(unique_ips[num1].ip), IP_LENGTH) == 0){
			unique_ips[num1].times++;
			return 1;
		}
		num1++;
	}
	return 0;
}

//int main(int argc, char **argv){

void Main_Loop(void){
	FILE *fp;
	//const char *file_name = "/var/log/named/security.log";
	//const char *denied = "denied";
	char linestring[256];
	//uint32_t linenum = 0;
	char cur_ip[IP_LENGTH];
	struct Unique_Ips *unique_ips = NULL;
	//struct Unique_Ips tmp_unique_ip;
	uint32_t ip_count = 1;
	//uint32_t tmp1 = 0;
	uint32_t num1 = 0;
	//19-Sep-2018 07:48:25.243 client @0x7f9fc01ba2d0 23.161.0.30#12426 (access-board.gov): query (cache) 'access-board.gov/ANY/IN' denied

	//open log file
	if( (fp = fopen(file_name, "r")) == NULL){
		fprintf( stderr, "Error opening %s\n", file_name );
		exit( 1 );
	}
	unique_ips = (struct Unique_Ips *)malloc(ip_count * sizeof(struct Unique_Ips));

	//grab first "denied" line
	while(fgets(linestring, sizeof(linestring), fp) != NULL){
		if(Is_Denied(linestring) == 0){
			Grab_Ip(linestring, cur_ip);
			(void)memcpy(unique_ips[ip_count-1].ip, cur_ip, IP_LENGTH);
			unique_ips[ip_count-1].times = 1;
			break;
		}
	}

	//do the rest
	while(fgets(linestring, sizeof(linestring), fp) != NULL){
		if(Is_Denied(linestring) == 0){
			Grab_Ip(linestring, cur_ip);
			//unique_ips[num1].times+
			if(Already_Denied(cur_ip, unique_ips, ip_count) == 0){
				ip_count++;
				unique_ips = (struct Unique_Ips *)realloc(unique_ips, ip_count * sizeof(struct Unique_Ips));
				(void)memcpy(unique_ips[ip_count-1].ip, cur_ip, IP_LENGTH);
				unique_ips[ip_count-1].times = 1;
			}
		}
	}
	fclose(fp);
	printf("%d unique denied ips\n", ip_count);
	system("iptables -F");

	for(num1=0; num1<ip_count; num1++){
//		printf("ip: %s denied: %d\n", unique_ips[num1].ip, unique_ips[num1].times);

		if(unique_ips[num1].times>3){
			(void)memset(linestring, '\0', sizeof(linestring));
			(void)sprintf(linestring, "iptables -A INPUT -s %s -j DROP", unique_ips[num1].ip);
			//system("iptables -F");
			system((const char *)linestring);
		}
	}
	fclose(fp);


	free(unique_ips);

	//return 0;
}


int File_Modified(void) {
	struct stat attr;
	static time_t st_mtime_backup = 0;

	stat(file_name, &attr);
	//st_mtime_backup = attr.st_mtime;

	//printf("Last modified time: %lu %lu\n", st_mtime_backup, attr.st_mtime);
	//printf("Last modified time: %s", ctime(&attr.st_mtime));
	//st_mtime_backup = attr.st_mtime;
	if(st_mtime_backup != attr.st_mtime){
		st_mtime_backup = attr.st_mtime;
		return 1;
	}else{
		//st_mtime_backup = attr.st_mtime;
		return 0;
	}
}

int main(int argc, char **argv){
	while(1){
		if(File_Modified() == 1){
			Main_Loop();
		}
		sleep(1);
	}

	//while(Main_Loop()){
	//	sleep(1);
	//}
	return 0;
}

