Пример #1
0
//Hook function for outgoing packets
static unsigned int hook_func_out(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
	struct iphdr *ip_header=NULL;         //IP  header structure
	struct tcphdr *tcp_header=NULL;       //TCP header structure
	unsigned short int src_port;     	  //TCP source port
	
	ip_header=(struct iphdr *)skb_network_header(skb);

	//The packet is not ip packet (e.g. ARP or others)
	if (!ip_header)
	{
		return NF_ACCEPT;
	}
	
	if(ip_header->protocol==IPPROTO_TCP) //TCP
	{
		tcp_header = (struct tcphdr *)((__u32 *)ip_header+ ip_header->ihl);
		src_port=htons((unsigned short int) tcp_header->source);
		if(src_port==5001)
		{
			tcp_modify_timestamp(skb,get_tsval());
		}
	}
	return NF_ACCEPT;
}
Пример #2
0
//Modify incoming TCP packets and return RTT sample value
u32 tcp_modify_incoming(struct  sk_buff *skb, u32 time)
{
	struct iphdr *ip_header=NULL;	//IP  header structure
	struct tcphdr *tcp_header=NULL;	//TCP header structure
	unsigned short tcp_header_len=0;	//TCP header length
	u8 *tcp_opt=NULL;	//TCP option pointer
	u32 *tsecr=NULL;	//TCP Timestamp echo reply pointer
	unsigned short tcplen=0;	//TCP packet length
	u8 tcp_opt_value=0;	//TCP option pointer value
	u32 rtt=0;	//Sample RTT
	
	//If we can not modify this packet, return 0
	if(skb_linearize(skb)!=0) 
	{
		return 0;
	}
	
	//Get IP header
	ip_header=(struct iphdr *)skb_network_header(skb);
	//Get TCP header on the base of IP header
	tcp_header=(struct tcphdr *)((__u32 *)ip_header+ ip_header->ihl);
	//Get TCP header length
	tcp_header_len=(unsigned short)(tcp_header->doff*4);
	
	//Minimum TCP header length=20(Raw TCP header)+10(TCP Timestamp option)
	if(tcp_header_len<30)
	{
		return 0;
	}
	
	//TCP option offset=IP header pointer+IP header length+TCP header length
	tcp_opt=(u8*)ip_header+ip_header->ihl*4+20;
	//printk(KERN_INFO "TCP header length is %hu\n",tcp_header_len);

	while(1)
	{
		//If pointer has moved out off the range of TCP option, stop current loop
		if(tcp_opt-(u8*)tcp_header>=tcp_header_len)
		{
			break;
		}
		//Get value of current byte
		tcp_opt_value=*tcp_opt;
		
		if(tcp_opt_value==0x01)//No-Operation (NOP)
		{
			//Move to next byte
			tcp_opt++;
		}
		else if(tcp_opt_value==0x08) //TCP option kind: Timestamp (8)
		{
			//Get pointer to Timestamp echo reply (TSecr)
			tsecr=(u32*)(tcp_opt+6);
			//Get one RTT sample
			rtt=get_tsval()-ntohl(*tsecr);
			//printk(KERN_INFO "Echo back value: %u\n",ntohl(*tsecr));
			//Modify TCP TSecr back to jiffies
			//Don't disturb TCP. Wrong TCP timestamp echo reply may reset TCP connections
			*tsecr=htonl(time);
			break;
		}
		else //Other TCP options (e.g. MSS(2))
		{
			//Move to next byte to get length of this TCP option 
			tcp_opt++;
			//Get length of this TCP option
			tcp_opt_value=*tcp_opt;
			//Move to next TCP option
			tcp_opt=tcp_opt+1+((unsigned int)tcp_opt_value-2);
		}
	}
	
	//TCP length=Total length - IP header length
	//tcplen=(ip_header->tot_len)-(ip_header->ihl<<2);
	tcplen=skb->len-(ip_header->ihl<<2);
	tcp_header->check=0;
	tcp_header->check = csum_tcpudp_magic(ip_header->saddr, ip_header->daddr,tcplen, ip_header->protocol,csum_partial((char *)tcp_header, tcplen, 0));
	skb->ip_summed = CHECKSUM_UNNECESSARY;
	return rtt;
}