Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8001
  • 博文数量: 1
  • 博客积分: 75
  • 博客等级: 民兵
  • 技术积分: 22
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-30 09:29
文章分类
文章存档

2010年(1)

我的朋友
最近访客

分类: LINUX

2010-07-30 09:38:44

 
 
问题已解,原因只有一个,那就是协议头的指针位置不对啦(不好意思,太大意啦):

1、skb_set_network_header(skb, 0);
    应该改成   skb_set_network_header(skb, sizeof(struct ethhdr));
2、skb_set_transport_header(skb, sizeof(struct iphdr));
    应该改成   skb_set_transport_header(skb, sizeof(struct ethhdr) + sizeof(struct iphdr));

最新的代码我也附给大家:  (14.96 KB)

注:ubuntu-9.10下直接make即可,只在初始化的时候发一个udp包

资源中心链接:http://blogimg.chinaunix.net/blog/upfile2/100730094319.bz2

 


原贴:

我在内核构造一帧数据想发出去,使用了两种方法均以失败告终,用抓包工具根本没抓到,请指教(附源码)

这是源码包

可以直接make,生成testmodule.ko,插入后便会发一帧数据出去,但是用嗅探器(wireshark)抓不到我发的包,看样子是没发出去

但是两种方法中,dev_queue_xmit及kernel_sendmsg都没有返回错误,贴出代码如下(头文件在源码包里),大家也可以直接看附件里的源码

在testmod_init中大家可以发现,我尝试了两种方式,一种是通过kernel socket发包,另一种是DIY sk_buff发包,可惜呀,都没有成功,不清楚问题到底出在了什么地方,请大家指教一下



#include "testmodule.h"

struct socket *sock;

static int k_sendmsg(struct socket *sock, void * buff, size_t len,
                     unsigned flags, struct sockaddr *addr, int addr_len)
{
        struct kvec vec;
        struct msghdr msg;

        vec.iov_base = buff;
        vec.iov_len = len;

        memset(&msg, 0x00, sizeof(msg));
        /* msg.msg_name = addr;  */
        /* msg.msg_namelen = addr_len;  */
        /* msg.msg_flags = flags | MSG_DONTWAIT;  */

        return kernel_sendmsg(sock, &msg, &vec, 1, len);
}

static void send_by_sock()
{
        struct sockaddr_in addr;
        u8 buf[15] = {"hello world"};
        int ret;

        sock_create_kern(PF_INET, SOCK_DGRAM, 0, &sock);

        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(319);
        addr.sin_addr.s_addr = in_aton("192.168.1.36");
       
        kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
       
        ret = k_sendmsg(sock, buf, sizeof(buf), 0, (struct sockaddr *) &addr, sizeof(addr));
        if (ret) {
                printk("kernel_msg: %d\n", ret);
        }
}

static void sock_init()
{
        struct ifreq ifr;
       
        sock_create_kern(PF_INET, SOCK_DGRAM, 0, &sock);
        strcpy(ifr.ifr_ifrn.ifrn_name, IF_NAME);
        kernel_sock_ioctl(sock, SIOCSIFNAME, (unsigned long) &ifr);
}

static void send_by_skb()
{
        struct net_device *netdev;
        struct net *net;
        struct sk_buff *skb;
        struct ethhdr *eth_header;
        struct iphdr *ip_header;
        struct udphdr *udp_header;
        __be32 dip = in_aton(DIP);
        __be32 sip = in_aton(SIP);
        u8 buf[16] = {"hello world"};
        u16 data_len = sizeof(buf);
        u16 expand_len = 16;        /* for skb align */
        u8 *pdata = NULL;
        u32 skb_len;
        u8 dst_mac[ETH_ALEN] = {DST_MAC_00, DST_MAC_01, DST_MAC_02, DST_MAC_03, DST_MAC_04, DST_MAC_05}; /* dst MAC */
        u8 src_mac[ETH_ALEN] = {SRC_MAC_00, SRC_MAC_01, SRC_MAC_02, SRC_MAC_03, SRC_MAC_04, SRC_MAC_05}; /* src MAC */


        /* construct skb */
        sock_init();
        net = sock_net((const struct sock *) sock->sk);
        netdev = dev_get_by_name(net, IF_NAME);
       
        skb_len = LL_RESERVED_SPACE(netdev) + sizeof(struct iphdr) + sizeof(struct udphdr) + data_len + expand_len;
        printk("iphdr: %d\n", sizeof(struct iphdr));
        printk("udphdr: %d\n", sizeof(struct udphdr));
        printk("data_len: %d\n", data_len);
        printk("skb_len: %d\n", skb_len);
       
        skb = dev_alloc_skb(skb_len);
        if (!skb) {
                return;
        }

        skb_reserve(skb, LL_RESERVED_SPACE(netdev));
        skb->dev = netdev;
        skb->pkt_type = PACKET_OTHERHOST;
        skb->protocol = htons(ETH_P_IP);
        skb->ip_summed = CHECKSUM_NONE;
        skb->priority = 0;

       
        /* construct ethernet header in skb */
        eth_header = (struct ethhdr *) skb_put(skb, sizeof(struct ethhdr));
        memcpy(eth_header->h_dest, dst_mac, ETH_ALEN);
        memcpy(eth_header->h_source, src_mac, ETH_ALEN);
        eth_header->h_proto = htons(ETH_P_IP);

        /* construct ip header in skb */
        skb_set_network_header(skb, 0);
        skb_put(skb, sizeof(struct iphdr));
        ip_header = ip_hdr(skb);
        ip_header->version = 4;
        ip_header->ihl = sizeof(struct iphdr) >> 2;
        ip_header->frag_off = 0;
        ip_header->protocol = IPPROTO_UDP;
        ip_header->tos = 0;
        ip_header->daddr = dip;
        ip_header->saddr = sip;
        ip_header->ttl = 0x40;
        ip_header->tot_len = htons(skb->len);
        ip_header->check = 0;
       

        /* construct udp header in skb */
        skb_set_transport_header(skb, sizeof(struct iphdr));
        skb_put(skb, sizeof(struct udphdr));
        udp_header = udp_hdr(skb);
        udp_header->source = htons(SPORT);
        udp_header->dest = htons(DPORT);


        /* insert data in skb */
        pdata = skb_put(skb, data_len);
        if (pdata) {
                memcpy(pdata, buf, data_len);
        }

        /* caculate checksum */
        udp_header->check = csum_tcpudp_magic(sip, dip, skb->len - ip_header->ihl * 4, IPPROTO_UDP, skb->csum);
        skb->csum = skb_checksum(skb, ip_header->ihl * 4, skb->len - ip_header->ihl * 4, 0);


        /* send packet */
        if (dev_queue_xmit(skb) < 0) {
                dev_put(netdev);
                kfree_skb(skb);
                printk("send packet by skb failed.\n");
                return;
        }
        printk("send packet by skb success.\n");
}

static int __init testmod_init(void)
{

        /* send_by_sock(); */
        send_by_skb();
       
       
        printk("testmod kernel module load!\n");

        return 0;
}

static void __exit testmod_exit(void)
{
        sock_release(sock);
       
        printk("testmod kernel module removed!\n");
}

module_init(testmod_init);
module_exit(testmod_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("lion3875 <
>");
MODULE_DESCRIPTION("A packet generation & send kernel module");

(2.67 KB)
阅读(2374) | 评论(0) | 转发(1) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~