新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   >>中国XML论坛<<     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 讨论密码学、密码协议、入侵检测、访问控制等与安全理论研究有关的主题
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机理论与工程『 安全理论 』 → [原创]Winpcap学习第六天 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 10755 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [原创]Winpcap学习第六天 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     binaryluo 帅哥哟,离线,有人找我吗?
      
      
      威望:6
      等级:研二(Pi-Calculus看得一头雾水)(版主)
      文章:679
      积分:5543
      门派:IEEE.ORG.CN
      注册:2005/2/19

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给binaryluo发送一个短消息 把binaryluo加入好友 查看binaryluo的个人资料 搜索binaryluo在『 安全理论 』的所有贴子 引用回复这个贴子 回复这个贴子 查看binaryluo的博客楼主
    发贴心情 [原创]Winpcap学习第六天

    尽管Winpcap清楚地指出了它的目的是数据包的截获,但是它还提供了一些对于原始网络(raw networking)的有用特性。用户可以找到一组完整的发包(send packets)函数。需要注意的是,libpcap目前并没有提供任何的发包的方法。

    用pcap_sendpacket()发送单个数据包

        下面的代码片断表现了最简单的发送一个数据包的过程。打开适配器后,pcap_sendpacket()被用来发送一个手工的(hand

    -crafted)数据包。

        试验代码:

    #include <stdlib.h>
    #include <stdio.h>
    #include <pcap.h>
    #include <remote-ext.h>

    void main(int argc, char** argv){
    pcap_t* fp;
    char errbuf[PCAP_ERRBUF_SIZE];
    u_char packet[100];
    int i;

    /* Check the validity of the command line*/
    if (argc != 2)
    {
      printf("\tusage: %s interface (e.g. 'rpcap://eth0')", argv[0]);
      return;
    }

    /* Open the output device */
    if ((fp = pcap_open(argv[1],  /* name of the device */
          100,      /* portion of the packet to capture (only the first 100 bytes)*/
          PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
          1000,     /* read timeout */
          NULL,     /* authentication on the remote machine */
          errbuf    /* error buffer */
          )) == NULL)
    {
      fprintf(stderr, "\nUnable to open the adapter. %s is not supported by Winpcap\n", argv[1]);
      return;
    }

    /* Supposing to be on ethernet, set mac destinat to 1:1:1:1:1:1 */
    packet[0] = 1;
    packet[1] = 1;
    packet[2] = 1;
    packet[3] = 1;
    packet[4] = 1;
    packet[5] = 1;

    /* set mac source to 2:2:2:2:2:2 */
    packet[6] = 2;
    packet[7] = 2;
    packet[8] = 2;
    packet[9] = 2;
    packet[10] = 2;
    packet[11] = 2;

    /* Fill the rest of the packet */
    for (i = 12; i < 100; ++ i)
    {
      packet[i] = i % 256;
    }

    /* Send down the packet */
    if (pcap_sendpacket(fp, packet, 100 /* size */) != 0)
    {
      fprintf(stderr, "\nError sending the packet: \n", pcap_geterr(fp));
      return;
    }

    return;
    }

    函数1:

    int pcap_sendpacket(pcap_t*   p,

    u_char*   buf,

    int       size)

        发送一个原始数据包(raw packet)到网络上。p是用来发送数据包的那个接口,buf包含着要发送的数据包的数据(包括各种各样的协议头),size是buf所指的缓冲区的尺寸,也就是要发送的数据包的大小。MAC循环冗余码校验不必被包含,因为它很容易被计算出来并被网络接口驱动添加。如果数据包被成功发送,返回0;否则,返回-1。

    发送队列(Send queues)

          pcap_sendpacket()提供了一个简单快捷的发送单个数据包的方法,发送队列(send queues)提供了一个高级的,强大的,优化的发送一组数据包的机制。发送队列是一个用来保存将要发送到网络上的的众多数据包的容器。它有一个大小,描述了它所能容纳的最大字节数。

        通过指定发送队列的大小,pcap_sendqueue_alloc()函数创建一个发送队列。一旦发送队列被创建好,pcap_sendqueue_queue()可以把一个数据包添加到发送队列里。函数pcap_sendqueue_alloc()的参数必须与pcap_next_ex()和pcap_handler()的相同,因此,从一个文件捕获或读取数据包的时候,如何进行pcap_sendqueue_alloc()的参数传递是一个问题。

    试验代码:

    #include <stdlib.h>
    #include <stdio.h>

    #include <pcap.h>
    #include <remote-ext.h>

    void usage();

    void main(int argc, char **argv)
    {
        pcap_t *indesc,*outdesc;
        char errbuf[PCAP_ERRBUF_SIZE];
        char source[PCAP_BUF_SIZE];
        FILE *capfile;
        int caplen, sync;
        u_int res;
        pcap_send_queue *squeue;
        struct pcap_pkthdr *pktheader;
        u_char *pktdata;
        float cpu_time;
        u_int npacks = 0;
       
        /* Check the validity of the command line */
        if (argc <= 2 || argc >= 5)
        {
            usage();
            return;
        }
           
        /* Retrieve the length of the capture file */
        capfile=fopen(argv[1],"rb");
        if(!capfile){
            printf("Capture file not found!\n");
            return;
        }
       
        fseek(capfile , 0, SEEK_END);
        caplen= ftell(capfile)- sizeof(struct pcap_file_header);
        fclose(capfile);
               
        /* Chek if the timestamps must be respected */
        if(argc == 4 && argv[3][0] == 's')
            sync = TRUE;
        else
            sync = FALSE;

        /* Open the capture */
        /* Create the source string according to the new WinPcap syntax */
        if ( pcap_createsrcstr( source,         // variable that will keep the source string
                                PCAP_SRC_FILE,  // we want to open a file
                                NULL,           // remote host
                                NULL,           // port on the remote host
                                argv[1],        // name of the file we want to open
                                errbuf          // error buffer
                                ) != 0)
        {
            fprintf(stderr,"\nError creating a source string\n");
            return;
        }
       
        /* Open the capture file */
        if ( (indesc= pcap_open(source, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
        {
            fprintf(stderr,"\nUnable to open the file %s.\n", source);
            return;
        }

        /* Open the output adapter */
        if ( (outdesc= pcap_open(argv[2], 100, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
        {
            fprintf(stderr,"\nUnable to open adapter %s.\n", source);
            return;
        }

        /* Check the MAC type */
        if (pcap_datalink(indesc) != pcap_datalink(outdesc))
        {
            printf("Warning: the datalink of the capture differs from the one of the selected interface.\n");
            printf("Press a key to continue, or CTRL+C to stop.\n");
            getchar();
        }

        /* Allocate a send queue */
        squeue = pcap_sendqueue_alloc(caplen);

        /* Fill the queue with the packets from the file */
        while ((res = pcap_next_ex( indesc, &pktheader, &pktdata)) == 1)
        {
            if (pcap_sendqueue_queue(squeue, pktheader, pktdata) == -1)
            {
                printf("Warning: packet buffer too small, not all the packets will be sent.\n");
                break;
            }

            npacks++;
        }

        if (res == -1)
        {
            printf("Corrupted input file.\n");
            pcap_sendqueue_destroy(squeue);
            return;
        }

        /* Transmit the queue */
       
        cpu_time = (float)clock ();

        if ((res = pcap_sendqueue_transmit(outdesc, squeue, sync)) < squeue->len)
        {
            printf("An error occurred sending the packets: %s. Only %d bytes were sent\n", pcap_geterr(outdesc), res);
        }
       
        cpu_time = (clock() - cpu_time)/CLK_TCK;
       
        printf ("\n\nElapsed time: %5.3f\n", cpu_time);
        printf ("\nTotal packets generated = %d", npacks);
        printf ("\nAverage packets per second = %d", (int)((double)npacks/cpu_time));
        printf ("\n");

        /* free the send queue */
        pcap_sendqueue_destroy(squeue);

        /* Close the input file */
        pcap_close(indesc);

        /*
         * lose the output adapter
         * IMPORTANT: remember to close the adapter, otherwise there will be no guarantee that all the
         * packets will be sent!
         */
        pcap_close(outdesc);


        return;
    }


    void usage()
    {
       
        printf("\nSendcap, sends a libpcap/tcpdump capture file to the net. Copyright (C) 2002 Loris Degioanni.\n");
        printf("\nUsage:\n");
        printf("\t sendcap file_name adapter [s]\n");
        printf("\nParameters:\n");
        printf("\nfile_name: the name of the dump file that will be sent to the network\n");
        printf("\nadapter: the device to use. Use \"WinDump -D\" for a list of valid devices\n");
        printf("\ns: if present, forces the packets to be sent synchronously, i.e. respecting the timestamps in the dump file. This option will work only under Windows NTx.\n\n");

        exit(0);
    }

    函数1:

    pcap_send_queue* pcap_sendqueue_alloc(u_int memsize)

        为一个发送队列分配空间,即创建一个用来存储一组原始数据包(raw packet)的缓冲区,这些数据包将用pcap_sendqueue_transmit()提交到网络上。memsize是队列容纳的字节数,因此它决定了队列所能容纳的最大数据量。使用pcap_sendqueue_queue()可以在发送队列中插入数据包。

    函数2:

    int pcap_sendqueue_queue(pcap_send_queue*            queue,

    const struct pcap_pkthdr* pkt_header,

    const u_char*             pkt_data)

        添加一个数据包到发送队列中。queue指向发送队列的尾部;pkt_header指向一个pcap_pkthdr结构体,该结构体包含时间戳和数据包的长度;pkt_data指向存放数据包数据部分的缓冲区。

        为了提交一个发送队列,Winpcap提供了pcap_sendqueue_transmit()函数。

    函数3:

    u_int pcap_sendqueue_transmit(pcap_t*                 p,

    pcap_send_queue*      queue,

    int                   sync)

        该函数将队列里的内容提交到线路上。p是一个指向适配器的指针,数据包将在这个适配器上被发送;queue指向pcap_send_queue结构体,它包含着要发送的所有数据包;sync决定了发送操作是否被同步:如果它是非0(non-zero),发送数据包关系到时间戳,否则,他们将以最快的速度发送(即不考虑时间戳)。

        返回值是发送的字节数。如果它小于size参数,将发生一个错误。该错误可能是由于驱动/适配器(driver/adapter)问题或发送队列的不一致/伪造(inconsistent/bogus)引起。

    注意:

    l         使用该函数的效率比使用pcap_sendpacket()发送一系列数据包的效率高,因为数据包在核心态(kernel-level)被缓冲,所以降低了上下文的交换次数。因此,使用pcap_sendqueue_transmit()更好。

    l         当sync被设置为TRUE时,随着一个高精度的时间戳,数据包将在内核伴被同步。这就要求CPU的数量是不可忽略的,通常允许以一个微秒级的精度发送数据包(这依赖于机器性能计数器的准确度)。然而,用pcap_sendpacket()发送数据包不能达到这样一个精确度。

        如果第三个参数非0,发送将被同步(synchronized),即相关的时间戳将被注意。这个操作要求注意CPU的数量,因为使用“繁忙 等待(busy wait)”循环,同步发生在内核驱动。

        当不再需要一个队列时,可以用pcap_sendqueue_destroy()来删除之,这将释放与该发送队列相关的所有缓冲区。


       收藏   分享  
    顶(0)
      




    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2006/6/1 9:25:00
     
     001liujie 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:1
      积分:61
      门派:XML.ORG.CN
      注册:2006/8/25

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给001liujie发送一个短消息 把001liujie加入好友 查看001liujie的个人资料 搜索001liujie在『 安全理论 』的所有贴子 引用回复这个贴子 回复这个贴子 查看001liujie的博客2
    发贴心情 
    libpcap 0.9.1可以发包啦!
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/1/15 15:47:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 安全理论 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/23 1:58:11

    本主题贴数2,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms