2012-10-24 90 views
7

在linux中,如何使用0.0.0.0作爲源地址傳輸UDP包。傳輸源地址爲0.0.0.0的UDP包

這是我到目前爲止嘗試過的。

#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; 
} 

問題是源地址只設置爲0.0.0.0如果沒有接口具有IPv4地址。如果只有一個接口具有IPv4地址,則將該地址用作源地址。

我查看了一些現有的DHCP客戶端的源代碼,發現他們使用RAW套接字並手動構建IP和UDP頭。這是可能的,但我想避免手動進行此操作。

+0

如果沒有接口具有IPv4地址,則根本無法發送數據包... – glglgl

+1

@glglgl那麼您將如何發送DHCP發現(那需要完全相同)? – KillianDS

+1

可能使用原始插座... – glglgl

回答

4

你應該使用RAW SOCKET和自己的努力構建數據包。

舉個例子,你可以採取這樣的:https://github.com/fycth/DHCP-server-scanner/blob/master/src/dhcpd-detector.c

這是我的教育項目。它很小,你可以看看這個任務如何在那裏解決。

+0

這是我試圖避免的......但我想沒有其他方式做到這一點。 – Allan

+3

對不起,令人失望,但似乎沒有辦法避免這個令人興奮的經歷... – fycth

0

我想如果有可能通過UDP套接字來做,他們會做,而不是手動建立一個。所以我認爲它根本不起作用...