私は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をとります。
ネットワークスタックがコードを変更しないようにするにはどうすればよいですか? 私は間違ったアプローチをしていますか?これはどうやってできますか?