☆ Ethereal内置解码器随笔 (随笔的意思就是非正式文档,挑三拣四地说了几处地方而已) 下面这几份文档不得不看,必须承认,它们非常烂: doc\README.developer doc\README.plugins doc\README.tvbuff 所谓内置解码器,就是将来编译到libethereal.dll中的解码函数,源代码位于epan\ dissectors目录,名为packet-xxx.c的便是。如果看别人写的源代码,或是自己写源 代码,应该从下面这个函数开始: void proto_register_xxx ( void ); 相当于解码器的总入口。以packet-time.c为例,proto_register_time()一上来就调 用proto_register_protocol()注册协议,后者的三个形参都要保证在Ethereal运行 时的惟一性,这是我实测出来的结论。更多细节,看过文档自己再尝试一下较好。接 下来应该看: void proto_reg_handoff_xxx ( void ); 在这里注册解码函数,也就是将解码函数与协议关联起来。解码函数原型如下: static void dissect_xxx ( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree ); 这是程序员真正要动脑子去实现的函数。一不小心出个事,多在这里。可以关注一下 dissector_add()调用,该函数完成协议层次关联。一般靠端口识别进行关联,比如: dissector_add( "udp.port", UDP_PORT_TIME, time_handle ); 就是说UDP端口等于37时调用dissect_time()进行解码。上面介绍的是一般情况,并 不是所有内置解码器都如此实现。比如packet-rwall.c: void proto_reg_handoff_rwall ( void ) { /* * Register the protocol as RPC */ rpc_init_prog ( proto_rwall, RWALL_PROGRAM, ett_rwall ); /* * Register the procedure tables */ rpc_init_proc_table ( RWALL_PROGRAM, 1, rwall1_proc, hf_rwall_procedure_v1 ); } /* end of proto_reg_handoff_rwall */ 显然ONC/Sun RPC因涉及动态端口而做了其它处理,参看: epan\dissectors\packet-rpc.h epan\dissectors\packet-rpc.c doc\README.developer提供了一个框架代码,但据我的经验,不如看packet-time.c。 搭好编译环境,改动pakcet-time.c,运行最终自编译出来的程序,一对照改动在哪 里生效,就很好理解Ethereal提供的那堆API了。Ethereal的文档不是一般的烂,但 看完之后也理解了为什么这么烂,我也不想写那么多精细的文档。编写内置解码器时, 要注意这两个函数: void proto_register_xxx ( void ) { } /* end of proto_register_xxx */ void proto_reg_handoff_xxx ( void ) { } /* end of proto_reg_handoff_xxx */ 编译时有脚本生成其它代码调用这两个函数,文档要求写这两个函数头时保持一定格 式,我曾写成如下格式: void proto_register_xxx ( void ) { } /* end of proto_register_xxx */ void proto_reg_handoff_xxx ( void ) { } /* end of proto_reg_handoff_xxx */ 编译通过,但实际没有生成正确的调用它们的代码,也就是说你写的解码函数不会被 调用。另一个要注意的地方是: prefs_register_bool_preference() doc\README.developer中的框架代码就是错的。该函数的第二形参要求比较严格,应 确保由小写字母、数字、下划线、点号组成,第三、四形参则无所谓。参看: epan\prefs.c:431 如果违反了,编译通过,运行时报错。 Ethereal提供了一个函数abs_time_secs_to_str(),这个函数内部调用了localtime, 后者不是线程安全函数。我看到有些内置解码器在调用abs_time_secs_to_str(),难 道说Ethereal在解码时是单线程进行的?应该是这样,不然肯定会坏菜。参看: epan\to_str.h epan\to_str.c