天天看點

《教你修改以及重構skb》在2.6.30上的實作

但ubuntuer兄的代碼是基于2.6.18的,比較舊。今天經過摸索,我終于讓其可以在2.6.30上運作了,代碼如下:

skb_DIY.c

#include

MODULE_LICENSE("GPL");

MODULE_AUTHOR("[email protected]");

#define    ETH     "eth0"

#define    SIP     "192.168.238.180"

#define    DIP     "192.168.1.101"

#define    SPORT   39804

#define    DPORT   80

unsigned char   SMAC[ETH_ALEN] = {0x00,0x0C,0x29,0x4F,0xDE,0xAC};

unsigned char   DMAC[ETH_ALEN] = {0x00,0x50,0x56,0xFA,0x70,0x2A};

int cp_dev_xmit_tcp (char * eth, u_char * smac, u_char * dmac,

             u_char * pkt, int pkt_len,

             u_long sip, u_long dip,

             u_short sport, u_short dport, u_long seq, u_long ack_seq, u_char psh, u_char fin)

{

    struct sk_buff * skb = NULL;

    struct net_device * dev = NULL;

    struct ethhdr * ethdr = NULL;

    struct iphdr * iph = NULL;

    struct tcphdr * tcph = NULL;

    u_char * pdata = NULL;

    int nret = 1;

    if (NULL == smac || NULL == dmac) goto out;

    dev = dev_get_by_name(&init_net, eth);

    if (NULL == dev)

        goto out;

    skb = alloc_skb (pkt_len + sizeof (struct iphdr) + sizeof (struct tcphdr) + LL_RESERVED_SPACE (dev), GFP_ATOMIC);

    /* 

    LL_RESERVED_SPACE(dev) = 16

    alloc_skb傳回以後,skb->head = skb_data = skb->tail =  alloc_skb配置設定的記憶體區首位址,skb->len = 0;

    skb->end = skb->tail + size;

         注:我的機子是32位x86機器,是以沒有定義NET_SKBUFF_DATA_USES_OFFSET,因而,

     skb->tail,skb->mac_header,skb->network_header,skb->transport_header這幾個成員都是指針

    */

      if (NULL == skb)

            goto out;

    skb_reserve (skb, LL_RESERVED_SPACE (dev));//add data and tail

    skb->dev = dev;

    skb->pkt_type = PACKET_OTHERHOST;

    skb->protocol = __constant_htons(ETH_P_IP);

    skb->ip_summed = CHECKSUM_NONE;

    skb->priority = 0;

    //skb->nh.iph = (struct iphdr*)skb_put(skb, sizeof (struct iphdr));

    //skb->h.th = (struct tcphdr*)skb_put(skb, sizeof (struct tcphdr));

    skb_set_network_header(skb, 0);    //skb->network_header = skb->data + 0;

    skb_put(skb, sizeof (struct iphdr)); //add tail and len

    skb_set_transport_header(skb, sizeof (struct iphdr));//skb->transport_header = skb->data + sizeof (struct iphdr)

    skb_put(skb, sizeof (struct tcphdr));   

    pdata = skb_put (skb, pkt_len);

      {

            if (NULL != pkt)

                 memcpy (pdata, pkt, pkt_len);

      }

    {

        tcph = tcp_hdr(skb);

        memset (tcph, 0, sizeof (struct tcphdr));

        tcph->source = sport;

        tcph->dest = dport;

        tcph->seq = seq;

        tcph->ack_seq = ack_seq;

        tcph->doff = 5;

        tcph->psh = psh;

        tcph->fin = fin;

        tcph->syn = 1;

        tcph->ack = 0;

        tcph->window = __constant_htons (5840);

        skb->csum = 0;

        tcph->check = 0;

    }

        iph = ip_hdr(skb);

        iph->version = 4;

        iph->ihl = sizeof(struct iphdr)>>2;

        iph->frag_off = 0;

        iph->protocol = IPPROTO_TCP;

        iph->tos = 0;

        iph->daddr = dip;

        iph->saddr = sip;

        iph->ttl = 0x40;

        iph->tot_len = __constant_htons(skb->len);

        iph->check = 0;

      skb->csum = skb_checksum (skb, iph->ihl*4, skb->len - iph->ihl * 4, 0);

    tcph->check = csum_tcpudp_magic (sip, dip, skb->len - iph->ihl * 4, IPPROTO_TCP, skb->csum);

        ethdr = (struct ethhdr*)skb_push (skb, 14);//reduce data and add len

        memcpy (ethdr->h_dest, dmac, ETH_ALEN);

        memcpy (ethdr->h_source, smac, ETH_ALEN);

        ethdr->h_proto = __constant_htons (ETH_P_IP);

     if (0 > dev_queue_xmit(skb)) goto out;

    nret = 0;

out:

    if (0 != nret && NULL != skb)

        dev_put (dev);

        kfree_skb (skb);

      return (nret);

}

static int __init init(void)

    printk("%s\n","insmod skb_diy module\n");

        cp_dev_xmit_tcp (ETH, SMAC, DMAC,NULL, 0,

                    in_aton(SIP),in_aton(DIP),

                    htons(SPORT),htons(DPORT),

                    0, 0, 0, 0);

    return 0;

static void __exit fini(void)

    printk("%s\n","remove skb_diy module.\n");

module_init(init);

module_exit(fini);

Makefile:

PWD:=$(shell pwd)

KERNEL_SRC = /lib/modules/`uname -r`/build

obj-m:=skb_DIY.o

skb_DIY-objs:=skb.o

all:

    make -C $(KERNEL_SRC) M=$(PWD) modules

clean:

    rm -f *.o

    rm -f *.ko

    rm -f .*.cmd

    rm -rf .tmp_versions

    rm -f *.mod.c

    rm -f *.symvers

    rm -f *.order