2014-01-24 88 views
1

我想捕獲特定接口的數據包,而是從所有接口獲取數據包。我究竟做錯了什麼?在linux上嗅探以太網接口

bool Snooper::raw_init (const char *device) 
{ 

uid_t privid = geteuid(); 
int  retval; 
bool  retVal = false; 

do { 
    if ((retval = setuid(0)) != 0) { 
     perror("seteuid error"); 
     break; 
    } 

    cap_t caps = cap_get_proc(); 
    cap_value_t cap_list[2]; 
    cap_list[0] = CAP_NET_RAW; 
    cap_list[1] = CAP_SETUID; 
    if ((retval = cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET)) == -1) { 
     perror("cap_set_flag error"); 
     break; 
    } 
    if ((retval = cap_set_proc(caps)) == -1) { 
     perror("cap_set_proc error"); 
     break; 
    } 

    struct ifreq ifr; 
    memset(&ifr, 0, sizeof (struct ifreq)); 

    /* Open A Raw Socket */ 
    if ((m_sockfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL))) < 1) { 
     perror("Snooper::raw_init:socket Error"); 
     break; 
    } 

    /* Set the device to use */ 
    strncpy(ifr.ifr_name, device, strlen(device) + 1); 

    /* Get the current flags that the device might have */ 
    if (ioctl(m_sockfd, SIOCGIFFLAGS, &ifr) == -1) { 
     perror("Error: Could not retrieve the flags from the device.\n"); 
     break; 
    } 

    printf("The interface is ::: %s\n", device); 
    perror("Retrieved flags from interface successfully"); 

    /* Set the old flags plus the IFF_PROMISC flag */ 
    ifr.ifr_flags |= IFF_PROMISC; 
    if (ioctl(m_sockfd, SIOCSIFFLAGS, &ifr) == -1) { 
     perror("Error: Could not set flag IFF_PROMISC"); 
     break; 
    } 
    printf("Setting interface ::: %s ::: to promisc\n", device); 

    /* Configure the device */ 
    if (ioctl(m_sockfd, SIOCGIFINDEX, &ifr) < 0) { 
     perror("Error: Error getting the device index.\n"); 
     break; 
    } 
    retVal = true; 
} while(false); 

if ((retval = seteuid(privid)) != 0) { 
    perror("seteuid error"); 
} 
return retVal; 
} 

我首先驗證自從IFF_PROMISC需要它以後我可以申請到根。然後爲UDP流量創建套接字,爲設備預製IOCtl,然後爲PROMISC預處理IOCtl。

現在,我已經準備好了一個套接字,並在recv上循環,但是我也從其他接口獲取數據包。

+0

由於@Vlad拉扎連科現在它工作。我認爲這將是綁定,但是其他地方發現的其他例子都沒有綁定,因此它被省略了。至於其他人想要做同樣類型的任務。編譯後。 chown root exe,然後chmod a + s exe。儘管您必須擁有root權限才能執行任一操作。 –

回答

1

要從特定接口捕獲數據包,必須使用bind函數將套接字綁定到該接口。例如,您可以查看this answer

0

pcap方案也許能幫助您

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<pcap/pcap.h> 
#include<netinet/if_ether.h> 
#include<netinet/ip.h> 
#include<netinet/tcp.h> 

void process_packet(u_char *args, const struct pcap_pkthdr *header, 
           const u_char *buffer) 
{ 
// printf("In Process_Packet\n"); 
struct ethhdr *eth = (struct ethhdr *)(buffer); 

printf("%.2x: %.2x: %.2x: %.2x: %.2x: %.2x: %.2x:\n ", eth->h_dest[0], eth->h_dest[1], eth->h_dest[2], eth->h_dest[3], eth->h_dest[4], eth->h_dest[5], eth->h_dest[6]); 

printf("%x \n", htons(eth->h_proto)); 

if(htons(eth->h_proto)== ETHERTYPE_ARP) 
{ 
    printf("ARP PACKET\n"); 
} 

struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr)); 

int ipheader = iph-> ihl *4; 

printf("Source IP Address :%s\n ", inet_ntoa(iph->saddr)); 

printf("Destination IP Address :%s\n ", inet_ntoa(iph->daddr)); 
} 
int main() 
{ 
pcap_if_t *alldevspec,*devices; 
pcap_addr_t *a; 
pcap_t *handle; 
const char filter_exp[]="IP"; 
bpf_u_int32 netp; 
char errbuf[PCAP_ERRBUF_SIZE]; 
struct bpf_program fp; 
int ret=0, count =1, n=0; 
char devs[100][100],*devicename; 

ret = pcap_findalldevs(&alldevspec,errbuf); 

if(ret < 0) 
{ 
    printf("Error in finding the devices\n"); 
    return -1; 
} 

for(devices = alldevspec; devices!= NULL; devices = devices->next) 
{ 
    printf("%d %s-%s \n",count, devices->name,devices->description); 

    for(a=devices->addresses;a;a=a->next) 
    { 
     printf("family %d \n", (a->addr)->sa_family); 

     if(devices->name != NULL) 
     { 
      strcpy(devs[count], devices->name); 
     } 

     switch((a->addr)->sa_family) 
     { 
      case AF_INET: 
      printf("%s \n",inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr.s_addr)); 
      break; 

      case AF_INET6: 
      break; 
     } 
    } 
++count; 
} 

printf("Enter the device u want to select\n"); 
scanf("%d",&n); 
devicename = devs[n]; 

handle = pcap_open_live(devicename,65536,1,-1,errbuf); 

if(handle == NULL) 
{ 
    printf("Error in opening the device\n"); 
    return -1; 
} 

pcap_compile(handle,&fp, filter_exp,-1,netp); 
pcap_setfilter(handle, &fp); 
pcap_loop(handle,-1,process_packet,NULL); 

return 0; 
}