2016-09-13 14 views
1

Я хочу отправить необработанные IP-пакеты, которые отлично работают, за исключением одного поля в заголовке IP.Программирование сокета C: Установить идентификатор IP-заголовка в 0?

Мне нужно установить IP-идентификатор 0. Я пробовал следующим образом:

struct iphdr ip; 

ip.version = 4;        // Ipv4 
ip.frag_off = 0;        // IP Fragmentation 
ip.tos  = 0;        // Type of Service - We don't need this 
ip.ttl = 64;         // Maxmimum value 
ip.protocol = IPPROTO_UDP;     // DHCP uses UDP 
ip.check = 0;         // The checksum needs to be 0 before being calculated 

// We don't yet have an IP Address 
if((ip.saddr = inet_addr("0.0.0.0")) == -1) { 
    perror("Failed to convert IP address"); 
    exit(1); 
} 

ip.daddr = inet_addr("255.255.255.255");  // we have to do a broadcast 
ip.id = 0;         // 
ip.ihl = 5;         // Header length - 5 means no additional options are being sent in the IP header 
ip.tot_len = sizeof(struct packet);   // The total length of the Packet 

Я тогда создать RAW_SOCKET с набором опций IP_HDRINCL:

 if ((sockd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) { 
     perror("Failed to create socket"); 
     exit(1); 
    } 
int hdrincl = 1; 
if (setsockopt(sockd, IPPROTO_IP, IP_HDRINCL, &hdrincl, sizeof(hdrincl)) == -1) { 
    perror("Failed to set IP_HDRINCL"); 
    exit(1); 
} 

Я тогда создать буфер, содержащий мой IP-заголовок, UDP-заголовок и полезную нагрузку и отправьте его.

Однако сетевой стек продолжает менять свой идентификатор в IP-заголовке. Мне нужно включить заголовок IP, но мне также нужно отключить фрагментацию и/или установить IP-идентификатор на 0. Как мне это достичь?

EDIT: Я на Linux

+0

Вы находитесь на linux или windows? Если вы находитесь на окнах, сокеты - это не способ сделать это; попробуйте libpcap. –

+1

Если вы проверите man-страницу 'man 7 raw', вы увидите, что когда' id' является '0', он будет автоматически заполнен, поэтому объясняется, почему вы не можете использовать id 0, однако у меня нет решение для фактического использования id 0. – Jite

ответ

3

В Linux, вы можете использовать AF_PACKET с SOCK_DGRAM розетками вместо AF_INET с SOCK_RAW и заполнить sockaddr_ll.

Нечто подобное:

socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)) 

Однако, чтобы сделать вам программу работы с ОС Windows тоже, вы должны использовать libpcap.

Имейте в виду, что вы должны решить физический адрес адресата самостоятельно (в Linux, вы можете попробовать использовать интерфейс rtnetlink).

Подробнее см. На packet(7) и rtnetlink(7). Если ваш проект является Open Source, вы можете использовать my old project, который выполняет некоторые из этих действий (для получения дополнительной информации свяжитесь со мной).