#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <sys/socket.h> 
#include <sys/wait.h> 


#define MYPORT 18    /* the port users will be sending to */

//administrator program to send packets to add policies

/*whattodo */
#define DELETE_ALL 2 // Delete all entries
#define FORWARD 1 //Forward
#define DROP 0 //Drop


/*filter ids */
#define SRC_PORT 1 // (16 bits)
#define DST_PORT 2
#define SRC_ADDR 3 // (32 bits)
#define DST_ADDR 4
#define PROTOCOL 5 //  (8 bits)


struct Filter{
  int policy_id; //which policy it belongs to
  int filter_id; //type of filter (e.g src port)
  int filter_value; //either contains the value or the address (pointer) to the value
  int filter_mask; //applies if masks are necessary (we know if its necessary by looking at the policy_id
};

struct Admin_struct{
  int whattodo;
  int numfilters;
  struct Filter filts[6];
};

int print_to_file(FILE* fileptr, struct Admin_struct new_policy){
  int i = 0;
  if(!fileptr){
    return -1;
  }
  else{
    fprintf(fileptr, "%d ",new_policy.whattodo);
    fprintf(fileptr, "%d ",new_policy.numfilters);
    for(i =0; i < new_policy.numfilters; i++){
      fprintf(fileptr, "%d ",new_policy.filts[i].policy_id);
      fprintf(fileptr, "%d ",new_policy.filts[i].filter_id);
      if(new_policy.filts[i].filter_id == SRC_ADDR || 
	 new_policy.filts[i].filter_id == DST_ADDR){ 
	fprintf(fileptr, "0x%x ",new_policy.filts[i].filter_value);
	fprintf(fileptr, "0x%x ",new_policy.filts[i].filter_mask);
      }
      else{
	fprintf(fileptr, "%d ",new_policy.filts[i].filter_value);
	fprintf(fileptr, "%d ",new_policy.filts[i].filter_mask);
      }
    }
    fprintf(fileptr, "\n");
    return 1;
  }
}

int main(int argc, char *argv[])
{
  int sockfd;
  struct sockaddr_in their_addr; /* connector's address information */
  struct hostent *he;
  int numbytes;
  int input;
  int filter_input;
  int ip1, ip2, ip3, ip4;
  short int port;
  char protocol;
  FILE* fileptr;

  if((fileptr = fopen("packet_output" , "w+")) == NULL){
    printf("Cannot open packet_output\n");
  }

  /**************** Prepare admin stuff here ***************************/
  
  while(1){
    struct Admin_struct new_policy;      
    int i = 0;
    printf("What is thy bidding my master?\n");
    printf("You have two options: 1, 2, 3 \n");
    printf("1: Delete all policies\n");
    printf("2: Add a new policy\n");
    printf("3: Exit the program\n");
    
    input = -1;
    scanf("%d", &input);
    
    switch(input){
    case 1:
      printf("Deleting all policies\n");
      new_policy.whattodo = DELETE_ALL;
      print_to_file(fileptr, new_policy);
      break;
    case 2:
      printf("Adding a new policy\n");
      /* Deciding how many filters in the policy */
      input = -1;
      while(input <=0 || input >= 6){
	printf("Number filters? (between 1 and 5) : \n");
	scanf("%d", &input);
      }
      
      new_policy.numfilters = input;
      printf("You have chosen to add %d filters\n", new_policy.numfilters);
      
      for(i = 0; i < input; i++){
	printf("Fill in the policy id\n");
	scanf("%d", &filter_input);
	printf("Your input policy is %d\n", filter_input);
	new_policy.filts[i].policy_id = filter_input;
	printf("Fill in the filter id: %s\n,%s\n,%s\n,%s\n,%s\n\n", 
	       "SRC_PORT 1 // (16 bits)",
	       "DST_PORT 2",
	       "SRC_ADDR 3 // (32 bits)",
	       "DST_ADDR 4",
	       "PROTOCOL 5 //  (8 bits)");
	
	scanf("%d", &filter_input);
	new_policy.filts[i].filter_id = filter_input;
	printf("Your filter id is %d\n", filter_input);
	if(filter_input == 1 || filter_input == 2 || filter_input == 5){
	  printf("Please input the port or protocol value \n");
	  scanf("%d", &filter_input);
	  new_policy.filts[i].filter_value = filter_input;
	  printf("Your port or protocol value was %d \n", filter_input);
	  /* Read in mask */
	  printf("Please input the port or protocol mask \n");
	  scanf("%d", &filter_input);
	  new_policy.filts[i].filter_mask = filter_input;
	  printf("Your port or protocol mask was %d \n", filter_input);
	}
	else if(filter_input == 3 || filter_input == 4){
	    printf("Please input the IP address value \n");
	    scanf("%d.%d.%d.%d",&ip1, &ip2, &ip3, &ip4);
	    ip1 = ip1 << 24;
	    ip2 = ip2 << 16;
	    ip3 = ip3 << 8;
	    new_policy.filts[i].filter_value = ip1 | ip2 | ip3 | ip4;
	    printf("Your IP address value was %x \n",
		   new_policy.filts[i].filter_value);
	    
	    /* Read in the mask */
	    printf("Please input the IP mask value \n");
	    scanf("%d.%d.%d.%d",&ip1, &ip2, &ip3, &ip4);
	    ip1 = ip1 << 24;
	    ip2 = ip2 << 16;
	    ip3 = ip3 << 8;
	    new_policy.filts[i].filter_mask = ip1 | ip2 | ip3 | ip4;
	    printf("Your IP mask value was %x \n",
		   new_policy.filts[i].filter_mask);
	}
      }
      
      input = -1;
      while(input < 0 || input > 1){
	printf("Should this policy drop or forward? (Drop = 0, Forward = 1)\n");
	scanf("%d", &input);
      }

      if(!input){
	printf("This policy is set to drop packets\n");
	new_policy.whattodo = 0;
      }
      else{
	printf("This policy is set to forward packets\n");
	new_policy.whattodo = 1;
      }
      print_to_file(fileptr, new_policy);
      
      break;
    case 3: 
      printf("Exiting the program\n");
      fclose(fileptr);
      exit(1);
      break;
    default:
      printf("Invalid input\n");
      break;
    }
    
   }
  
  return 0;
}

