Exemple #1
0
void test(const char* exp, const char* dev)
{
    int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
    if (sock<=0)
    {
        P("socket error");
        return;
    }
    //设置缓冲区
    #define PER_PACKET_SIZE 2048
    const int BUFFER_SIZE = 1024*1024*16; //16MB的缓冲区
    struct tpacket_req req;
    req.tp_block_size = 4096;
    req.tp_block_nr = BUFFER_SIZE/req.tp_block_size;
    req.tp_frame_size = PER_PACKET_SIZE;
    req.tp_frame_nr = BUFFER_SIZE/req.tp_frame_size;
    if (-1==setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(struct tpacket_req)))
    {
        perror("setsockopt");
        P("set PACKET_RX_RING error");
        close(sock);
        return;
    }
    //映射缓冲区
    char* pBuffer = (char*)mmap(0, BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, sock, 0);
    if (MAP_FAILED==pBuffer)
    {
        P("mmap error");
        close(sock);
        return;
    }
    //注意:一定要先映射后再绑定,否则会有问题
    // 问题的详细描述可参考:https://lists.linux-foundation.org/pipermail/bugme-new/2003-October/009110.html
    if (!SetPromisc(sock, dev))
    {
        P("SetPromisc [%s] error", dev);
        memset(&req, 0, sizeof(req));
        if (-1==setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)))
        {
            P("set map buffer to 0 error!");
        }
        close(sock);
        return;
    }
    if (!BindDevice(sock, dev))
    {
        P("bind [%s] error", dev);
        memset(&req, 0, sizeof(req));
        if (-1==setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)))
        {
            P("set map buffer to 0 error!");
        }
        close(sock);
        return;
    }
    //设置过滤器
    int nExpLen = strlen(exp);
    struct sock_fprog Filter;
    memset(&Filter, 0, sizeof(struct sock_fprog));
    if (nExpLen>0)
    {
        if (ExpressionToFilter(exp, &Filter))
        {
            if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER,
                    &Filter, sizeof(Filter))<0)
            {
                perror("setsockopt");
            }
        }
    }
    //
    struct pollfd pfd;
    int nIndex = 0;
    for (; ; )
    {
        for (; ; )
        {
            struct tpacket_hdr* pHead = (struct tpacket_hdr*)(pBuffer + nIndex*PER_PACKET_SIZE);
            if (pHead->tp_len<34 || pHead->tp_len>1614)
            {
                break;
            }
            PrintPacket((char*)pHead+pHead->tp_net);
            pHead->tp_len = 0;
            pHead->tp_status = TP_STATUS_KERNEL;
            //注意:pHead->tp_status这个变量并不能真正反应出包的处理状态,
            //在有的服务器上 TP_STATUS_USER(1)代表包可用, TP_STATUS_KERNEL(0)代表包不可用
            //但是在有的服务器上,这个标志变量无效
            //对于这个问题我还没找到原因
            nIndex++;
            if (nIndex>=BUFFER_SIZE/PER_PACKET_SIZE)
            {
                nIndex = 0;
            }
        }
        //
        pfd.fd = sock;
        pfd.events = POLLIN | POLLERR;
        pfd.revents = 0;
        switch (poll(&pfd, 1, 1000))
        {
        case -1:
            perror("poll");
            P("poll error");
            goto EndWhile;
            break;
        case 0:
            P("time out");
            continue;
            break;
        }
    }
EndWhile:
    if (-1==munmap(pBuffer, BUFFER_SIZE))
    {
        P("unmap error!");
    }
    memset(&req, 0, sizeof(req));
    if (-1==setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)))
    {
        P("set map buffer to 0 error!");
    }
    close(sock);
    sock = -1;
    //
    if (nExpLen>0)
    {
        FreeFilter(&Filter);
    }
}
Exemple #2
0
void StartSniffer(struct ISlist *iq)
{
    struct ifreq        newfl;
    struct iovec        packet_ring;
    struct tpacket_hdr  *packet_hdr;
    struct pollfd       pfd;
    register int        i;
    int                 size;

    iq -> fd = CreateSocket(PF_PACKET, SOCK_RAW, iq -> args -> protocol);
    newfl = GetIndex(iq -> fd, iq -> args -> device);
    //promiscous mode
    SetPromisc(iq -> fd, newfl);
    //calculate packet request for packet_ring
    iq -> packet_req = CalculatePacket();
    RequestPacketRing(iq -> fd, PACKET_RX_RING, *(iq -> packet_req));
    size = iq -> packet_req -> tp_block_size * iq -> packet_req -> tp_block_nr;
    iq -> ps_hdr_start =(unsigned char *) mmap(0, size,
                        PROT_READ|PROT_WRITE, MAP_SHARED, iq -> fd, 0);

    if ( iq -> ps_hdr_start == MAP_FAILED )
    {
        perror("mmap()");
        DestroySocket(iq -> fd);
        exit(ERROR);
    }
    pfd.fd = iq -> fd;
    pfd.revents = 0;
    pfd.events = POLLIN|POLLRDNORM|POLLERR;

    i = 0;
    while(i < iq->args->packet_num || iq->args->packet_num == 0)
    {
        packet_hdr = (struct tpacket_hdr *)
                     (iq -> ps_hdr_start+iq -> packet_req -> tp_frame_size*i);
        switch(packet_hdr -> tp_status)
        {
        case TP_STATUS_KERNEL:
            if ( poll(&pfd, 1, -1) < 0 )
            {
                perror("poll: ");
                exit(ERROR);
            }
            if ( packet_hdr -> tp_status != TP_STATUS_USER )
                packet_hdr -> tp_status = TP_STATUS_USER;
            break;
        case TP_STATUS_USER:
        case 5:
        case 9:
        case 13:
            packet_ring.iov_base = ((unsigned char *)packet_hdr+packet_hdr -> tp_mac);
            packet_ring.iov_len = iq -> packet_req -> tp_frame_size - packet_hdr -> tp_mac;
            iq -> args -> FunctionPtr(&packet_ring, iq -> args -> argv);
            packet_hdr -> tp_status = TP_STATUS_KERNEL;
            if ( iq -> args->packet_num >= iq -> packet_req -> tp_frame_nr )
                iq->args->packet_num--;
            i = (((unsigned)i) == (unsigned)iq -> packet_req ->
                 tp_frame_nr-1)? 0 : i+1;
            break;
        default:
            if ( poll(&pfd, 1, -1) < 0 )
            {
                perror("poll: ");
                exit(ERROR);
            }
            if ( iq -> args -> packet_num >= iq -> packet_req -> tp_frame_nr )
                iq->args->packet_num--;
            i = (((unsigned)i) == (unsigned)iq -> packet_req ->
                 tp_frame_nr-1)? 0 : i+1;
            break;
        }
    }
}