间隔1.5s发送一次DHCP DISCOVER报文
抓包发现我的路由器,如果没获取IP,会间隔1.5s发送一次DHCP DISCOVER报文,这个肯定是个BUG
正常的DHCP服务的工作过程如下:
如果在局域网中部署了DHCP服务器,并且客户端设置为自动获得IP地址。这样当DHCP客户端第一次登录网络的时候,也 就是客户端发现本机上没有任何IP数据设定,它会向网络发出一个DHCP discover封包。因为客户端还不知道自己属于哪一个网络,所以封包的来源地址会为 0.0.0.0,而目的地址则为255.255.255.255,然后再附上DHCP discover的信息,向网络进行广播。在windows的预设默认情况下,DHCP discover的等待时间预设为1秒,也就是当客户端将第一个DHCP discover封包送出去之后,在1秒之内没有得到响应的话,就会进行第二次DHCP discover广播。若一直得不到响应的情况下,客户端一共会有四次DHCP discover广播(包括第一次在内)。除了第一次会等待1秒之外,其余三次的等待时间分别是9、13、16秒。如果都没有得到DHCP服务器的响应, 客户端则会显示错误信息,宣告DHCP discover的失败。之后,基于使用者的选择,系统会继续在5分钟之后再重复一次DHCP discover的过程;当DHCP服务器收到DHCP客户机广播的DHCP discover信息后,它会向DHCP客户机发送DHCP offer信息,其中包括一个可租用的IP地址。一旦客户机收到DHCP offer信息,就将使用服务器所提供的IP地址。(http://blog.chinaunix.net/uid-14239467-id-93140.html)
那么如何解决呢?
刚开始以为控制DHCP就是在dhcp.c文件里面,但是printf打印却没有相关信息,后来找到了相关文件,是dhcp_port.c文件
刚开始运行的是这个函数,当然可以找到在set_wan.c里面有:
if (wan_type == DHCP_CLIENT) //当为DHCP客户端时候
wandhcpc_startup(wan_interface, dns_mode);
函数注释如下:
__externC int wandhcpc_startup(char *if_name, int dns_mode)
{
diag_printf("enter dhcpc_startup\n");//在串口打印信息里面可以找到这条打印信息
if (wandhcpc_started==1)
{
diag_printf("DHCPC has already been startup\n");//串口里面没有找到这条打印信息
return(-1);
}
unsigned char flag=0;
flag |= 0x01;
if(dns_mode==0) //auto dns
flag |= 0x02;
sprintf(wan_ifname, "dhcpc %s", if_name);
if (wandhcpc_running==0)
{
cyg_thread_create(DHCPC_THREAD_PRIORITY,//创建线程,DHCPC_THREAD_PRIORITY为线程优先级,找到定义为16
dhcpc_main, //线程函数指针,即为相应的函数入口
flag, //线程函数的入口参数
wan_ifname, //线程名
wandhcpc_stack,//堆栈基址
sizeof(wandhcpc_stack),//堆栈大小
&wandhcpc_thread,//线程句柄
&wandhcpc_thread_object);//保存线程内核数据结构的存储空间
diag_printf("Starting WAN DHCPC thread\n");//串口有这条打印信息
cyg_thread_resume(wandhcpc_thread);//线程进入RUNNING状态
wandhcpc_started=1;
return(0);
}
else
{
diag_printf("WAN DHCPC is already running\n");
return(-1);
}
}
跳往:
void dhcpc_main(cyg_addrword_t data)
{
while(1)
{
do_dhcp(data);//可见这个函数才是关键
sleep(2);
}
}
再跳往int do_dhcp(cyg_addrword_t data),这个函数有点长
if(((cyg_uint8)data) & 0x01)//data是入口函数,在wandhcpc_startup函数里对应flag,调试知道((cyg_uint8)data) & 0x01为真
{
intf=wan_ifname+6;
res=&wan_bootp_data;
pstate=&wan_dhcpstate;
lease=&wan_lease;
wandhcpc_running=1;
}
else
{
intf=lan_ifname+6;
res=&lan_bootp_data;
pstate=&lan_dhcpstate;
lease=&lan_lease;
landhcpc_running=1;
}
在这个函数里发现reset_timeout( &tv, &timeout_scratch );留意一下
接着进入while循环
while ( 1 ) {
if(recon_flag==1)
{
diag_printf("%s:%d RECONNECT!\n",__FUNCTION__,__LINE__);//没有发现打印这个信息,所以recon_flag==0应该
no_lease( lease );
do_dhcp_down_net( intf, res, &oldstate, lease );
oldstate=DHCPSTATE_INIT;
syslogAll_printk("DHCPC disconnect!\n");
syslogAll_printk("DHCPC reinit!\n");
goto RE_CONNECT;
}
diag_printf("%s:%d\n",__FUNCTION__,__LINE__);//打印了这条信息,__FUNCTION__是正在运行的函数,__LINE__是在文件的哪一行
if ( DHCPSTATE_DO_RELEASE != *pstate
&& DHCPSTATE_NOTBOUND != *pstate
&& DHCPSTATE_FAILED != *pstate ) {
cyg_uint8 lease_state;
diag_printf("%s:%d\n",__FUNCTION__,__LINE__);//有这个打印信息,证明进入了这个if语句
if ( lease_state & DHCP_LEASE_EX ) { }//调试信息显示没有进入这个if语句,三个都没进入
else if ( lease_state & DHCP_LEASE_T2 ) {
else if ( lease_state & DHCP_LEASE_T1 ) {
然后进入switch ( *pstate ) {
case DHCPSTATE_INIT: //DHCP的init状态,在这个状态里发送DISCOVER报文
bzero(xmit, sizeof(*xmit));
xmit->bp_op = BOOTREQUEST; //操作码
xmit->bp_htype = HTYPE_ETHERNET; //硬件地址类型
xmit->bp_hlen = IFHWADDRLEN; //硬件地址长度
xmit->bp_xid = xid; //传输ID,每次好像都不一样,应该是个随机数吧
xmit->bp_secs = cyg_current_time() / 100;// 客户机所使用的地址,在最近一次地址获取/地址更新后所经过的时间
*pstate = DHCPSTATE_SELECTING;//说明接着进入DHCPSTATE_SELECTING的case项,即进入DHCP的SELECTING状态
在case DHCPSTATE_SELECTING:选项里发现:
if ( ! next_timeout( &tv, &timeout_scratch ) ) {
*pstate = DHCPSTATE_FAILED;
*pstate =DHCPSTATE_INIT;
break;
那么现在基本定位了发送DISCOVER报文时间间隔的地方:
static inline void reset_timeout( struct timeval *ptv, struct timeout_state *pstate )
{
#if 0
timeout_random++;
pstate->countdown = 4; // initial fast retries
pstate->secs = 3 + (timeout_random & 3);
ptv->tv_sec = 0;
ptv->tv_usec = 65536 * (2 + (timeout_random & 3)); // 0.1 - 0.3S, about
#endif
ptv->tv_sec=1;
ptv->tv_usec=500000;
}
static inline int next_timeout( struct timeval *ptv, struct timeout_state *pstate )
{
#if 0
if ( 0 < pstate->countdown-- )
return true;
if ( 0 == ptv->tv_sec )
ptv->tv_sec = pstate->secs;
else {
timeout_random++;
pstate->secs = ptv->tv_sec * 2 - 2 + (timeout_random & 3);
pstate->countdown = 2; // later fast retries
ptv->tv_sec = 0;
}
// If longer, too many tries...
return pstate->secs < CYGNUM_NET_DHCP_MIN_RETRY_TIME;
#endif
ptv->tv_sec=1;
ptv->tv_usec=500000;
return 1;
}
问题应该就在这里,但是为什么原厂#if 0 #endif把中间的代码屏蔽掉呢?
是否有特殊原因,这一点不好确认,但是1.5S发送一次报文也不会造成网络风暴吧,而且只要获取到IP了,DISCOVER报文就会停止,那么这是算一个bug呢,还是某种优化处理,也不确定。得去和市场部和测试部商量一下了,关于这个问题。
间隔1.5s发送一次DHCP DISCOVER报文相关推荐
- 通过access口加vlan标签吗_Access 发送不带标签的报文, 一般与 pc 、 server 相连时使用,端口能属于 3 个 VLAN。_学小易找答案...
[填空题]在正常情况下,车站实行逐级负责制,顺序依次为().中心站副站长.().值班员.(). [判断题]如果ping不通默认网关,说明IP地址信息中有关默认网关的设置是错误的. [单选题]下列各句中 ...
- Linux 下C/C++实现发送ICMP和ICMPv6(报文分析)
当终端系统无法到达目的地的IP数据包时,为了方便获取诊断信息.一种称为Internet控制消息协议(ICMP)的特殊协议与IP结合使用,以提供与IP协议层配置和IP数据包处理相关的诊断和控制信息.主要 ...
- Scapy 发送带数据的TCP报文 wireshark抓不到scapy发出的包
scapy的发送包函数 scapy中,将Ether()看作是第二层,IP()看作是第三层 send()是发送第三层的包,也就是IP层,会自动处理路由和第二层 sendp()是发送第二层的包,需要自己选 ...
- 华为交换机DHCP snooping
配置思路 1.使能DHCP Snooping功能. 2.配置接口的信任状态,以保证客户端从合法的服务器获取IP地址. 3.使能ARP与DHCPSnooping的联动功能,保证DHCP用户在异常下线时实 ...
- 哈工大计算机网络MOOC作业题解答
第一周 如图所示网络.A在t=0时刻开始向C发送一个2Mbits的文件:B在t=0.1+e秒(e为无限趋近于0的小正实数)向D发送一个1Mbits的文件.忽略传播延迟和结点处理延迟. 请回答下列问题: ...
- 2015年计算机网络考研真题及解析
一.单项选择题:第1~40小题,每小题2分,共80****分.下列每题给出的四个选项中,只有一个选项最符合试题要求. \33. 通过POP3协议接收邮件时,使用的传输层服务类型是 A.无连接不可靠的数 ...
- 计算机网络1-6章考研题
计算机网络六章考研题 1.物理层 2.数据链路层 3.网络层 4.运输层 5.应用层 1.在OSI参考模型中, 自下而上第一个提供端到端服务的层次是( ) 传输层为网络体系结构中高低层之间衔接的一个接 ...
- 【计算机网络】网络层精选习题1(含联考真题)
网络层的功能 选择题 1.网络层的主要目的是( ). A.在邻接结点间进行数据报传输 B.在邻接结点间进行数据报可靠传输 C.在任意结点间进行数据报传输 D.在任意结点间进行数据报可靠传输 2.路由器 ...
- DHCP八种报文 Discover Offer Request Ack Nack decline release inform及其工作原理流程 详解
工作端口 服务端端口:67 客户端端口:68 八种报文 Discover DHCP客户端寻找DHCP服务器位置时所使用的报文.DHCP请求客户端时,因不知服务器位置,便在本地网络中以广播形式发送Dis ...
最新文章
- 计算机应用基础 辅助教学系统,计算机应用基础课程辅助教学和智能测评系统使用手册——网络版.doc...
- 特斯拉化身电影院,马斯克:车自动开,你来看电影
- 打印数组算法:堆栈与深度优先搜索(迷宫问题)
- 机房管理系列之门禁系统
- java重置_JAVA復制數組和重置數組大小
- Harfbuzz API 基本用法
- 文字描边_6招迅速做出炫酷PPT字效!|10分钟干货第二期(文字描边)
- Qt工作笔记-QGraphics框架场景中图元的移除与析构
- linux中GIT组件,linux – 使用git和符号链接的基于组件的Web项目目录布局
- 运行Gazebo出现[Err] [REST.cc:205] Error in REST reques
- 国产plc做modbus从站_Modbus-RTU通信
- strcpy(d,s)的溢出问题
- [Asp.net]Uploadify上传大文件,Http error 500 解决方案
- 【招】阿里云技术战略高级专家
- 使用python将pdf转化为长图片
- Microsoft edge 主页被劫持的处理办法
- PIL gif 图片加文字 python
- 408如何复习?浙大学长经验贴
- M35J型多普勒流量计使用说明书
- 微信小程序:globalData和Storage数据存储的错误示例
热门文章
- 软件高分辨率缩放问题
- html圣杯布局,HTML+CSS实现圣杯布局!
- 所有伟大的创新,本质上都是从一小撮年轻人肆无忌惮打破规则开始的
- 两个数字交换的三种方法
- 好程序员云计算培训分享云计算中微服务是什么?
- 使用建造者模式(Builder Pattern) 设计Excel导出场景,附源码
- selenium使用PhantomJS浏览器报错module ‘selenium.webdriver‘ has no attribute ‘PhantomJS‘
- mysql所有任务为灰色_MySQL权限体系任务事理
- java 初始化从句_java中if从句
- .NET Core使用NPOI的例子