抓包发现我的路由器,如果没获取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报文相关推荐

  1. 通过access口加vlan标签吗_Access 发送不带标签的报文, 一般与 pc 、 server 相连时使用,端口能属于 3 个 VLAN。_学小易找答案...

    [填空题]在正常情况下,车站实行逐级负责制,顺序依次为().中心站副站长.().值班员.(). [判断题]如果ping不通默认网关,说明IP地址信息中有关默认网关的设置是错误的. [单选题]下列各句中 ...

  2. Linux 下C/C++实现发送ICMP和ICMPv6(报文分析)

    当终端系统无法到达目的地的IP数据包时,为了方便获取诊断信息.一种称为Internet控制消息协议(ICMP)的特殊协议与IP结合使用,以提供与IP协议层配置和IP数据包处理相关的诊断和控制信息.主要 ...

  3. Scapy 发送带数据的TCP报文 wireshark抓不到scapy发出的包

    scapy的发送包函数 scapy中,将Ether()看作是第二层,IP()看作是第三层 send()是发送第三层的包,也就是IP层,会自动处理路由和第二层 sendp()是发送第二层的包,需要自己选 ...

  4. 华为交换机DHCP snooping

    配置思路 1.使能DHCP Snooping功能. 2.配置接口的信任状态,以保证客户端从合法的服务器获取IP地址. 3.使能ARP与DHCPSnooping的联动功能,保证DHCP用户在异常下线时实 ...

  5. 哈工大计算机网络MOOC作业题解答

    第一周 如图所示网络.A在t=0时刻开始向C发送一个2Mbits的文件:B在t=0.1+e秒(e为无限趋近于0的小正实数)向D发送一个1Mbits的文件.忽略传播延迟和结点处理延迟. 请回答下列问题: ...

  6. 2015年计算机网络考研真题及解析

    一.单项选择题:第1~40小题,每小题2分,共80****分.下列每题给出的四个选项中,只有一个选项最符合试题要求. \33. 通过POP3协议接收邮件时,使用的传输层服务类型是 A.无连接不可靠的数 ...

  7. 计算机网络1-6章考研题

    计算机网络六章考研题 1.物理层 2.数据链路层 3.网络层 4.运输层 5.应用层 1.在OSI参考模型中, 自下而上第一个提供端到端服务的层次是( ) 传输层为网络体系结构中高低层之间衔接的一个接 ...

  8. 【计算机网络】网络层精选习题1(含联考真题)

    网络层的功能 选择题 1.网络层的主要目的是( ). A.在邻接结点间进行数据报传输 B.在邻接结点间进行数据报可靠传输 C.在任意结点间进行数据报传输 D.在任意结点间进行数据报可靠传输 2.路由器 ...

  9. DHCP八种报文 Discover Offer Request Ack Nack decline release inform及其工作原理流程 详解

    工作端口 服务端端口:67 客户端端口:68 八种报文 Discover DHCP客户端寻找DHCP服务器位置时所使用的报文.DHCP请求客户端时,因不知服务器位置,便在本地网络中以广播形式发送Dis ...

最新文章

  1. 计算机应用基础 辅助教学系统,计算机应用基础课程辅助教学和智能测评系统使用手册——网络版.doc...
  2. 特斯拉化身电影院,马斯克:车自动开,你来看电影
  3. 打印数组算法:堆栈与深度优先搜索(迷宫问题)
  4. 机房管理系列之门禁系统
  5. java重置_JAVA復制數組和重置數組大小
  6. Harfbuzz API 基本用法
  7. 文字描边_6招迅速做出炫酷PPT字效!|10分钟干货第二期(文字描边)
  8. Qt工作笔记-QGraphics框架场景中图元的移除与析构
  9. linux中GIT组件,linux – 使用git和符号链接的基于组件的Web项目目录布局
  10. 运行Gazebo出现[Err] [REST.cc:205] Error in REST reques
  11. 国产plc做modbus从站_Modbus-RTU通信
  12. strcpy(d,s)的溢出问题
  13. [Asp.net]Uploadify上传大文件,Http error 500 解决方案
  14. 【招】阿里云技术战略高级专家
  15. 使用python将pdf转化为长图片
  16. Microsoft edge 主页被劫持的处理办法
  17. PIL gif 图片加文字 python
  18. 408如何复习?浙大学长经验贴
  19. M35J型多普勒流量计使用说明书
  20. 微信小程序:globalData和Storage数据存储的错误示例

热门文章

  1. 软件高分辨率缩放问题
  2. html圣杯布局,HTML+CSS实现圣杯布局!
  3. 所有伟大的创新,本质上都是从一小撮年轻人肆无忌惮打破规则开始的
  4. 两个数字交换的三种方法
  5. 好程序员云计算培训分享云计算中微服务是什么?
  6. 使用建造者模式(Builder Pattern) 设计Excel导出场景,附源码
  7. selenium使用PhantomJS浏览器报错module ‘selenium.webdriver‘ has no attribute ‘PhantomJS‘
  8. mysql所有任务为灰色_MySQL权限体系任务事理
  9. java 初始化从句_java中if从句
  10. .NET Core使用NPOI的例子