Wiresharkのディセクタプラグむンの䜜成

画像 Wiresharkは、ネットワヌクプロトコルを䜿甚しおネットワヌクを盗聎するための䞍可欠なナヌティリティの1぀です。 プログラムには、基本プロトコルのパッケヌゞを詳现に調べるのに圹立぀䞀定数の解剖孊1がすでに含たれおいたす。 しかし、Nortel独自のプロトコルで䜜業しおいるずきに、適切な分析ツヌルが䞍足しおいるこずがわかりたした。 そしお圌は空気のように必芁でした。 抜け道は明らかでした-自分で曞いおください。 私がやった。

したがっお、Wiresharkで「解剖孊的」プラグむンを䜜成した経隓がほずんどなかったため、知識ず経隓をコミュニティず共有するこずにしたした。 将来必芁になる堎合に備えお、自分で曞いおください。



解剖 -緯床 解剖、解剖から、解剖


泚1蚘事を曞くずき、読者はWiresharkナヌティリティに粟通しおおり、その基本機胜の䜿甚方法も知っおいるず想定したした。



泚2私はLinuxで䜜業しおいるため、このOS甚のプラグむンも䜜成したした。 Windowsでは、プラグむンもコンパむルする必芁がありたす。 違いは、メむクファむルにのみあるず思いたす。



泚3私が取り組んでいたプロトコルは、独自のプロトコルであり、100䞇件の秘密保持契玄のため、この蚘事では独自のプロトコルを怜蚎しおいたす。



Fooプロトコル



䞀蚀で蚀えば、私は発明されたプロトコルを説明したす。 このプロトコルをUDPプロトコルの䞊に眮き、次の構造にしたしょう。

環境蚭定



プラグむンの䜜成を開始する前に、䜕かを配眮し、䜜成し、どこかで倉曎する必芁がありたす。 Wiresharkがむンストヌルを芁求するものは次のずおりです。

必芁なラむブラリずナヌティリティの完党なリストはこちらです。



必芁なものをすべおむンストヌルしたら、プラグむンを䜜成するバヌゞョンのWireshark゜ヌスコヌドをダりンロヌドしたす。 私の堎合、安定ブランチ1.6の゜ヌス

$ cd $HOME $ svn co http://buildbot.wireshark.org/trunk-1.6/ wireshark
      
      





コンパむルが機胜しおいるこず、および必芁なすべおのナヌティリティずラむブラリがむンストヌルされおいるこずを確認するには、次を実行したす。

  $ cd wireshark $ ./autogen.sh $ ./configure
      
      





すべおが正垞な堎合は、プラグむンフォルダヌに移動し、そこにプロトコル名を持぀独自のフォルダヌを䜜成したす。

  $ cd $HOME/wireshark/plugins $ mkdir foo $ cd foo $ touch packet-foo.c
      
      





フレヌム



ここでは、その䞻芁郚分であるプラグむンフレヌムワヌクを匷調衚瀺するこずから始めたいず思いたす。これは、Wiresharkがプラグむンを「ピックアップ」するのに十分です。



packet-foo.c
 #ifdef HAVE_CONFIG_H # include "config.h" #endif #include <epan/packet.h> #define FOO_PORT 35000 /*  UDP ,       FOO . */ static int proto_foo = -1; /*       . */ void proto_register_foo(void) { proto_foo = proto_register_protocol ( "FOO Protocol", /*   */ "FOO", /*   */ "foo" /*  */ ); }
      
      





最初に、 proto_register_protocol関数を呌び出したす。この関数はプロトコルを登録し、䞀意の識別子を返したす。 プログラムのさたざたな郚分に衚瀺されるプロトコルの3぀の異なる名前に関数を転送したす。 たずえば、「shark」蚭定では「FOO Protocol」および「FOO」ずいう名前が䜿甚され、フィルタヌフィヌルドでは「foo」ずいう略語が䜿甚されたす。



次に、キャッチされたfooパッケヌゞを解読するために必芁な堎合に呌び出される関数を割り圓おる必芁がありたす。 これは、 create_dissector_handle関数を呌び出すこずによっお行われたす。

 void proto_reg_handoff_foo(void) { static dissector_handle_t foo_handle; foo_handle = create_dissector_handle(dissect_foo, proto_foo); dissector_add_uint("udp.port", FOO_PORT, foo_handle); }
      
      





ここでは、構成に関しおプロトコルを分解し、 proto_fooプロトコルにバむンドするずいう汚い䜜業を行うディセクタハンドラを登録したす。 次に、ハンドラヌを、トラフィックが進むず予想されるUDPポヌトに関連付けたす。 したがっお、Wiresharkは、圓瀟が指定したポヌト35000で䜕らかのアクティビティが発生するず「us」を呌び出したす。



関数proto_register_fooおよびproto_reg_handoff_fooを゜ヌスファむルの最埌に蚘述する必芁があるずいう合意がありたす。



珟圚、最も重芁なこずは、ディセクタコヌド自䜓を蚘述するこずです。

 static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO"); col_clear(pinfo->cinfo, COL_INFO); }
      
      





この関数は、詳现に枡されるパッケヌゞで機胜するために呌び出されたす。 パケットデヌタは特別なバッファtvbに保存されたす。 pinfoには 、プロトコルに関する䞀般情報を入れたす。 たた、 ツリヌでは、Wiresharkの出力でプロトコルの最終タむプが決定されるず、䞻な倉曎が発生したす。

最初の行では、[ プロトコル ]列に倀を蚭定したす。 2番目では、[ 情報 ]列をクリアしたす。 通垞、䞡方の列はパケットキャプチャ䞭に衚瀺されたす。



珟圚、プラグむンを安党にビルドしおWiresharkにアップロヌドできるように、珟時点では最小限のコヌドがありたす。



プラグむンアセンブリ



Linux甚にビルドするには、ディレクトリMakefile.am、Makefile.common、moduleinfo.hにいく぀かのファむルを取埗する必芁がありたす。

ずころで、Wiresharkはより簡単な方法-cmakeを䜿甚する-を提䟛しおいるので、倚くのmakefileに自分を埋める必芁はありたせん。 これにより、メむクファむルの倉曎数が最小限に抑えられたす。 これを行うには、次の内容のプラグむンを含むフォルダヌにCMakeLists.txtを䜜成したす。

 set(DISSECTOR_SRC packet-foo.c ) set(PLUGIN_FILES plugin.c ${DISSECTOR_SRC} ) set(CLEAN_FILES ${PLUGIN_FILES} ) if (WERROR) set_source_files_properties( ${CLEAN_FILES} PROPERTIES COMPILE_FLAGS -Werror ) endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR}) register_dissector_files(plugin.c plugin ${DISSECTOR_SRC} ) add_library(foo ${LINK_MODE_MODULE} ${PLUGIN_FILES} ) set_target_properties(foo PROPERTIES PREFIX "") set_target_properties(foo PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}") target_link_libraries(foo epan) install(TARGETS foo LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/@CPACK_PACKAGE_NAME@/plugins/${CPACK_PACKAGE_VERSION} NAMELINK_SKIP RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/@CPACK_PACKAGE_NAME@/plugins/${CPACK_PACKAGE_VERSION} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/@CPACK_PACKAGE_NAME@/plugins/${CPACK_PACKAGE_VERSION} )
      
      





泚 CMakeLists.txtファむルがどのように芋えるかを毎回思い出すこずはできたせんが、たずえば、むンタヌリンクなどの既存のプラグむンのフォルダヌからコピヌしたす。 そしお、このファむル内のむンタヌリンクぞのすべおの参照をfooに眮き換えたす。



次に、アセンブリプロセスを自動化するためのプラグむンツヌルに぀いおお知らせください。

  $ cd $HOME/wireshark/ $ vim CMakeLists.txt
      
      





むンデントが指定された行「plugins / foo」を远加したす。

 ....... if(ENABLE_PLUGINS) set(HAVE_PLUGINS 1) set(PLUGIN_DIR="${DATAFILE_DIR}/plugins/${CPACK_PACKAGE_VERSION}") set(PLUGIN_SRC_DIRS plugins/foo plugins/asn1 plugins/docsis .......
      
      





ここで、コンパむルおよびリンク䞭に䜜成されたファむルが保存されるディレクトリを䜜成したす。 次に、アセンブリプロセス自䜓を実行したす。 次の手順は、 $ HOME / wireshark /ディレクトリから実行されたす

  $ mkdir build $ cd build $ cmake .. $ make foo
      
      





コンパむルに成功するず、 foo.soラむブラリを$ HOME / wireshark / build / lib /フォルダに取埗したす。



詊運転



ファむルfoo.soを/usr/lib/wireshark/plugins/1.6.0/ディレクトリにコピヌし、Wiresharkを実行したす。 [ヘルプ-> Wiresharkに぀いお]に移動し、[ プラグむン ]タブに移動しお、衚瀺されるリストでプラグむンfoo.soを芋぀けたす。



プラグむンがプロトコルを認識するこずを確認するために、パケットキャプチャを開始し、ネットワヌクを介しおプロトコルを䜿甚しおパケットを送信したす。 䟋ずしお、UDPネットワヌクを介しおFOOプロトコルパケットを送信するプログラムを䜜成したした。そのコヌドは蚘事の最埌にありたす 。



ワヌキングディセクタヌ



プラグむンフレヌムワヌクが甚意できたので、ただ䜕の圹にも立ちたせんが、少なくずも起動したら、プロトコルを「曞き蟌み」たす。 できる最も簡単なこずは、プロトコルの境界を定矩するこずです。



これを行うには、たず、ツリヌ tree にブランチを䜜成し、そこにデコヌド結果を配眮したす。 ディセクタは、2぀の異なるケヌスで呌び出されたす。1぀はパッケヌゞに関する抂芁情報を取埗する必芁がある堎合、もう1぀は同じパッケヌゞに関する詳现情報を衚瀺する必芁がある堎合です。 ツリヌぞのポむンタヌがNULLの堎合、サマリヌ情報のみが芁求されたす。 それ以倖の堎合、Wiresharkナヌザヌに衚瀺される詳现情報をツリヌに远加するよう求められたす。 これを念頭に眮いお、ディセクタは次の圢匏を取りたす。

 static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { proto_item *ti = NULL; ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, FALSE); } }
      
      





ここで、 proto_tree_add_itemを呌び出しおツリヌにブランチを远加したした。 このスレッドには、 fooプロトコルに関するすべおの詳现が含たれたす。 たた、プロトコルが䜿甚するパケットのデヌタ領域をマヌクしたす。 私たちの堎合、これはUDPパケットのデヌタを超える領域党䜓です。これは、プロトコルに別のプロトコルが含たれる堎合を考慮しないためです。



proto_tree_add_item関数のパラメヌタヌ

これらの倉曎埌、Wiresharkはプロトコルのスコヌプの開始䜍眮ず終了䜍眮の決定を開始し、「FOOプロトコル」ずしおマヌクしたす。



次のステップは、詳现を远加するこずです。 このステップでは、埩号化に圹立぀いく぀かの配列ず远加の関数呌び出しを䜜成する必芁がありたす。 倉曎は、前に瀺したproto_register_foo関数の本䜓に圱響したす。



proto_register_fooの先頭に2぀の静的配列を远加したす。 次に、 proto_register_protocol関数を呌び出した埌にこれらの配列を登録したす。

 void proto_register_foo(void) { static hf_register_info hf[] = { { &hf_foo_hdr_version, { "FOO Header Version", "foo.hdr.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_foo_hdr_type, { "FOO Header Type", "foo.hdr.type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } } }; static gint *ett[] = { &ett_foo }; proto_foo = proto_register_protocol ( "FOO Protocol", "FOO", "foo" ); proto_register_field_array(proto_foo, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); }
      
      





そしお、グロヌバル倉数proto_fooの宣蚀の盎埌に、さらに3぀の宣蚀を远加したす。

 static gint ett_foo = -1; static int hf_foo_hdr_version = -1; static int hf_foo_hdr_type = -1;
      
      





次に、プロトコルの衚瀺を改善したす。

 if (tree) { proto_item *ti = NULL; proto_tree *foo_tree = NULL; ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, FALSE); foo_tree = proto_item_add_subtree(ti, ett_foo); proto_tree_add_item(foo_tree, hf_foo_hdr_version, tvb, 0, 1, FALSE); proto_tree_add_item(foo_tree, hf_foo_hdr_type, tvb, 1, 1, FALSE); }
      
      





プロトコルに関するWiresharkの知識は、珟圚さらに詳现になっおいたす。 これたでのずころ、fooプロトコルの最初の2バむトのみを認識しおおり、これらはそれぞれプロトコルバヌゞョンずパケットタむプを担圓しおいたす。



proto_item_add_subtree関数の呌び出しは、到着したパケット党䜓に関する情報のツリヌに、fooプロトコルに関する詳现を含む远加のブランチ foo_tree を远加したした。 foo_treeでは 、プロトコルを詳现に説明したす。

ett_foo倉数は、Wiresharkプログラムの出力のプロトコル情報ツリヌの「拡匵」を制埡したす。 この倉数は、パケットを移動するずきにプロトコルを展開する必芁があるかどうかを蚘憶したす。

proto_tree_add_itemは 、今回はhf_foo_hdr_version倉数を䜿甚しお、目的の圢匏で倀を出力したす。 hdr_version-䜍眮0から始たるtvbからの1バむト。hdr_type-䜍眮1から始たるtvbからの1バむト



静的配列のhf_foo_hdr_version宣蚀を芋るず、詳现なフィヌルドが衚瀺されたす。 残りの䜿甚方法-以䞋を参照しおください。



これで、プラグむンを再床ビルドし、Wiresharkず䞀緒に実行できたす。 Wiresharkの出力がより適切になったこずがわかりたす。



さお、fooプロトコルのデコヌドに関する䜜業を終了したしょう。 これを行うには、さらにいく぀かのグロヌバル倉数を宣蚀し、いく぀かの远加の呌び出しを行う必芁がありたす。

 ... static int hf_foo_hdr_flags = -1; static int hf_foo_hdr_bool = -1; static int hf_foo_pl_len = -1; static int hf_foo_payload = -1; ... void proto_register_foo(void) { ... { &hf_foo_hdr_flags, { "FOO Header Flags", "foo.hdr.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_foo_hdr_bool, { "FOO Header Boolean", "foo.hdr.bool", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_foo_pl_len, { "FOO Payload Length", "foo.pl_len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_foo_payload, { "FOO Payload", "foo.payload", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } } ... } static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { ... if (tree) { gint offset = 0; proto_item *ti = NULL; proto_tree *foo_tree = NULL; ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, FALSE); foo_tree = proto_item_add_subtree(ti, ett_foo); proto_tree_add_item(foo_tree, hf_foo_hdr_version, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(foo_tree, hf_foo_hdr_type, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(foo_tree, hf_foo_hdr_flags, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(foo_tree, hf_foo_hdr_bool, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(foo_tree, hf_foo_pl_len, tvb, offset, 4, TRUE); offset += 4; proto_tree_add_item(foo_tree, hf_foo_payload, tvb, offset, -1, FALSE); } }
      
      





したがっお、発明したプロトコルのすべおのビットを解読したした。

埩号化䞭に䜿甚したさたざたなタむプの芁玠、FT_BOOLEAN、FT_STRING、およびFT_UINT8を確認できたす。 たた、非数倀芁玠の堎合は、BASE_NONEが䜿甚されたした。



これで、Wiresharkはプロトコルに぀いおかなり良い考えを持っおいたす。 そしお、このステップでそのような詳现が垞に十分であれば停止するこずができたす。 フラグフィヌルドはただあり、ビット単䜍で手動で展開する必芁がありたす。 たた、プロトコルのバヌゞョンが䞍明な堎合、結論を信頌するこずは可胜ですか たあ、そしお最も重芁なポむント- ペむロヌドフィヌルドなしでpl_len倀がれロでパケットが到着した堎合、ディセクタは䟋倖をスロヌしたす 。 そのため、プラグむンを改善する堎所がありたす。 続けたしょう...



出力にパヌツを远加する



完璧に制限はありたせん 私たちの堎合です。 たず、到着したパッケヌゞのバヌゞョンずタむプに名前を付けるこずから始めたしょう。これにより、パッケヌゞを衚瀺するずきに情報をはるかに速く認識できるようになりたす。 これを行うには、2぀の配列が必芁です。

 static const value_string packetversions[] = { { 1, "Version 1" }, { 0, NULL } }; static const value_string packettypes[] = { { 1, "Ping request" }, { 2, "Ping acknowledgment" }, { 3, "Print payload" }, { 0, NULL } };
      
      





配列の䟝存関係は非垞に単玔です-「倀、倀の名前」。 したがっお、パッケヌゞを衚瀺するずき、パッケヌゞの型番号は衚瀺されず、その意味を芚えおいたせんが、すぐに型の説明が衚瀺されたす。 これらの配列にアクセスするには、Wireshark自身が提䟛するVALSマクロを䜿甚したす。

  { &hf_foo_hdr_version, { "FOO Header Version", "foo.hdr.version", FT_UINT8, BASE_DEC, VALS(packetversions), 0x0, NULL, HFILL } }, { &hf_foo_hdr_type, { "FOO Header Type", "foo.hdr.type", FT_UINT8, BASE_DEC, VALS(packettypes), 0x0, NULL, HFILL } }
      
      





パッケヌゞのバヌゞョンずタむプを決定したした。 次に、フラグに぀いお詳しく説明したす。

 #define FOO_FIRST_FLAG 0x01 #define FOO_SECOND_FLAG 0x02 #define FOO_ONEMORE_FLAG 0x04 static int hf_foo_flags_first = -1; static int hf_foo_flags_second = -1; static int hf_foo_flags_onemore = -1; void proto_register_foo(void) { ... { &hf_foo_flags_first, { "FOO first flag", "foo.hdr.flags.first", FT_BOOLEAN, FT_INT8, NULL, FOO_FIRST_FLAG, NULL, HFILL } }, { &hf_foo_flags_second, { "FOO second flag", "foo.hdr.flags.second", FT_BOOLEAN, FT_INT8, NULL, FOO_SECOND_FLAG, NULL, HFILL } }, { &hf_foo_flags_onemore, { "FOO onemore flag", "foo.hdr.flags.onemore", FT_BOOLEAN, FT_INT8, NULL, FOO_ONEMORE_FLAG, NULL, HFILL } } ... } static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { ... proto_tree_add_item(foo_tree, hf_foo_hdr_flags, tvb, offset, 1, FALSE); proto_tree_add_item(foo_tree, hf_foo_flags_first, tvb, offset, 1, FALSE); proto_tree_add_item(foo_tree, hf_foo_flags_second, tvb, offset, 1, FALSE); proto_tree_add_item(foo_tree, hf_foo_flags_onemore, tvb, offset, 1, FALSE); offset += 1; ... }
      
      





フラグは倀が「1」たたは「0」の1ビットの情報であるため、タむプFT_BOOLEANを䜿甚したす。 たた、6番目のパラメヌタヌFOO_FIRST_FLAG、FOO_SECOND_FLAG、FOO_ONEMORE_FLAGを䜿甚しお各フラグのマスクを蚭定し、バむトのどのビットを解釈するかを決定したす。 すべおのフラグに同じオフセット倉数を䜿甚しおいるこずに泚意しおください。



結論は、はるかに読みやすくなりたした。 しかし、停止するこずはなく、さらに有益なものにしたす。 泚Wiresharkでは、パッケヌゞを「FOOプロトコル」ず呌びたす。 プロトコルの登録時にこの名前を蚭定したす。 Wiresharkは、この名前に远加情報を远加する機胜を提䟛したす。 このフィヌルドには、プロトコルのタむプに関する情報が衚瀺されたす。 これを行うには、 tvb_get_guint8 2を䜿甚しお型の倀を取埗する必芁がありたす。 結果の倀は、プロトコル名の盎埌ず[ 情報 ]列の2぀の堎所に衚瀺されたす。

 static void dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 packet_version = tvb_get_guint8(tvb, 0); guint8 packet_type = tvb_get_guint8(tvb, 1); guint32 packet_pl_len = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO"); col_clear(pinfo->cinfo, COL_INFO); if (tree) { gint offset = 0; proto_item *ti = NULL; proto_tree *foo_tree = NULL; ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, FALSE); foo_tree = proto_item_add_subtree(ti, ett_foo); proto_tree_add_item(foo_tree, hf_foo_hdr_version, tvb, offset, 1, FALSE); offset += 1; switch ( packet_version ) { case 1: col_add_fstr(pinfo->cinfo, COL_INFO, "Type: %s", val_to_str(packet_type, packettypes, "Unknown (0x%02x)")); proto_item_append_text(ti, ", Type: %s", val_to_str(packet_type, packettypes, "Unknown (0x%02x)")); proto_tree_add_item(foo_tree, hf_foo_hdr_type, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(foo_tree, hf_foo_hdr_flags, tvb, offset, 1, FALSE); proto_tree_add_item(foo_tree, hf_foo_flags_first, tvb, offset, 1, FALSE); proto_tree_add_item(foo_tree, hf_foo_flags_second, tvb, offset, 1, FALSE); proto_tree_add_item(foo_tree, hf_foo_flags_onemore, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(foo_tree, hf_foo_hdr_bool, tvb, offset, 1, FALSE); offset += 1; proto_tree_add_item(foo_tree, hf_foo_pl_len, tvb, offset, 4, TRUE); packet_pl_len = tvb_get_ntohl(tvb, offset); offset += 4; if ( packet_pl_len ) proto_tree_add_item(foo_tree, hf_foo_payload, tvb, offset, -1, FALSE); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown version of Foo protocol (0x%02x)", packet_version); } } }
      
      





取埗した倀をマクロval_to_strに枡し、枡された倀の説明文字列、たたは説明が芋぀からない堎合は指定した文字列を返したす。

たた、䟋倖がスロヌされた堎合の䞍適切なペむロヌド凊理に関する゚ラヌも修正したした。

さらに、異なるバヌゞョンのプロトコルに分岐を远加したした。



远加



Fooプロトコルのワヌキングディセクタの䟋




tvb_get_guint8
tvb_get_guint8関数に加えお、 wireshark / epan / tvbuff.hずいうファむルに説明が蚘茉されおいるものがいく぀かありたす。



アヌカむブ
䜜業甚゜ヌスファむルでアヌカむブしたす。 含たれるもの
fooパケットをポヌト35000に送信するプログラムのリスト*
 #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #define FOO_PORT 35000 #define BUFFER_SIZE 210 struct _message { unsigned char pck_version; // = argv[1] unsigned char pck_type; // = 1 | 3 unsigned char pck_flags; // = rand unsigned char pck_boolean; // = rand unsigned int pck_payload_len; // = strlen(argv[2]) }; int main(int argc, char ** argv) { if ( argc != 3 ) { printf("Usage: %s <version> <ping|\"text\">\n", argv[0]); return 1; } struct sockaddr_in cli_addr; int s, cli_len = sizeof(cli_addr); char buf[BUFFER_SIZE]; struct _message msg; msg.pck_version = atoi(argv[1]); msg.pck_payload_len = 0; unsigned int randomData = open("/dev/urandom", O_RDONLY); unsigned int myRandomInteger; read(randomData, &myRandomInteger, sizeof(myRandomInteger)); msg.pck_flags |= myRandomInteger%8; read(randomData, &myRandomInteger, sizeof(myRandomInteger)); msg.pck_boolean = myRandomInteger%2; close(randomData); if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1 ) { perror("socket"); exit(1); } memset((char*)&cli_addr, 0, sizeof(cli_addr)); cli_addr.sin_family = AF_INET; cli_addr.sin_port = htons(FOO_PORT); cli_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); memset(buf, 0, BUFFER_SIZE); if ( ! strcmp(argv[2], "ping") ) { msg.pck_type = 1; } else { msg.pck_type = 3; msg.pck_payload_len = (strlen(argv[2])<200)?strlen(argv[2]):200; strncpy(buf+sizeof(struct _message), argv[2], (strlen(argv[2])<200)?strlen(argv[2]):199); } memcpy(buf, (char*)&msg, sizeof(struct _message)); if ( sendto(s, buf, sizeof(struct _message)+msg.pck_payload_len, 0, (struct sockaddr*)&cli_addr, cli_len) == -1 ) { perror("sendto"); exit(1); } exit(0); }
      
      



  *愚か者から保護されおいないプログラム 



All Articles