2016-09-05 26 views
2

私はRawソケットを使用して、Type UDPのIPパケットを送信しています。ネットワークスタックがIPヘッダーを変更しないようにするにはどうすればよいですか?

私の目標は、DHCP要求を送信することです。 RFCは、まだIPを持っていないクライアントの送信元IPアドレスを0に設定する必要があることを定義しています。 これは、IPヘッダー、UDPヘッダー、およびペイロード。 私は、このように、IPヘッダを修正し、0にソースIPアドレスを設定します。

//Now, let's copy the structs inside our packet struct we want to return 
struct packet *packet = (struct packet *)malloc(sizeof(struct packet)); 

memcpy(&packet->iph, &ip, sizeof(struct iphdr)); 
memcpy(&packet->udph, &udp, sizeof(struct udphdr)); 
memcpy(&packet->dhcpm, dhcp, sizeof(struct dhcp_message)); 
:このように、

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 = 255;         // 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 = htonl(INADDR_BROADCAST);   // we have to do a broadcast 
ip.id = 489;         // The packets ID 
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 

    // Secondly, create the udp header and fill out the information 
struct udphdr udp; 

udp.source = htons(DHCP_CLIENT_PORT);    // We are a client sending a request 
udp.dest = htons(DHCP_SERVER_PORT);    // We want to send the packet to a DHCP server 
udp.check = 0;         // zero the checksum until it's calculated 

// The total length of the UDP packet is the size of the UDP header combined with the DHCP message struct 
udp.len = htons(sizeof(struct udphdr) + sizeof(struct dhcp_message)); 

私はその後、私のDHCPのものを行うと、1つのバッファに構造体のすべてをコピーします

そして、私のコードの最後の部分は、私が作成したパケットを送信します。

struct packet *pckt = minidhc_make_packet(DHCP_DISCOVER, "enp7s0"); 

// Create socket 
int sockd; 
if((sockd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) { 
    perror("Failed to create socket"); 
    exit(1); 
} 

// Enable broadcasting 
int broadcast = 1; 
if(setsockopt(sockd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast))) { 
    perror("Failed to enable broadcasting on 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); 
} 


union sockunion { 
    struct sockaddr sa; 
    struct sockaddr_in sin; 
}; 

union sockunion su; 

su.sin.sin_family = AF_INET; 
su.sin.sin_port = DHCP_SERVER_PORT; 
su.sin.sin_addr.s_addr = htonl(INADDR_BROADCAST); 

// Send to 
int bytes; 
if((bytes = sendto(sockd, (void *)pckt, sizeof(struct packet), 0, &su.sa, sizeof(struct sockaddr_in))) == -1) { 
    perror("Failed to send DHCP request"); 
    exit(1); 
} 

printf("Bytes sent: %d\n", bytes); 

printf("Sent raw packet\n"); 

free(pckt); 

私の問題:Wiresharkを使ってネットワークトラフィックを盗聴するとき、私は私が送信され、放送をキャプチャすることができます。これは有効なDHCP要求です。しかし、ソースIPアドレスは私の実際のIPであり、0.0.0.0ではありません。

私は、それは完全に正常に動作します(例えば192.168.192.1など)いくつかの任意の1にソースIPアドレスを設定しようとしています。 私の前提は、ネットワークスタックがIPヘッダーをチェックし、送信元IPアドレスの値が0であることを確認してから、実際のIPを追加することです。それはちょうど仮定ですが、私はそれが事実であるかどうか分かりません。

また、私は、パラメータとしてのsendtoを与える宛先IPアドレスとは異なるものにIPヘッダ内の宛先IPアドレスを設定しようとしている、それは、IPヘッダのIP desstinationをとります。

ネットワークスタックがコードを変更しないようにするにはどうすればよいですか? 私は間違ったアプローチをしていますか?これはどうやってできますか?

答えて

0

私の前提は、ネットワークスタックがIPヘッダーをチェックし、送信元IPアドレスの値が0であることを確認してから、実際のIPを追加することです。

あなたの仮定が正しいです。 raw(7)を参照してください:

送信元アドレスは、それが0.0.0.0に等しい場合、カーネルによって自動的に入力されます(INADDR_ANYと同じである)とソケットオプションIP_HDRINCLが有効になっています。

私はあなたのカーネルを変更して再コンパイルする必要がない限り、この動作を変更する方法はありませんだと思います。しかし、あなた自身のイーサネットフレームを作成するか、少なくとも有効なイーサネットヘッダを追加することで、この問題を解決できるはずです。

あなたがそれをしようとする前に、あなたが対応するpacket(7) manページをお読みください。概要セクションは何が必要を示しています。ご利用の場合を考慮し

#include <sys/socket.h> 
#include <linux/if_packet.h> 
#include <net/ethernet.h> /* the L2 protocols */ 

packet_socket = socket(AF_PACKET, int socket_type, int protocol); 

、あなたが最も可能性が高いためhtons(ETH_P_ALL)を挿入します。それは始めるには十分な情報でなければなりません。私は、フレームを適切に構築して送信する方法について、たくさんのコード例をインターネット上で見つけることができると確信しています。同じレベルで起こっているので、ARPを扱うソースコードもおそらく参考になるでしょう。

これが役に立ちます。

関連する問題