分享

【转】使用dev_queue_xmit发送定制报文

 enchen008 2013-09-11

原文地址:http://blog./u1/53031/showart_726099.html

本文档的Copyleft归necofang所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn :

来源:

   本文通过实例讲述如何使用dev_queue_xmit来直接发送udp和tcp报文。示例代码在linux-2.6.24上可以编译执行。
  
   用于调试的代码:#define MSG_DEBUG(msg...) printk(KERN_INFO "cup: " msg)

#define IP_PARTS_NATIVE(n) \
(unsigned int)((n)&0xFF),                         \
    (unsigned int)((n)>>8)&0xFF,                    \
    (unsigned int)((n)>>16)&0xFF,                   \
    (unsigned int)((n)>>24)&0xFF

#define XMIT(skb, rt)                              \
        NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \
                (rt)->u.dst.dev, dst_output);     

void dump_block(char *s, caddr_t bb, int len)
{
int i;
unsigned char *b = bb;

printk(KERN_INFO "dump: ""at %s, len=%d:\n", s, len);

for(i = 0; i < len; i++ /*, c++*/) {
    if(!(i % 16)) {
      printk(KERN_INFO "dump:   @%03x:", i);
    }
    printk(" %02x", b[i]);
    if(!((i + 1) % 16)) {
      printk("\n");
    }
}
if(i % 16) {
    printk("\n");
}
}

void print_ip(struct iphdr *ip)
{
printk(KERN_INFO "debug:   IP:");
printk(" ihl:%d", ip->ihl << 2);
printk(" ver:%d", ip->version);
printk(" tos:%d", ip->tos);
printk(" tlen:%d", ntohs(ip->tot_len));
printk(" id:%d", ntohs(ip->id));
printk(" %s%s%sfrag_off:%d",
    ip->frag_off & __constant_htons(IP_CE) ? "CE " : "",
    ip->frag_off & __constant_htons(IP_DF) ? "DF " : "",
    ip->frag_off & __constant_htons(IP_MF) ? "MF " : "",
    (ntohs(ip->frag_off) & IP_OFFSET) << 3);
printk(" ttl:%d", ip->ttl);

printk(" proto:%d", ip->protocol);
if(ip->protocol == IPPROTO_UDP)
    printk(" (UDP)");
if(ip->protocol == IPPROTO_TCP)
    printk(" (TCP)");
if(ip->protocol == IPPROTO_ICMP)
    printk(" (ICMP)");
if(ip->protocol == IPPROTO_ESP)
    printk(" (ESP)");
if(ip->protocol == IPPROTO_AH)
    printk(" (AH)");
if(ip->protocol == IPPROTO_COMP)
    printk(" (COMP)");
printk(" chk:%d", ntohs(ip->check));

printk(" saddr:%d.%d.%d.%d", IP_PARTS_NATIVE(ip->saddr));
if(ip->protocol == IPPROTO_UDP)
    printk(":%d", __constant_htons(((struct udphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));

if(ip->protocol == IPPROTO_TCP)
    printk (":%d", __constant_htons(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->source));

printk(" daddr:%d.%d.%d.%d", IP_PARTS_NATIVE(ip->daddr));
if(ip->protocol == IPPROTO_UDP)
    printk(":%d", __constant_htons(((struct udphdr*)((u_char * )ip + (ip->ihl << 2)))->dest));

if(ip->protocol == IPPROTO_TCP)
    printk(":%d", __constant_htons(((struct tcphdr*)((caddr_t)ip + (ip->ihl << 2)))->dest));

if(ip->protocol == IPPROTO_ICMP)
    printk(" type:code=%d:%d", ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->type,
       ((struct icmphdr*)((caddr_t)ip + (ip->ihl << 2)))->code);
printk("\n");

//dump_block ("PACKET DUMP", (caddr_t)ip, ntohs(ip->tot_len));
}
skb destroy
void cup_destroy (struct sk_buff *skb)
{
dev_put(skb->dev);
}
tcp输出
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);

if (NULL == skb) goto out;

skb_reserve (skb, LL_RESERVED_SPACE (dev));

skb->dev = dev;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = __constant_htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_NONE;
skb->destructor = cup_destroy;
skb->priority = 0;

skb->network_header = skb_put (skb, sizeof (struct iphdr));
skb->transport_header = skb_put (skb, sizeof (struct tcphdr));
pdata = skb_put (skb, pkt_len);

{
    if (NULL != pkt) memcpy (pdata, pkt, pkt_len);
}

{
    tcph = (struct tcphdr *) skb->transport_header;
    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->ack = 1;
    tcph->window = __constant_htons (65535);
    skb->csum = 0;
    tcph->check = 0;
}

{
    iph = (struct iphdr*) skb->network_header;
    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);

ip_send_check(iph);

skb->mac_header = skb_push (skb, 14);
{ //eth header
    ethdr = (struct ethhdr *) skb->mac_header;
    memcpy (ethdr->h_dest, dmac, ETH_ALEN);
    memcpy (ethdr->h_source, smac, ETH_ALEN);
    ethdr->h_proto = __constant_htons (ETH_P_IP);
}

print_ip ((struct iphdr *)skb->network_header);

dump_block ("before xmit", skb->data, skb->len);

if (0 > dev_queue_xmit(skb)) goto out;
MSG_DEBUG ("dev_queue_xmit succ\n");
MSG_DEBUG ("skb->len = %d\n", skb->len);

nret = 0;
out:
if (0 != nret && NULL != skb) {dev_put (dev); kfree_skb (skb);}

return (nret);
}
udp输出

void my_cup (void)
{
struct sk_buff * skb = NULL;
struct net_device * dev = NULL;
u_char pkt_eth [14] = {
    0x00, 0x1E, 0x37, 0x82, 0x9D, 0xFF, 0x00, 0x0C,
    0x29, 0xF1, 0xF9, 0x87, 0x08, 0x00 }; //eth
u_char pkt_ip [20] = {
    0x45, 0x00,
    0x00, 0x54, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01,
    0xB6, 0x90, 0xC0, 0xA8, 0x01, 0x67, 0xC0, 0xA8,
    0x01, 0x61 }; //ip
u_char pkt_icmp [8] = {
    0x08, 0x00, 0x2A, 0x7D, 0x1B, 0x08, //icmp
    0x00, 0x01 };
u_char pkt_data [56] = {
    0x69, 0xD5, 0x43, 0x48, 0x14, 0x59,
    0x06, 0x00, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
    0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
    0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
    0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
    0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
    0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
    0x36, 0x37
};

MSG_DEBUG ("send \n");

dev = dev_get_by_name (&init_net, "eth2");

MSG_DEBUG ("dev name : %s\n", dev->name);

skb = alloc_skb (100, GFP_ATOMIC);
//skb = dev_alloc_skb (100);

if (NULL == skb) return;

skb->dev = dev;
skb->pkt_type = PACKET_OTHERHOST;//PACKET_OUTGOING;
skb->protocol = __constant_htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_NONE;
skb->destructor = cup_destroy;
skb->priority = 0;

skb_reserve (skb, 16);

memcpy (skb_push (skb, 14), pkt_eth, 14);

skb->network_header = skb_put (skb, sizeof (struct iphdr));
memcpy (skb->network_header, pkt_ip, sizeof (struct iphdr));

skb->transport_header = skb_put (skb, sizeof (struct icmphdr));
memcpy (skb->transport_header, pkt_icmp, sizeof (struct icmphdr));

memcpy (skb_put (skb, 56), pkt_data, 56);

MSG_DEBUG ("skb->network_header = %p \n", skb->network_header);
MSG_DEBUG ("skb->data %p \n", skb->data);
MSG_DEBUG ("skb->tail %p \n", skb->tail);
skb->tail = skb->data + 98;
MSG_DEBUG ("skb->tail %p \n", skb->tail);

print_ip ((struct iphdr *)skb->network_header);

dump_block ("before xmit", skb->data, skb->len);

if (0 > dev_queue_xmit(skb)) { kfree_skb (skb); dev_put(dev); MSG_DEBUG ("dev_queue_xmit error\n"); }
else {
    MSG_DEBUG ("dev_queue_xmit succ\n");
    MSG_DEBUG ("skb->len = %d\n", skb->len);
}

return;
}
代码很简单,我就不多做说明了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多