liuqun / njit8021xclient

南京工程学院802.1X客户端(Linux版兼容H3C/iNode V2.40-F0335)
http://wiki.ubuntu.org.cn/南京工程学院802.1X客户端
159 stars 107 forks source link

auth.c 中超时参数 DefaultTimeout 设置错误导致认证失败 #12

Closed bitdust closed 8 years ago

bitdust commented 8 years ago

最近编译了njit8021xclient发现其工作不正常。特征是:

  1. 发送start包后很久才收到交换机的响应包;
  2. 心跳响应也不正常。

通过wireshark抓包发现,本机在已收到交换机的802.1x验证数据包时,njit8021xclient并没有及时响应,程序内存在着对数据包处理的巨大时延。

同时与QQ群中其他成员交流发现,他们也存在同样问题。同时@kingxf 总结经验是在libpcap-1.3及以前版本下,工作正常。新版本的libpcap下就会如上所说出现大时延导致认证失败。

阅读源码后发现,在 auth.c 中第87行有参数:

const int DefaultTimeout=60000;//设置接收超时参数,单位ms

用于pcap_open_live(DeviceName,65536,1,DefaultTimeout,errbuf),但是参照libpcap官方文档中对read timeout的解释

If, when capturing, packets are delivered as soon as they arrive, the application capturing the packets will be woken up for each packet as it arrives, and might have to make one or more calls to the operating system to fetch each packet. If, instead, packets are not delivered as soon as they arrive, but are delivered after a short delay (called a "read timeout"), more than one packet can be accumulated before the packets are delivered, so that a single wakeup would be done for multiple packets, and each set of calls made to the operating system would supply multiple packets, rather than a single packet. This reduces the per-packet CPU overhead if packets are arriving at a high rate, increasing the number of packets per second that can be captured. The read timeout is required so that an application won't wait for the operating system's capture buffer to fill up before packets are delivered; if packets are arriving slowly, that wait could take an arbitrarily long period of time.

简而言之,这个参数的设置是为了在大吞吐情况下减轻程序处理负担而设置的的。其作用是将一段时间(即我们设置的DefaultTimeout)内的包批量发送给程序进行处理。 正如文档最后一段所言,如果这一参数设置过大而要捕获的数据包来的太慢,则会带来很大的处理延时。因为pcap在捕获每个包后都必须等待一个DefaultTimeout周期。在stackoverflow也有类似讨论(问题1问题2)。

因此,对于njit8021xclient的应用场景:数据包吞吐量小,没有复杂的处理机制。这个参数应该设置的尽可能小,比如直接设置为 0 即可。 于是把DefaultTimeout改为0后再次测试,发现njit8021xclient工作正常。

顺便猜测下,为什么以前(libpcap-1.3)没有发现这个问题?根据libpcap文档所说,这个参数在一些平台及网卡上有兼容性问题,即设置该值后,在一些网卡上无效,而变为零。也就是说可能是老版本libpcap的BUG将这个njit8021xclient的BUG抵消了,DefaultTimeout没有发挥作用;而新版本的libpcap中,这个值又开始工作了~ 总之,修改DefaultTimeout为0,一切问题都不存在了。不管是在libpcap-1.3以前还是以后的所有版本中。

Nappp commented 8 years ago

刚好最近遇到这个问题,测试了楼主提供的办法,使用稳定版Chaos Calmer重新编译,并安装了在对应的系统上。安装libpcap版本1.5,认证不会提示成功,而是打出一连串的⎡ . ⎦ 。此时可以连上网络。但是最快半分钟,最慢十分钟就会掉线,程除了打点未有其他输出。libpcap降回1.1后问题解决。则DefaultTimeout修改为0的办法还不完善。

bitdust commented 8 years ago

的确有其他人也报告这个办法依然没有解决问题。 我提的这个issue尚不完善 但话说,似乎高版本libpcap的兼容性问题只有我靠这里的办法解决了~而且是在openwrt、linux-ubuntu、windows下都可用的。 @Nappp 有功夫的话可以试试一个比较折中的值,1000或者500(我的代码一直在用500这个值)。

liuqun commented 8 years ago

在pcap.c文件中找到pcap_open_live函数,源码如下:

pcap_t * pcap_open_live(constchar *source, int snaplen, int promisc, int to_ms, char *errbuf)
{
       pcap_t*p;
       intstatus;
       p= pcap_create(source, errbuf);
       if(p == NULL)
              return(NULL);
       status= pcap_set_snaplen(p, snaplen);
       if(status < 0)
              gotofail;
       status= pcap_set_promisc(p, promisc);
       if(status < 0)
              gotofail;
       status= pcap_set_timeout(p, to_ms);
       if(status < 0)
              gotofail;
//...
}
liuqun commented 8 years ago
pcap_set_timeout(p, to_ms);
liuqun commented 8 years ago

``