【问题标题】:Implementing DHCP client实现 DHCP 客户端
【发布时间】:2010-12-19 23:34:09
【问题描述】:

在使用 C 的 unix 上,我的客户端正在以超级用户模式侦听端口 68。发送 DHCP 发现消息后,当我尝试接收时,它在 recvfrom 中阻塞,表示没有收到消息,或者系统有一个进程(DHCP 客户端)在同一端口 68 上侦听接收消息,这就是我的进程无法接收消息。有什么问题?

我已经设置了套接字选项 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;
}

【问题讨论】:

  • 为什么有人投票结束这个问题?

标签: c unix network-programming dhcp


【解决方案1】:

我刚刚将 dhclient 分叉为dhcprobe。它是 linux 的 dhcp 客户端。

破解起来非常简单,可能是您项目的一个很好的起点。

【讨论】:

  • 我查看了 dhcprobe 的代码,尽管我同意这是一个很好的起点,但值得注意的是它基本上指向一个服务器。所以它基本上不会打扰协议中与广播相关的一些重要部分。
【解决方案2】:

需要注意的是,您没有 IP 地址,您想获得一个。 - 大多数操作系统不允许您在没有 IP 地址的 NIC 上绑定/发送 UDP 消息。 dhcp 客户端通常为此目的使用原始套接字/并且应将 src 地址设置为 0.0.0.0)

这样的原始套接字将获取所有数据包,如果有系统 dhcp 客户端正在运行,您的应用程序将无法获取

【讨论】:

  • 你的意思是说我在 68 端口上进行了原始套接字绑定,然后系统会将接收到的数据放在我的原始套接字和系统的 dhcp 客户端原始套接字上。你能给我源代码/sn-p 让我知道如何处理这件事吗?
【解决方案3】:

您可以查看现有 DHCP 客户端的源代码并了解其工作原理:

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

您可能还想发布源代码的相关 sn-p,以便人们可以准确地看到您是如何尝试这样做的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2022-11-04
    • 1970-01-01
    • 2013-04-02
    • 2011-08-27
    • 2018-03-02
    相关资源
    最近更新 更多