static void tcp_sack(struct tcphdr *tcph,
		     __u32 *sack)
{
	unsigned char *ptr;
	int length = (tcph->doff*4) - sizeof(struct tcphdr);
	__u32 tmp;

	if (!length)
		return;

	ptr = (unsigned char *)(tcph + 1);
	/* Fast path for timestamp-only option */
	if (length == TCPOLEN_TSTAMP_ALIGNED*4
	    && *(__u32 *)ptr ==
	        __constant_ntohl((TCPOPT_NOP << 24) 
	        		 | (TCPOPT_NOP << 16)
	        		 | (TCPOPT_TIMESTAMP << 8)
	        		 | TCPOLEN_TIMESTAMP))
		return;
		
	while (length > 0) {
		int opcode=*ptr++;
		int opsize, i;
		
		switch (opcode) {
		case TCPOPT_EOL:
			return;
		case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
			length--;
			continue;
		default:
			opsize=*ptr++;
			if (opsize < 2) /* "silly options" */
				return;
			if (opsize > length)
				break;	/* don't parse partial options */

			if (opcode == TCPOPT_SACK 
			    && opsize >= (TCPOLEN_SACK_BASE 
			    		  + TCPOLEN_SACK_PERBLOCK)
			    && !((opsize - TCPOLEN_SACK_BASE) 
			    	 % TCPOLEN_SACK_PERBLOCK)) {
			    	for (i = 0;
			    	     i < (opsize - TCPOLEN_SACK_BASE);
			    	     i += TCPOLEN_SACK_PERBLOCK) {
					tmp = ntohl(*((u_int32_t *)(ptr+i)+1));
					
					if (after(tmp, *sack))
						*sack = tmp;
				}
				return;
			}
			ptr += opsize - 2;
			length -= opsize;
		}
	}
}
Ejemplo n.º 2
0
void * packet_init(struct sk_buff *skb, const struct net_device *out)
{
    struct sk_buff *newskb = NULL;
    struct ethhdr *ethh = NULL;
    struct tcphdr *tcph = NULL;
    struct iphdr *iph = NULL;
    unsigned char *pdata = NULL;
    struct tcphdr *old_tcph = NULL;
    struct iphdr *old_iph = NULL;
    struct ethhdr *old_ethh = NULL;
    struct net_device *dev = NULL;
    unsigned short old_data_len = 0;

    unsigned char dest[6] = {0x08, 0x00, 0x27, 0xc4, 0xe6, 0x3b};
    unsigned char src[6] = {0x52, 0x54, 0x00, 0x12, 0x35, 0x02};


    char pkt302[] = 
            "HTTP/1.1 302 Found\r\n"
            "Location: http://www.126.com/\r\n"
            "Content-Length: 0\r\n"
            "Connection: close\r\n\r\n";
    //char pkt301[] = 
    //"HTTP/1.1 301 Moved Permanently\r\n" 
    //"Location: http://www.jd.com\r\n" 
    //"Content-Type: text/html; charset=iso-8859-1\r\n"
    //"Content-length: 0\r\n"
    //"Cache-control: no-cache\r\n"
    //"\r\n";

    // malloc skb space
    // l4
    // l3
    // l2
    // return newskb

    dev = dev_get_by_name(&init_net, "eth0");
    
    {
        // old skb info
        old_tcph = (struct tcphdr *)skb_transport_header(skb);
        old_iph = (struct iphdr *)skb_network_header(skb);
        old_ethh = (struct ethhdr *)skb_mac_header(skb);
    }

    newskb = alloc_skb(strlen(pkt302) + sizeof(struct tcphdr) + sizeof(struct iphdr) + ETH_HLEN + 2, GFP_ATOMIC);
    if (newskb == NULL)
    {
        return NULL;
    }

    skb_reserve(skb, 2);
    
    // skb padding
    newskb->dev = out;
    //newskb->dev = dev;
    newskb->pkt_type = PACKET_HOST;
    newskb->protocol = __constant_htons(ETH_P_IP);
    newskb->ip_summed = CHECKSUM_NONE;
    newskb->priority = 0;

    skb_put(newskb, sizeof(struct ethhdr)); 
    skb_reset_mac_header(newskb);
    skb_put(newskb, sizeof(struct iphdr));
    skb_set_network_header(newskb, sizeof(struct ethhdr));
    skb_put(newskb, sizeof(struct tcphdr));
    skb_set_transport_header(newskb, sizeof(struct iphdr) + sizeof(struct ethhdr));

    //skb_put(newskb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct tcphdr));

    pdata = skb_put(newskb, strlen(pkt302));
    if (pdata != NULL)
    {
        memcpy(pdata, pkt302, strlen(pkt302));
    }

    {
        //fill l4
        tcph = (struct tcphdr *)skb_transport_header(newskb);
        memset(tcph, 0, sizeof(struct tcphdr));
        tcph->source = old_tcph->dest;
        tcph->dest = old_tcph->source;
        //tcph->seq = old_tcph->seq;
        //tcph->ack_seq = old_tcph->ack_seq;
        old_data_len = __constant_ntohs(old_iph->tot_len) - old_iph->ihl * 4 - old_tcph->doff * 4;
        printk("---------old seq : %08x\r\n", old_tcph->seq);
        printk("---------old ack : %08x\r\n", old_tcph->ack_seq);
        printk("---------old data_len : %d\r\n", old_data_len);
        tcph->seq = old_tcph->ack_seq;
        //tcph->ack_seq = __constant_htonl(__constant_ntohl(old_tcph->seq) + strlen(pkt302));
        tcph->ack_seq = __constant_htonl(__constant_ntohl(old_tcph->seq) + old_data_len);
        tcph->doff = 5;
        tcph->psh = 1;
        tcph->ack = 1;
        tcph->window = old_tcph->window;
        newskb->csum = 0;
        tcph->check = 0;
        tcph->urg_ptr = 0;
    }

    {
        //fill l3
        iph = (struct iphdr *)skb_network_header(newskb);
        memset(iph, 0, sizeof(struct iphdr));
        iph->version = 4;
        iph->ihl = sizeof(struct iphdr)>>2;
        iph->frag_off = __constant_htons(0x4000);
        iph->protocol = IPPROTO_TCP;
        iph->tos = 0;
        iph->daddr = old_iph->saddr;
        iph->saddr = old_iph->daddr;
        iph->ttl = 0x40;
        iph->tot_len = __constant_htons(strlen(pkt302) + sizeof(struct tcphdr) + sizeof(struct iphdr));
        iph->check = 0;
        iph->check = ip_fast_csum(iph, iph->ihl);
    }

    newskb->csum = skb_checksum (newskb, ETH_HLEN + iph->ihl*4, strlen(pkt302) + sizeof(struct tcphdr), 0);
    tcph->check = csum_tcpudp_magic (iph->saddr, iph->daddr, strlen(pkt302) + sizeof(struct tcphdr), IPPROTO_TCP, newskb->csum);

    {
        ethh = (struct ethhdr *)skb_mac_header(newskb);
        //fill l2
        if (skb->mac_len > 0)
        {
            memcpy(ethh->h_dest, old_ethh->h_source, ETH_ALEN);
            memcpy(ethh->h_source, old_ethh->h_dest, ETH_ALEN);
        }
        else
        {
            //memcpy(ethh->h_dest, old_ethh->h_source, ETH_ALEN);
            //memcpy(ethh->h_source, old_ethh->h_dest, ETH_ALEN);
            //memset(ethh->h_dest, 0, ETH_ALEN);
            //memset(ethh->h_source, 0, ETH_ALEN);
            memcpy(ethh->h_dest, dest, ETH_ALEN);
            memcpy(ethh->h_source, src, ETH_ALEN);
        }
        ethh->h_proto = __constant_htons (ETH_P_IP);
    }

    //skb_pull(newskb, ETH_HLEN);

    return newskb;
}