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.