2016-07-08 156 views
1

我使用原始套接字寫了一個簡單的數據包接收器,我得到奇怪的輸出,FE:原始套接字數據包接收器,奇怪的輸出

Received packet: size: 124, type: PACKET_HOST (0) 
Sender info: Name: n003-000-000-000.static.ge.com, IP: 3.0.0.0 
Data: 
74 2f 68 3c d1 9f 00 37 b7 d1 5a a7 08 00 45 00 00 6e 00 00 40 
00 40 11 b6 e9 c0 a8 01 01 c0 a8 01 44 00 35 94 08 00 5a 3b aa 
e1 78 81 80 00 01 00 01 00 00 00 00 01 30 01 30 01 30 01 33 07 
69 6e 2d 61 64 64 72 04 61 72 70 61 00 00 0c 00 01 c0 0c 00 0c 
00 01 00 00 65 95 00 20 10 6e 30 30 33 2d 30 30 30 2d 30 30 30 
2d 30 30 30 06 73 74 61 74 69 63 02 67 65 03 63 6f 6d 00 

當我瀏覽互聯網,數據包越大,但主機名稱和地址保持不變或幾乎相同。

有人能幫我找出問題嗎?

下面的代碼:

#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <errno.h> 
#include <unistd.h> 
#include <net/if.h> 
#include <sys/ioctl.h> 
#include <linux/if_ether.h> 
#include <netdb.h> 
#include <linux/if_packet.h> 
#include <netinet/ether.h> 

#define PACKET_SIZE 1 << 16 

void usage(); 
void packetTypeToStr(int type, char *str); 

int main(int argc, char **argv) { 
    const char *iface_name; 
    if (argc == 2) { 
     iface_name = argv[1]; 
    } else if (argc > 2) { 
     usage(); 
     return 1; 
    } else { 
     iface_name = "wlan0"; 
    } 

    // Opening socket in raw mode 
    int socketFileDesc = 0; 
    if ((socketFileDesc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) { 
     perror("socket"); 
     return errno; 
    } 
    printf("Opened raw socket\n"); 

    // Acquiring the index of the interface 
    struct ifreq iface; 
    memset(&iface, 0, sizeof(struct ifreq)); 
    strncpy(iface.ifr_name, iface_name, strlen(iface_name) + 1); 
    if (ioctl(socketFileDesc, SIOCGIFINDEX, &iface) < 0) { 
     perror("SIOCGIFINDEX"); 
     usage(); 
     close(socketFileDesc); 
     return errno; 
    } 
    int index = iface.ifr_ifindex; 
    printf("Index of the interface %s: %d\n", iface_name, index); 

    // Acquiring the mac address of the interface 
    struct ifreq iface_mac; 
    memset(&iface_mac, 0, sizeof(struct ifreq)); 
    strncpy(iface_mac.ifr_name, iface_name, strlen(iface_name) + 1); 
    if (ioctl(socketFileDesc, SIOCGIFHWADDR, &iface_mac) < 0) { 
     perror("SIOCGIFHWADDR"); 
     usage(); 
     close(socketFileDesc); 
     return errno; 
    } 
    printf("MAC address of the interface %s: %s\n", iface_name, ether_ntoa((struct ether_addr*)iface_mac.ifr_hwaddr.sa_data)); 


    // Setting interface in promiscuous mode 
    struct ifreq iface_options; 
    memset(&iface_options, 0, sizeof(struct ifreq)); 
    strncpy(iface_options.ifr_name, iface_name, strlen(iface_name) + 1); 
    if (ioctl(socketFileDesc, SIOCGIFFLAGS, &iface_options) < 0) { 
     perror("SIOCGIFFLAGS"); 
     close(socketFileDesc); 
     return errno; 
    } 
    iface_options.ifr_flags |= IFF_PROMISC; 
    if (ioctl(socketFileDesc, SIOCSIFFLAGS, &iface_options) < 0) { 
     perror("SIOCGIFFLAGS"); 
     close(socketFileDesc); 
     return errno; 
    } 
    printf("Interface %s set in promiscuous mode\n", iface_name); 

    // Binding socket to the interface 
    struct sockaddr_ll socketAddress; 
    memset(&socketAddress, 0, sizeof(socketAddress)); 
    socketAddress.sll_family = AF_PACKET; 
    socketAddress.sll_protocol = htons(ETH_P_ALL); 
    socketAddress.sll_ifindex = index; 
    if (bind(socketFileDesc, (struct sockaddr *) &socketAddress, sizeof(socketAddress)) < 0) { 
     perror("bind"); 
     close(socketFileDesc); 
     return errno; 
    } 
    printf("Socket bound to the interface: %s\nWaiting for packets...\n", iface_name); 

    // Receiving packets in a loop 
    while (1) { 
     ssize_t n = 0; 
     uint8_t packet[PACKET_SIZE]; 
     bzero(packet, sizeof(packet)); 
     struct sockaddr_in address; 
     socklen_t length = sizeof(address); 

     if ((n = recvfrom(socketFileDesc, packet, sizeof(packet), 0, (struct sockaddr *) &address, &length)) < 0) { 
      perror("recvfrom"); 
      close(socketFileDesc); 
      return errno; 
     } 
     // Null-terminated data 
     if (n > 0) 
      packet[n - 1] = '\0'; 
     else 
      continue; 

     // IP address 
     char ip[INET_ADDRSTRLEN]; 
     inet_ntop(AF_INET, &(address.sin_addr), ip, length); 

     // Host name 
     struct hostent *host = gethostbyaddr(&(address.sin_addr), length, AF_INET); 
     if (host == NULL) { 
      herror("gethostbyaddr"); 
      return h_errno; 
     } 
     const char *hostName = host->h_name; 

     // Packet type 
     char packetType[BUFSIZ]; 
     int type = ((struct sockaddr_ll *) &address)->sll_pkttype; 
     packetTypeToStr(type, packetType); 

     // Printing info and data 
     printf("\n\nReceived packet: size: %li, type: %s\n" 
         "Sender info: Name: %s, IP: %s\n", 
       n, packetType, hostName, ip); 
     printf("Data:\n"); 
     int i = 0; 
     for (; i < n; ++i) 
      printf("%02x ", packet[i]); 
    } 
    return 0; 
} 

回答

1

既然您收到原始數據包recvfrom()因爲一般的數據可能不是一個網絡數據包不能返回的IP地址。例如,它可能只是一個任意的以太網數據包,它是從某個沒有TCP/IP協議棧的設備發出的。可能recvfrom()將sockaddr指針視爲struct sockaddr_ll *並返回物理層地址。

您可以嘗試通過解析收到的數據包來獲取正確的IP地址。如果它真的是IP數據包 - 它將包含所有標題,包含源地址和目標地址。

相關問題