recently for one of the packet fuzzers i coded,i wanted to add a feature to send fragmented packets.here is the code i wrote according to the RFC:-
/*This function fragments the ip packets and sends them on the wire
parameter passed:MTU,pcap header ,packet len,vlan header present or not
return value:none
follows RFC791 http://www.ietf.org/rfc/rfc791.txt
*/
void FragmentAndSendIPPackets(struct pcap_pkthdr *pktheader,u_char* Packet,u_int len){
ethernet* EthHeader;
ip* IPHeader;
ip* OrigIPHeader;
ip* NewIPHeader;
u_short NFB=0;
u_short MTU;
u_short OrigFragOff;
u_short OrigMF;
MTU=FragmentMTU;
/*here we will check if the packet contains the VLAN header if yes then ip header will be at
ethernet header+4 bytes
*/
if(strcmp(AddVLANHeaderflg,"1")==0)
{
VLAN *VLANHeader;
VLANHeader=(VLAN*)(Packet+14);
//here we will check ip the VLAN->protocol is ip else we simply send the packet
if(ntohs(VLANHeader->Proto)==0x0800)
{
IPHeader=(ip*)(Packet+14+4);
}
else
{
SendPacket(pktheader,Packet,len);
return;
}
}
else //if VLAN is not present then simple ip header=ethernet header+14
{
IPHeader=(ip*)(Packet+14);
}
//start of fragmentation algo
//if ip>ip_len is more then MTU then only we need to fragment otherwise send the packet
if(ntohs(IPHeader->ip_len)>MTU)
{
//copy the orignal ip header
OrigIPHeader=(ip*)malloc(sizeof(ip)+1);
memset(OrigIPHeader,'\0',sizeof(ip)+1);
memcpy(OrigIPHeader,IPHeader,sizeof(ip));
//copy the data for future use
OrigFragOff=ntohs(OrigIPHeader->ip_off);
OrigMF=OrigFragOff & IP_MF;
//first fragment
NFB=(MTU-IP_HL(OrigIPHeader)*4)/8;
u_short FirstIPLen;
FirstIPLen=IP_HL(OrigIPHeader)*4+NFB*8;
NewIPHeader=(ip*)malloc(IP_HL(OrigIPHeader)*4+1);
memset(NewIPHeader,'\0',IP_HL(OrigIPHeader)*4+1);
memcpy(NewIPHeader,OrigIPHeader,IP_HL(OrigIPHeader)*4);
//its a framgneted packet so we need to set the more fragment bit=1
u_short MF=1;
u_short IP_OFF;
IP_OFF=ntohs(NewIPHeader->ip_off);
MF=MF<<13;
IP_OFF|=MF;
NewIPHeader->ip_off=htons(IP_OFF);
NewIPHeader->ip_len=htons(IP_HL(OrigIPHeader)*4+NFB*8);
NewIPHeader->ip_sum=0;
NewIPHeader->ip_sum=htons(ComputeIPCheckSum(IP_HL(NewIPHeader)*4,NewIPHeader));
u_char* FirstFragPacket;
if(strcmp(AddVLANHeaderflg,"1")!=0)
{
FirstFragPacket=(u_char*)malloc(14+FirstIPLen+1);
memset(FirstFragPacket,'\0',14+FirstIPLen+1);
memcpy(FirstFragPacket,Packet,14);
memcpy(FirstFragPacket+14,(u_char*)NewIPHeader,IP_HL(NewIPHeader)*4);
memcpy(FirstFragPacket+14+IP_HL(NewIPHeader)*4,Packet+14+IP_HL(NewIPHeader)*4,NFB*8);
pktheader->len=14+FirstIPLen;
pktheader->caplen=14+FirstIPLen;
}
else
{
FirstFragPacket=(u_char*)malloc(14+4+FirstIPLen+1);
memset(FirstFragPacket,'\0',14+4+FirstIPLen+1);
memcpy(FirstFragPacket,Packet,18);
memcpy(FirstFragPacket+14+4,(u_char*)NewIPHeader,IP_HL(NewIPHeader)*4);
memcpy(FirstFragPacket+14+4+IP_HL(NewIPHeader)*4,Packet+14+4+IP_HL(NewIPHeader)*4,NFB*8);
pktheader->len=14+4+FirstIPLen;
pktheader->caplen=14+4+FirstIPLen;
}
SendPacket(pktheader,FirstFragPacket,FirstIPLen);
free(NewIPHeader);
NewIPHeader=NULL;
free(FirstFragPacket);
FirstFragPacket=NULL;
u_char* SecondFragPacket;
u_short SecondIPLen;
u_short FragOff;
SecondIPLen=ntohs(OrigIPHeader->ip_len)-NFB*8;
NewIPHeader=(ip*)malloc(IP_HL(OrigIPHeader)*4+1);
memset(NewIPHeader,'\0',IP_HL(OrigIPHeader)*4+1);
memcpy(NewIPHeader,OrigIPHeader,IP_HL(OrigIPHeader)*4);
//correct the fields
NewIPHeader->ip_len=htons(SecondIPLen);
FragOff=OrigFragOff+NFB;
FragOff|=OrigMF;
NewIPHeader->ip_off=htons(FragOff);
if(strcmp(AddVLANHeaderflg,"1")!=0)//VLAN header is not present
{
SecondFragPacket=(u_char*)malloc(14+SecondIPLen+1);
memset(SecondFragPacket,'\0',14+SecondIPLen+1);
memcpy(SecondFragPacket,Packet,14);
memcpy(SecondFragPacket+14,(u_char*)NewIPHeader,IP_HL(NewIPHeader)*4);
memcpy(SecondFragPacket+14+IP_HL(NewIPHeader)*4,Packet+14+IP_HL(NewIPHeader)*4+NFB*8,ntohs(OrigIPHeader->ip_len)-IP_HL(OrigIPHeader)*4-NFB*8);
pktheader->len=14+SecondIPLen;
pktheader->caplen=14+SecondIPLen;
//this is the reamining fragment and there might be further fragment possible so recursivaly call the fragment function until the ip->lenip_len)-IP_HL(OrigIPHeader)*4-NFB*8);
pktheader->len=14+4+SecondIPLen;
pktheader->caplen=14+4+SecondIPLen;
free(OrigIPHeader);
OrigIPHeader=NULL;
free(NewIPHeader);
NewIPHeader=NULL;
FragmentAndSendIPPackets(pktheader,SecondFragPacket,14+SecondIPLen);
free(SecondFragPacket);
SecondFragPacket=NULL;
}
}
else //ip->len <=MTU so no need to fragment simply send the packet
{
IPHeader->ip_sum=0;
IPHeader->ip_sum=htons(ComputeIPCheckSum(IP_HL(IPHeader)*4,IPHeader));
SendPacket(pktheader,Packet,len);
}
}
















