Hi everybody!!!
>    
>  I am writting an application to intercept packects with a certain
destination
> port, send them to my application, and then modify them and reinject them.
I have a big      problem, that I cannot solve.
> . When I intercept the packet I allocate memory to have the new
> modified packet and later I reinject this new packet that it is stored in
a
> different memory position that the original one. I can see that this
packet
> reachs the destination, but now the problems starts, the application then
> start to receive copies from the original one, I do not how, but in the
> queue several copies were created, and the following packets are not
reinjected.
>
>    If the modification that I do to the packet does not implies to change
> the length and therefore not to change the memory address, the application
> works fine. So I think that the problem lies in the fact that I need to
> move the packet to another memory address, so how can I solve that?
>
>     If anybody have any idea about this strange working I will be very
grateful.
>

  Here I detail what I am doing.

   IPTABLES

   iptables -F INPUT
   iptables -A INPUT -p tcp --dport 554 -j LOG --log-prefix MY_TEST:
   iptables -A INPUT -p tcp --dport 554 -j QUEUE

 The source code is dettached below:

  int main()
{
    
  struct pseudo
  {
      unsigned long src_addr;
      unsigned long dest_addr;
      unsigned char dummy;
      unsigned char proto;
      unsigned short length;
  } pseudohead;
struct tcp_help_checksum
 {
    struct pseudo pshd;
    struct tcphdr tcphd;
   char data[1024];
 } tcp_chk_construct;

struct udp_help_checksum
  {
    struct pseudo pshd;
    struct udphdr udphd;
    char data[1024];
} udp_chk_construct;

struct ipq_handle *h;
     
int status;
    int tam;
    int flag=0;    
start_line str;
    char buff[SIZE];
    unsigned char *packet=NULL;
    struct iphdr *iph=NULL;
      struct tcphdr *tcph=NULL;
    ipq_packet_msg_t *m=NULL;
    unsigned char *payload=NULL;
    unsigned char protocol;
    unsigned char *new_packet=NULL;    
   char *address=NULL;
    unsigned char *new_setup=NULL;
    unsigned char *auxiliar1=NULL;
    unsigned char *auxcopia=NULL;
    unsigned char *copia=NULL;

        
     h=ipq_create_handle(0,PF_INET);
     if(!h) die(h);
     status=ipq_set_mode(h,IPQ_COPY_PACKET,SIZE);
        
       if(status<0) die(h);
        for(;;)
        {       
          fprintf(stderr,"\n\nprincipio\n\n"); 
 memset(buff,0,SIZE); /*Por si quedan restos de antes*/
 memset(&str,0,sizeof(str));
 memset(&pseudohead,0,sizeof(pseudohead));
 memset(&tcp_chk_construct,0,sizeof(tcp_chk_construct)); 
 memset(&udp_chk_construct,0,sizeof(udp_chk_construct));

 status=ipq_read(h,buff,SIZE,0);
                
  if(status<0)  die(h);

       
             switch(ipq_message_type(buff))
              {
                case NLMSG_ERROR:
                        fprintf(stderr,"Received error message
%d\n",ipq_get_msgerr(buff));
                        break;
                case IPQM_PACKET:
         

                m=ipq_get_packet(buff);
    
        if(!m)break;
            
         if(m->data_len>=sizeof(struct iphdr)){
                 packet = (unsigned char *)m+ sizeof(*m);
                 iph=(struct iphdr *)packet;                              
                  protocol=iph->protocol;
 
       
           
 

  if(protocol==6) { /*TCP*/
    tcph=(struct tcphdr *)(packet+iph->ihl*4);         
    payload=packet+4*(iph->ihl)+4*(tcph->doff);
                          }
                                          else {
          fprintf(stderr,"\n\n Unknown Protocol. Not doing
modification\n\n");
                                          break;
                                          }
                        
parse_start_line((char *)payload,&str);
 
if(str.type!=unknown){
        if(!strcmp(str.method,"SETUP")){ /* Packet  being modified*/
        
    
    address=dump_iphdr(packet);
    fprintf(stderr,"%s %s",address,payload);
    new_packet=(unsigned char
*)calloc(strlen(address)+13+m->data_len,sizeof(unsigned char));
   if(!new_packet){ fprintf(stderr,"\n\nNOT enough memory to modify the
packet\n\n");
   free(address);
   die(h);
  }
   memset((char *)new_packet,'\0',m->data_len+strlen(address)+13);   
   memcpy(new_packet,packet,(iph->ihl*4)+(tcph->doff*4));
   auxcopia=new_packet+(iph->ihl*4)+(tcph->doff*4);   
   
  for(auxiliar1=payload;*auxiliar1;auxiliar1++) /* New field is included
inside the original payload*/
     {
     if(!strncmp((char *)auxiliar1,"Transport",9))
       {
                   
      while(*auxiliar1!=';')auxiliar1++;
           memcpy(auxcopia,payload,(auxiliar1-payload)+1);
                    
auxcopia=auxcopia+1+(auxiliar1-payload);
           
         memcpy(auxcopia,"DESTINATION:",strlen("DESTINATION:"));
           
auxcopia=auxcopia+strlen("DESTINATION:");
           memcpy(auxcopia,address,strlen(address));
           
auxcopia=auxcopia+strlen(address);
memcpy(auxcopia,";",1);
           auxcopia++;
           auxiliar1++;
           copia=auxiliar1;
         }
     }
  


memcpy(auxcopia,copia,auxiliar1-copia);
  

/*At this point I have the new packet */   
/* Length fields are updated */

iph=(struct iphdr *)new_packet;
tcph=(struct tcphdr *)(new_packet+(iph->ihl*4));
m->data_len=m->data_len+13+strlen(address);   
iph->tot_len=htons(ntohs(iph->tot_len)+13+strlen(address));    
/*Checksum*/   
iph->check=0;
   iph->check=checksum((unsigned short*)iph,iph->ihl*4);
   tcph->check=0;
        
    pseudohead.src_addr=iph->saddr;
        pseudohead.dest_addr=iph->daddr;
        pseudohead.dummy=0;
        pseudohead.proto=iph->protocol;
        pseudohead.length=htons(ntohs(iph->tot_len)-((iph->ihl)*4));
        tcp_chk_construct.pshd=pseudohead;
        tcp_chk_construct.tcphd=*tcph;
        
              
        
memcpy(tcp_chk_construct.data,new_packet+(iph->ihl*4)+20,ntohs(iph->tot_len)
-20-((iph->ihl)*4));
  tcph->check=checksum((unsigned short
*)&tcp_chk_construct,ntohs(iph->tot_len)-(4*(iph->ihl))+sizeof(pseudohead));
  fprintf(stderr,"\n\nEL PAQUETE VALE
%s\n\n",new_packet+(iph->ihl*4)+(tcph->doff*4));  

  /* The packet is accepted*/
  ipq_set_verdict(h,m->packet_id,NF_ACCEPT,m->data_len,new_packet);
  
    break;
}
                        else{
                        
       status =
ipq_set_verdict(h,m->packet_id,NF_ACCEPT,m->data_len,packet);
                                if (status < 0) die(h);
                                             break;
                                  
                        }
  }
                        else { /*LO aCEpto pq son de la conexion*/
       status =
ipq_set_verdict(h,m->packet_id,NF_ACCEPT,m->data_len,packet);
                                        if (status < 0)die(h);
                                            break;
                                  
                        }
                 }
                 else { /*LO DROPPEO No suficiente longitud*/
      status=ipq_set_verdict(h,m->packet_id,NF_DROP,m->data_len,packet);

      if(status<0) die(h);
      break;
                 }
                        
                
                default:
                        fprintf(stderr,"UNknown message !!!\n");
                        break;
              }
                
        }       
return 0;
}




char *dump_iphdr(unsigned char *packet)
{

 
  unsigned char value;
  char *aux;
  struct dstring addr;
  struct iphdr *iph=(struct iphdr *)packet;  


  
dstring_init(&addr);
  aux=(char *)calloc(3,sizeof(char));
  value=(ntohl(iph->saddr)>>24)&0xFF;
  sprintf(aux,"%d",value);
   dstring_append(&addr,aux,strlen(aux));
        dstring_append(&addr,".",1);
  value=(ntohl(iph->saddr)>>16)&0xFF;
  sprintf(aux,"%d",value);
   dstring_append(&addr,aux,strlen(aux));
        dstring_append(&addr,".",1);
  value=(ntohl(iph->saddr)>>8)&0xFF;
  sprintf(aux,"%d",value);
   dstring_append(&addr,aux,strlen(aux));
        dstring_append(&addr,".",1);
  
    value=(ntohl(iph->saddr))&0xFF;
 sprintf(aux,"%d",value);
   dstring_append(&addr,aux,strlen(aux));

free(aux);      

return addr.ptr; 


}   


unsigned short checksum(unsigned short *addr,int len)
{
  int nleft=len;
  int sum=0;
  unsigned short *w=addr;
  unsigned short answer=0;

  
while(nleft>1)
    {
      sum+=*w++;
        
nleft-=2;
    }
  if(nleft==1)
    {
      *(unsigned char *)(&answer)=*(unsigned char *)w;
      sum+=answer;     
     
           

     

  
}
  sum=(sum>>16)+(sum&0xffff);
  sum+=(sum>>16);
 
answer=~sum;
  return answer;
}

void die(struct ipq_handle *h){
        ipq_perror("error");
        ipq_destroy_handle(h);
        exit(1);
}


  Thanks in advance.



Reply via email to