2012-10-24 2 views
7

In Linux, come è possibile trasmettere un pacchetto UDP utilizzando 0.0.0.0 come indirizzo di origine.Trasmissione di pacchetti UDP con indirizzo di origine 0.0.0.0

Ecco cosa ho provato finora.

#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 
#include <net/if.h> 
#include <string.h> 
#include <unistd.h> 
#include <assert.h> 
#include <arpa/inet.h> 
#include <sys/types.h> 
#include <sys/socket.h> 

int main(int argc, const char *argv[]) 
{ 
    struct sockaddr_in dst, src; 
    struct ifreq ifr; 
    int sock, tmp; 
    char payload[128]; 

    memset(payload, 0, 128); 

    memset(&dst, 0, sizeof(dst)); 
    dst.sin_family = AF_INET; 
    dst.sin_addr.s_addr = inet_addr("255.255.255.255"); 
    dst.sin_port = htons(67); 

    memset(&src,0,sizeof(src)); 
    src.sin_family = AF_INET; 
    src.sin_addr.s_addr = inet_addr("0.0.0.0"); 
    src.sin_port = htons(68); 

    sock = socket(AF_INET, SOCK_DGRAM, 0); 
    if (sock < 0) 
     perror("Failed to create socket"); 

    tmp = 1; 
    if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &tmp, sizeof(tmp)) < 0) 
     perror("SO_BROADCAST failed"); 

    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)) < 0) 
     perror("SO_REUSEADDR failed"); 

    if (setsockopt(sock, IPPROTO_IP, IP_FREEBIND, &tmp, sizeof(tmp)) < 0) 
     perror("IP_FREEBIND failed"); 

    memset(&ifr, 0, sizeof(ifr)); 
    strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name)); 

    if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) 
     perror("SO_BINDTODEVICE failed"); 

    if (bind(sock, (const struct sockaddr*)&src, sizeof(struct sockaddr_in)) < 0) 
     perror("bind failed"); 

    if (connect(sock, (const struct sockaddr*)&dst, sizeof(struct sockaddr_in)) < 0) 
     perror("bind failed"); 

    if (write(sock, payload, 128) < 0) 
     perror("Write failed"); 

    close(sock); 
    return 0; 
} 

Il problema è l'indirizzo sorgente è impostato solo per 0.0.0.0 se nessuna interfaccia ha un indirizzo IPv4. Se solo un'interfaccia ha un indirizzo IPv4, questo indirizzo viene utilizzato come indirizzo di origine.

Ho esaminato il codice sorgente di alcuni dei client DHCP esistenti e ho scoperto che utilizzano socket RAW e creano manualmente l'intestazione IP e UDP. Questa è una possibilità, ma vorrei evitare di farlo manualmente.

+0

Se nessuna interfaccia ha un indirizzo IPv4, non è possibile inviare il pacchetto a tutti ... – glglgl

+1

@glglgl come si invia un riscontro DHCP (che richiede esattamente questo)? – KillianDS

+1

Probabilmente usando le prese RAW ... – glglgl

risposta

4

Dovresti usare RAW SOCKET e costruire pacchetti con i tuoi sforzi.

A titolo di esempio si può prendere questo: https://github.com/fycth/DHCP-server-scanner/blob/master/src/dhcpd-detector.c

Questo è il mio progetto educativo. È piccolo e puoi vedere come esattamente questo compito è risolto lì.

+0

Questo è quello che ho cercato di evitare ... Ma immagino che non ci sia altro modo per farlo. – Allan

+3

Ci scusiamo per il disappunto ma sembra che non ci sia modo di evitare questa esperienza eccitante ... – fycth

0

Penso che se fosse possibile farlo tramite socket UDP, lo farebbero invece di costruirne uno manualmente. Quindi suppongo che non funzioni affatto ...