#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "vars.h"

int add_ip(char *string,char **ip_list,int *count)
{
 char *k,*k1,tmp[ML_CFG],etmp[ML_ETMP];
 int z,i;
 FILE *fp;

 #ifdef DEBUG_IP
 fprintf(stderr,"Parse ip string: %s\n",string);
 #endif

 // Get from file?
 if (string[0]=='f' && string[1]==':')
  {
     #ifdef DEBUG_IP
     fprintf(stderr," get ip from file: %s\n",&string[2]);
     #endif

     // Open file
     if ((fp=fopen(&string[2],"r"))==NULL)
         { // Open error
           sprintf(etmp,"ERROR: Can't open file %s: %s",&string[2],strerror(errno));
           err_mes(etmp);
           exit(-1);
         }
  
     // Parse file
     while(!feof(fp))
     {
      // Get line
      if (fgets(tmp,ML_CFG,fp)==NULL) continue;

      //Chomp
       if (tmp[strlen(tmp)-1]=='\n' || tmp[strlen(tmp)-1]=='\r') tmp[strlen(tmp)-1]=0;
       if (tmp[strlen(tmp)-1]=='\n' || tmp[strlen(tmp)-1]=='\r') tmp[strlen(tmp)-1]=0;
       if (strlen(tmp)<=0) continue;
		 
      #ifdef DEBUG_IP
       fprintf(stderr,"   read ip: %s\n",tmp);
      #endif
      
      //Strip free space in line start
      while(tmp[0]==' ' || tmp[0]==9)
         for(i=0;i<strlen(tmp);i++)
  	  tmp[i]=tmp[i+1];

      //Check for comment
      if(tmp[0]!='#' && tmp[0]!=';' && tmp[0]!=0)
       add_ip(tmp,ip_list,count);
     }
    fclose(fp);
    return(0);
   }														 
  
  //Add memory
  *ip_list=(char*)realloc(*ip_list,(8*(1 +  *count))*sizeof(char));
    if (*ip_list==NULL)
       {
        err_mes("Error: Can't allocate memory for allow_ip\n");
        exit(-1);
       }

 // 192.
  k=string;
 
  while(1)
   if (*k<48 || *k>57) break;
   else k++;
 
 if (*k!='.' ||  k-string<1)
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }
 memcpy(tmp,string,k-string);
 tmp[k-string]=0;

 #ifdef DEBUG_IP
 fprintf(stderr," ip digit 1: %s\n",tmp);
 #endif

 z=atoi(tmp);

 if (z>=0 && z<=255) (*ip_list)[(*count) * 8]=z;
 else {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 // 192.168.
 k++;
 k1=k;
 
  while(1)
   if (*k1<48 || *k1>57) break;
   else k1++;
 
 if (*k1!='.' || k1-k<1)
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 memcpy(tmp,k,k1-k);
 tmp[k1-k]=0;

 #ifdef DEBUG_IP
 fprintf(stderr," ip digit 2: %s\n",tmp);
 #endif

 z=atoi(tmp);

 if (z>=0 && z<=255) (*ip_list)[(*count)*8 +1]=z;
 else {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 // 192.168.129.
 k1++;
 k=k1;
 
  while(1)
   if (*k<48 || *k>57) break;
   else k++;
 
 if (*k!='.' || k-k1<1)
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 memcpy(tmp,k1,k-k1);
 tmp[k-k1]=0;

 #ifdef DEBUG_IP
 fprintf(stderr," ip digit 3: %s\n",tmp);
 #endif

 z=atoi(tmp);

 if (z>=0 && z<=255) (*ip_list)[(*count)*8 +2]=z;
 else {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }


 // 192.168.129.201
 k++;
 k1=k;
       
 while(1)
  if (*k1<48 || *k1>57) break;
  else k1++;
 
 if ((*k1!='/' && *k1!=0 && *k1!=' ' && *k1!=9 && *k1!='#' && *k1!=';') || k1-k<1)
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 memcpy(tmp,k,k1-k);
 tmp[k1-k]=0;

 #ifdef DEBUG_IP
 fprintf(stderr," ip digit 4: %s\n",tmp);
 #endif

 z=atoi(tmp);

 if (z>=0 && z<=255) (*ip_list)[(*count)*8 +3]=z;
 else {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 #ifdef DEBUG_IP
  fprintf(stderr," next sumbol: %c (%d)\n",*k1,(unsigned char)*k1);
 #endif  

  // End of line?
  if (*k1==0 || *k1==' ' || *k1==9 || *k1=='#' || *k1==';')
     {

      // Set mask to /255.255.255.255
      (*ip_list)[(*count)*8 +4]=255;
      (*ip_list)[(*count)*8 +5]=255;     
      (*ip_list)[(*count)*8 +6]=255;
      (*ip_list)[(*count)*8 +7]=255;     

      // inc counter
      (*count)++;

       #ifdef DEBUG_IP
	fprintf(stderr," IP LIST\n");
	for (z=0;z<*count;z+=8)
	  fprintf (stderr,"%i %i.%i.%i.%i/%i.%i.%i.%i\n",z/8,(*ip_list)[z],(*ip_list)[z+1],(*ip_list)[z+2],(*ip_list)[z+3],(*ip_list)[z+4],(*ip_list)[z+5],(*ip_list)[z+6],(*ip_list)[z+7]);
       #endif
       return(0);
     }

  // Symbol '/' present?
  if (*k1!='/')  
     {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
     }

  k1++;
  if (strchr(k1,'.'))
   {
    #ifdef DEBUG_IP
    fprintf(stderr," detect long mask\n");
    fprintf(stderr," long mask: %s\n",k1);
    #endif

    // ip/255.
    k=k1;
    
    while(1)
     if (*k1<48 || *k1>57) break;
      else k1++;
 
     if (*k1!='.' || k1-k<1)
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 memcpy(tmp,k,k1-k);
 tmp[k1-k]=0;

 #ifdef DEBUG_IP
 fprintf(stderr," Long mask digit #1: %s\n",tmp);
 #endif

 z=atoi(tmp);

 if (z>=0 && z<=255) (*ip_list)[(*count)*8 +4]=z;
 else {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

    // ip/255.255.
    k1++;
    k=k1;
    
    while(1)
     if (*k1<48 || *k1>57) break;
      else k1++;
 
     if (*k1!='.' || k1-k<1)
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 memcpy(tmp,k,k1-k);
 tmp[k1-k]=0;

 #ifdef DEBUG_IP
 fprintf(stderr," Long mask digit #2: %s\n",tmp);
 #endif

 z=atoi(tmp);

 if (z>=0 && z<=255) (*ip_list)[(*count)*8 +5]=z;
 else {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

    // ip/255.255.255
    k1++;
    k=k1;
    
    while(1)
     if (*k1<48 || *k1>57) break;
      else k1++;
 
     if (*k1!='.' || k1-k<1)
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 memcpy(tmp,k,k1-k);
 tmp[k1-k]=0;

 #ifdef DEBUG_IP
 fprintf(stderr," Long mask digit #3: %s\n",tmp);
 #endif

 z=atoi(tmp);

 if (z>=0 && z<=255) (*ip_list)[(*count)*8 +6]=z;
 else {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }
    

    // ip/255.255.255.0
    k1++;
    k=k1;
    
    while(1)
     if (*k1<48 || *k1>57) break;
      else k1++;
 
     if (*k1!=0 || k1-k<1)
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }

 memcpy(tmp,k,k1-k);
 tmp[k1-k]=0;

 #ifdef DEBUG_IP
 fprintf(stderr," Long mask digit #4: %s\n",tmp);
 #endif

 z=atoi(tmp);

 if (z>=0 && z<=255) (*ip_list)[(*count)*8 +7]=z;
 else {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }
   }
  else
   {
    #ifdef DEBUG_IP
    fprintf(stderr," detect short mask\n");
    #endif

     k=k1;
     while(1)
      if (*k<48 || *k>57) break;
      else k++;
      
    // end of line?
    if (*k!=0)
         {
          sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
          err_mes(etmp);
          exit(-1);
         }

     memcpy(tmp,k1,k-k1);
     tmp[k-k1]=0;

     #ifdef DEBUG_IP
     fprintf(stderr," short mask: %s\n",tmp);
     #endif

     z=atoi(tmp);

     if (z<0 || z>32) 
       {
        sprintf(etmp,"Error in config file. Bad ip or network address: %s",string);
        err_mes(etmp);
        exit(-1);
       }
    
    // Convert short mask to long mask
    for(i=4; i<8; i++)
    if (z>7) 
      {
       (*ip_list)[(*count)*8 +i]=255;
       z-=8;
      }
    else
      {
       switch (z)
        {
	 case 0: (*ip_list)[(*count)*8 +i]=0; break;
	 case 1: (*ip_list)[(*count)*8 +i]=128; z=0; break;
	 case 2: (*ip_list)[(*count)*8 +i]=192; z=0; break;
	 case 3: (*ip_list)[(*count)*8 +i]=224; z=0; break;
	 case 4: (*ip_list)[(*count)*8 +i]=240; z=0; break;
	 case 5: (*ip_list)[(*count)*8 +i]=248; z=0; break;
	 case 6: (*ip_list)[(*count)*8 +i]=252; z=0; break;
	 case 7: (*ip_list)[(*count)*8 +i]=254; z=0; break;
	}
      }
   }

 //Convert ip/mask to net/mask
 (*ip_list)[*count*8]  &=(*ip_list)[*count*8+4];
 (*ip_list)[*count*8+1]&=(*ip_list)[*count*8+5];
 (*ip_list)[*count*8+2]&=(*ip_list)[*count*8+6];
 (*ip_list)[*count*8+3]&=(*ip_list)[*count*8+7];
   
 // inc counter
 (*count)++;

 #ifdef DEBUG_IP
 fprintf(stderr," IP LIST\n");
 for (z=0;z<(*count *8);z+=8)
   fprintf (stderr,"%i %i.%i.%i.%i/%i.%i.%i.%i\n",z/8,(*ip_list)[z],(*ip_list)[z+1],(*ip_list)[z+2],(*ip_list)[z+3],(*ip_list)[z+4],(*ip_list)[z+5],(*ip_list)[z+6],(*ip_list)[z+7]);
 #endif
 return(0);

}


/********************************************************
 ******* Check of hit input IP to ip_list *******/

 int check_ip(char *ip_list,int last)
 {
  int z;


     for (z=0;z<last*8;z+=8)
     {    
       if ( ip_list[z]  ==( input_ip[0] & ip_list[z+4] ) &&\
	    ip_list[z+1]==( input_ip[1] & ip_list[z+5] ) &&\
	    ip_list[z+2]==( input_ip[2] & ip_list[z+6] ) &&\
	    ip_list[z+3]==( input_ip[3] & ip_list[z+7] ))
               return (1);
     }
     return (0);
 }																			 
