2009-11-24 122 views
3

在使用C的unix上,我的客戶端以超級用戶模式在端口68上偵聽。在發送DHCP發現消息後,當我嘗試接收時,它在recvfrom中阻塞意味着沒有收到消息,或者它是否像系統有一個進程(DHCP客戶端)正在偵聽收到該消息的同一端口68並且我的進程不能接收消息。問題是什麼?實現DHCP客戶端

我已經設置了套接字選項SO_REUSEADDR和SO_BROADCAST。我發送給端口67

struct dhcpmessage 
{ 
    uint8_t op; 
    uint8_t htype; 
    uint8_t hlen; 
    uint8_t hops; 
    uint32_t xid; 
    uint16_t secs; 
    uint16_t flags; 
    uint32_t ciaddr; 
    uint32_t yiaddr; 
    uint32_t siaddr; 
    uint32_t giaddr; 
    char chaddr[16]; 
    char sname[64]; 
    char file[128]; 
    char magic[4]; 
    char opt[3]; 
} __attribute__((__packed__)); 

#include<stdio.h> 
#include<ctype.h> 
#include<stdlib.h> 
#include<string.h> 
#include<unistd.h> 
#include<signal.h> 
#include<sys/wait.h> 
#include<sys/types.h> 
#include<sys/socket.h> 
#include<netinet/in.h> 
#include<arpa/inet.h> 
#include<errno.h> 
#include<sys/file.h> 
#include<sys/msg.h> 
#include<sys/ipc.h> 
#include<time.h> 
#include"defs.h" 
int main() { 
int sockfd,listenfd,connfd; 
const int on=1; 
struct sockaddr_in servaddr,cliaddr,rservaddr; 
if((sockfd=socket(AF_INET,SOCK_DGRAM,0)) < 0) 
    die("socket"); 
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) < 0) 
    die("setsockopt"); 

if(setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof(on)) < 0) 
    die("setsockopt"); 
bzero(&servaddr,sizeof(servaddr)); 
bzero(&cliaddr,sizeof(cliaddr)); 
cliaddr.sin_port = htons(68); 
cliaddr.sin_family = AF_INET; 
cliaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
if(bind(sockfd,(struct sockaddr*)&cliaddr,sizeof(cliaddr)) < 0) 
    die("bind"); 

servaddr.sin_port = htons(67); 
servaddr.sin_family = AF_INET; 
servaddr.sin_addr.s_addr = inet_addr("255.255.255.255"); 
struct dhcpmessage dhcpmsg; 
bzero(&dhcpmsg,sizeof(dhcpmsg)); 
dhcpmsg.op = 1; 
dhcpmsg.htype = 1; 
dhcpmsg.hlen = 6; 
dhcpmsg.hops = 0; 
dhcpmsg.xid = htonl(1000); 
dhcpmsg.secs = htons(0); 
dhcpmsg.flags = htons(0x8000); 
dhcpmsg.chaddr[0] = 0x00; 
dhcpmsg.chaddr[1] = 0x1A; 
dhcpmsg.chaddr[2] = 0x80; 
dhcpmsg.chaddr[3] = 0x80; 
dhcpmsg.chaddr[4] = 0x2C; 
dhcpmsg.chaddr[5] = 0xC3; 
dhcpmsg.magic[0]=99; 
dhcpmsg.magic[1]=130; 
dhcpmsg.magic[2]=83; 
dhcpmsg.magic[3]=99; 
dhcpmsg.opt[0]=53; 
dhcpmsg.opt[1]=1; 
dhcpmsg.opt[2]=1; 
if(sendto(sockfd,&dhcpmsg,sizeof(dhcpmsg),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0) 
    die("sendto"); 
struct dhcpmessage recvdhcpmsg; 
socklen_t rservlen = sizeof(rservaddr); 
if(recvfrom(sockfd,&recvdhcpmsg,sizeof(recvdhcpmsg),0,(struct sockaddr*)&rservaddr,&rservlen) < 0) 
    die("recvfrom"); 
char *str = (char*)&recvdhcpmsg; 
int i; 
for(i=0;i<sizeof(recvdhcpmsg);i++) 
    printf("%d_",str[i]); 
printf("\n"); 
return 0; 
} 
+0

爲什麼有人投票結束這個問題? – avd 2009-11-24 17:27:20

回答

5

需要注意的是,您沒有IP地址,您想獲得IP地址。 - 大多數操作系統不允許您在不帶IP地址的NIC上綁定/發送UDP消息。 DHCP客戶端通常使用原始套接字用於這一目的/並應設置src地址爲0.0.0.0)

這種原始套接字將得到所有的數據包,您的應用程序不會,如果有運行系統DHCP客戶端

+0

你的意思是說我在68端口上創建一個原始套接字綁定,然後系統會將接收到的數據放在我的原始套接字和系統的DHCP客戶端原始套接字上。你能給我一些代碼/片段給出一個關於如何去做這件事的想法嗎? – avd 2009-11-25 02:29:13

1

你可以看看源代碼,用於現有DHCP客戶端,並瞭解它是如何工作:

ftp://ftp.isc.org/isc/dhcp/

您可能還需要發佈相關的片段的源代碼,以便人們可以確切地看到你是如何嘗試這樣做的。

+0

現在添加了源代碼 – avd 2009-11-24 17:31:20

1

我剛分叉dhclient爲dhcprobe。這是一個Linux的dhcp客戶端。

這是非常簡單的黑客攻擊,可能是您的項目的一個很好的起點。

+0

我看了一下dhcprobe的代碼,儘管我同意這是一個很好的起點,值得注意的是它基本上指向了服務器。所以它基本上不會涉及與廣播有關的協議的一些重要部分。 – 2017-05-29 13:55:10