Linux下的C / C ++数据包嗅探器

时间:2014-03-05 18:59:22

标签: c++ c linux sockets raw-sockets

我尝试在linux下使用原始套接字捕获网络pket 这有时会奏效。我似乎可以捕捉到一些对话,但不是全部。

我创建了一个套接字:

sock = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));  

然后我将它绑定到eth0:

struct sockaddr_ll sll;
struct ifreq ifr;

memset( &sll, 0, sizeof( sll));
memset( &ifr, 0, sizeof( ifr));

strcpy( ifr.ifr_name, "eth0");

if(( ioctl( sock, SIOCGIFINDEX, &ifr))==-1)
{
   printf( "error\n");
   return(-1);
}
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons( ETH_P_ALL);

bind( sock, (struct sockaddr*)&sll, sizeof( sll));

然后我尝试接收:

int packetsize = 65535;
char packet[packetsize];

struct ether_header *eth = (struct ether_header *) packet;
struct iphdr *ip = (struct iphdr *) (packet + sizeof(struct ether_header));

struct tcphdr *tcp = (struct tcphdr*) (packet+sizeof( struct ether_header)+sizeof( struct iphdr));
struct udphdr *udp = (struct udphdr*) (packet+sizeof( struct ether_header)+sizeof( struct iphdr));



int k;

while(1)
{
    k = read( sock, packet, sizeof( packet));

    if( k>0)
    {
        if( ntohs( eth-> ether_type) == 0x0800)
        {       
            inet_ntop( AF_INET, &ip->saddr, source, 16);
            inet_ntop( AF_INET, &ip->daddr, dest, 16);

            switch (ip->protocol)
            {
            case 6://TCP
                printf( "TCP: %s:%d -> %s:%d\n", source, ntohs( tcp->source), dest, ntohs( tcp->dest));
                break;
            case 17://UDP
                printf( "UDP: %s:%d -> %s:%d\n", source, ntohs( udp->source), dest, ntohs( udp->dest));
                break;
            default:
                break;
            }//switch           
        }// if 0x800    
    }//if( k>0)
}//while

我可以捕获网络中的一些数据包,但不是全部。 我似乎错过了双方之间的整个对话。

有没有人有想法,我做错了什么?

提前致谢

德克

2 个答案:

答案 0 :(得分:4)

除非这是某种家庭作业或受虐狂运动,否则我强烈建议您使用libpcap,这将提供一种可移植的方法来解决已被测试死亡的问题。 libpcaptcpdumpwireshark在幕后使用的内容。

答案 1 :(得分:2)

如果“双方之间的整个对话”是指运行代码的主机以外的主机,则需要将接口设置为混杂模式。

说到libpcaplibpcap来源IFF_PROMISC是了解如何启用混杂模式的好地方。搜索PACKET_MR_PROMISC(旧内核)和{{1}}(新发布者/更复杂的方式)。