2009-11-24 5 views
3

C를 사용하는 유닉스에서 내 클라이언트는 수퍼 유저 모드로 포트 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

답변

5

주의 할 점은 IP 주소가 없으므로 IP 주소를 얻으려고한다는 것입니다. - 대부분의 OS는 IP 주소가없는 NIC에서 UDP 메시지를 바인드/전송할 수 없습니다. DHCP 클라이언트는 일반적으로 그 목적을 위해 원시 소켓을 사용/및 0.0.0.0에 SRC 주소)를 설정해야합니다

이러한 원시 소켓은 모든 패킷을 얻을 것이다, 당신의 응용 프로그램을 실행하는 시스템의 DHCP 클라이언트있다하지 않을 경우

+0

u는 68 포트에서 raw 소켓 바인드를 한 다음 시스템이 원시 소켓과 시스템의 dhcp 클라이언트 원시 소켓에 수신 된 데이터를 넣을 것을 의미합니다. 이 일에 대해 어떻게 생각하는지 아이디어를주는 souce code/snippet을 줄 수 있습니까? – avd

1

당신은 기존 DHCP 클라이언트의 소스 코드를보고 어떻게 작동하는지 배울 수 :

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

당신은 또한 관련 조각을 게시 할 수 있습니다 귀하의 소스 코드에 대해 사람들이 정확히 어떻게하는지 알 수 있습니다.

+0

소스 코드를 지금 추가했습니다. – avd

1

방금 ​​dhcprobe으로 dhclient를 포크했습니다. 이것은 리눅스 용 dhcp 클라이언트입니다.

해킹하는 것은 매우 간단하며 프로젝트의 좋은 출발점이 될 수 있습니다.

+0

dhcprobe의 코드를 살펴 보았습니다. 좋은 출발점이라는 데는 동의하지만, 기본적으로 서버를 가리키는 것이 중요합니다. 따라서 기본적으로 방송과 관련된 프로토콜의 중요한 일부는 신경 쓰지 않습니다. –

관련 문제