2015-10-22 4 views
1

Почему recvfrom создает дополнительный IP-заголовок?Зачем создавать дополнительный IP-заголовок?

Я посылаю:

------------- 
- IP header - 
------------- 
- Data - 
------------- 

Но когда я пытаюсь получить данные, похоже, есть код

------------- 
- IP header - 
------------- 
- IP header - 
-------------  
- Data - 
------------- 

Клиент: код

#include <sys/socket.h> 
#include <netinet/in.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h> 
#include <netinet/ip.h> 

#define DEBUG 1 


int main(void) { 

    // Create File descrptor for socket 
    int socket_fd; 
    if ((socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_IPV6)) < 0) { 
     perror("ERROR Socket"); 
     exit(2); 
    } 

    char *srcIP = "127.0.0.1"; 
    char *dstIP = "127.0.0.1"; 

    // Create address structure 
    struct sockaddr_in daddr; 
    daddr.sin_family = AF_INET; 
    daddr.sin_port = 0; // Raw sockets can't use ports 
    inet_pton(AF_INET, "127.0.0.1", &daddr.sin_addr); 
    memset(daddr.sin_zero, 0, sizeof(daddr.sin_zero)); 

    // Create a Packet 
    char packet[50]; 
    memset(packet, 0, sizeof(packet)); 

    // Structure packet 
    struct iphdr *ip_header = (struct iphdr *) packet; 
    // Data to be appended at the end of the ip header 
    char *data = (char *) (packet + (sizeof(struct iphdr))); 
    ip_header->version = 4; // IPv4 
    ip_header->tos = 0; // Type of service 
    ip_header->ihl = 5; // 5 x 32-bit words 
// ip_header->tot_len = htons(sizeof(struct iphdr) + strlen(data)); // Total IP packet length 
    ip_header->tot_len = sizeof(packet); // Total IP packet length 
    ip_header->protocol = IPPROTO_IPV6; // 6in4 protocol 
    ip_header->frag_off = 0x00; //16 bit field = [0:2] flags + [3:15] offset = 0x0 
    ip_header->ttl = 0xFF; // Max number of hops 16bit 
// ip_header->id = htons(54321); // 0x00; //16 bit id 
    ip_header->check = 0; //16 bit checksum of IP header. Can't calculate at this point 
    ip_header->saddr = inet_addr(srcIP); 
    ip_header->daddr = inet_addr(dstIP); 
    data[0] = 'T'; 
    data[1] = 'E'; 
    data[2] = 'S'; 
    data[3] = 'T'; 
    data[4] = '7'; 
    data[5] = '\0'; 

// ip_header->check = csum((unsigned short *) packet, ip_header->tot_len); 
#if DEBUG 
    printf("\nIP header checksum: %d\n", ip_header->check); 
#endif 

    while (1) { 
     sleep(1); 
     if (sendto(socket_fd, (char *) packet, sizeof(packet), 0, 
        (struct sockaddr *) &daddr, (socklen_t) sizeof(daddr)) < 0) 
      perror("Packet send error"); 
    } 

    return 0; 
} 

Сервер:

/*** IPPROTO_RAW receiver ***/ 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/ip.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
{ 
    int socket_fd; 
    struct sockaddr_in saddr; 
    char packet[50]; 

    if ((socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_IPV6)) < 0) { 
     perror("socket_fd"); 
     exit(EXIT_FAILURE); 
    } 

    memset(packet, 0, sizeof(packet)); 
    socklen_t len = (socklen_t) sizeof(saddr); 

    while(1) { 
     if (recvfrom(socket_fd, packet, sizeof(packet), 0, 
        (struct sockaddr *)&saddr, &len) < 0) 
      perror("recvfrom"); 

     int i = sizeof(struct iphdr); ////// WHY IS DATA PAYLOAD ON packet[sizeof(struct iphdr) * 2] 
     while (i < sizeof(packet)) { 
      fprintf(stderr, "%c", packet[i]); 
      i++; 
     } 
     printf("\n"); 
    } 
    exit(EXIT_SUCCESS); 
} 

ответ

0

В вашем отправителе вам необходимо установить опцию сокета IP_HDRINCL. Это говорит API, что вы вручную поставляете IP-заголовок. Поскольку вы не устанавливаете этот параметр, вы фактически ставите свою собственную копию IP-заголовка после того, как добавляет система.

+0

Большое спасибо – camabeh

0

Параметр сокета IP_HDRINCL обычно неявно устанавливается только в случае использования IPPROTO_RAW. Если вы не используете IPPROTO_RAW, заголовок будет сгенерирован, так как IP_HDRINCL не будет установлен неявно.

См. man7.org/linux/man-pages/man7/raw.7.html.

Смежные вопросы