tcp_record.c
最終更新:2010/1/15
001: /* 002: * tcp_record.c 003: * libpcap を使った TCP パケット解析サンプルコード 004: * ・コネクションごとに別ファイルにダンプする。 005: * ・起動後に SYN を検出したものだけ記録する。 006: * ・Ctrl-C で終了。 007: */ 008: 009: #define PROG_NAME "tcp_record" 010: 011: #include "mystab_pcap.h" 012: #include "apr_getopt.h" 013: #include "apr_network_io.h" 014: 015: /* デバッグフラグ D0 全パケットの表示等 */ 016: #define D0 0 017: 018: /* デバッグフラグ D1 全状態遷移の表示 */ 019: #define D1 0 020: 021: /* デバッグフラグ D2 オープンクローズの表示 */ 022: #define D2 1 023: 024: /* デバッグフラグ DD その他 */ 025: #define DD 0 026: 027: 028: /* コマンドラインオプション定義 */ 029: 030: static const apr_getopt_option_t opt_option[] = { 031: /* long-option, short-option, has-arg flag, description */ 032: { "port_num", 'p', TRUE, "[MUST] port_number" }, 033: { "interface", 'i', TRUE, "[MUST] network device to use" }, 034: { "log_dir", 'l', TRUE, "[MUST] log directory to record" }, 035: { "hex_dump", 'H', FALSE, "[OPTION] dumps tcp-payload in hexadecimal."}, 036: { "help", 'h', FALSE, "[OPTION] this help" }, /* -h or --help */ 037: 038: #if defined(WIN32) || defined(WINDOWS) || defined(MSVC) 039: 040: { "disp_ifs", 'D', FALSE, 041: "[OPTION] displays avalable interfaces (Win Only)" }, 042: 043: #endif 044: 045: { NULL, 0, 0, NULL }, /* SENTINEL */ 046: }; 047: 048: /* カスタマイズ可能マクロ変数定義:ここから */ 049: 050: /* 同時に扱えるコネクション数 051: * 詳細:コネクションレコードテーブルのサイズのデフォルト値 (65536未満) 052: */ 053: #define CONREC_TAB_SIZE 100 054: 055: /* 応答待ちバッファ (ACK 待ちの TCP ペイロードを格納するバッファ)のサイズ 056: * このサイズを超えたパケットが発生した場合は、記録を強制終了する 057: */ 058: #define TCP_PAYLOAD_BUFFER_SIZE (1500*5) 059: 060: /* コネクションレコードの保持のタイムアウト秒 061: * 最後にパケットの発生した時間から、この秒数を経過した記録は 062: * 強制的に終了する 063: */ 064: #define TIME_OUT_SEC 600 065: 066: /* カスタマイズ可能マクロ変数定義:ここまで */ 067: 068: 069: /* コネクションレコードテーブル */ 070: 071: typedef struct _st_my_conrec { 072: 073: /* ステータス(0で未使用) */ 074: apr_byte_t stat; 075: 076: /* コネクションID */ 077: apr_uint32_t id; 078: 079: /* コネクション名 XXX.XXX.XXX.XXX:XXXXX-XXX.XXX.XXX.XXX:XXXXX */ 080: char name[43]; 081: 082: /* クライアントIPアドレス */ 083: char c_ipaddr[16]; 084: /* クライアントポート番号 */ 085: apr_uint16_t c_port; 086: /* サーバIPアドレス */ 087: char s_ipaddr[16]; 088: /* サーバポート番号 */ 089: apr_uint16_t s_port; 090: 091: /* 開始日時 */ 092: apr_time_t start_time; 093: 094: /* パケットの発生した最終日時 */ 095: time_t last_time; 096: 097: /* メモリプール */ 098: apr_pool_t *pool; 099: 100: /* ログファイルのファイルポインタ */ 101: apr_file_t *fp; 102: 103: /* クライアントシーケンス番号 */ 104: apr_uint32_t c_seq_no; 105: /* サーバシーケンス番号 */ 106: apr_uint32_t s_seq_no; 107: 108: /* サーバ応答待ちのクライアントデータのサイズ */ 109: apr_uint16_t c_data_size; 110: /* クライアント応答待ちのサーバデータのサイズ */ 111: apr_uint16_t s_data_size; 112: 113: /* サーバ応答待ちのクライアントデータ */ 114: apr_byte_t c_data[TCP_PAYLOAD_BUFFER_SIZE]; 115: /* クライアント応答待ちのサーバデータ */ 116: apr_byte_t s_data[TCP_PAYLOAD_BUFFER_SIZE]; 117: 118: } my_conrec; 119: 120: 121: /* コネクションテーブルのステータス */ 122: 123: #define CLOSED 1 124: #define SYN1 2 125: #define SYN2 3 126: #define ESTAB 4 127: #define C_FIN1 5 128: #define C_FIN2 6 129: #define S_FIN1 7 130: #define S_FIN2 8 131: #define UNKNOWN 99 132: 133: static apr_uint16_t count_active_conrec_data = 0; 134: static apr_uint16_t count_id = 0; 135: 136: my_conrec conrec_tab[CONREC_TAB_SIZE]; 137: 138: /* 監視対象ポート */ 139: static apr_uint16_t target_port = 0; 140: 141: /* ローカルアドレス文字列 */ 142: static const char *local_addr = NULL; 143: 144: /* ログ保存ディレクトリ */ 145: static const char *log_dir = NULL; 146: 147: /* 観測者情報 */ 148: static char *watcher_str = NULL; 149: 150: /* TCP ペイロードの16進ダンプフラグ */ 151: static int tcp_payload_hex_dump_flag = 0; 152: 153: #define STAT_NORMAL 0 154: #define STAT_TIME_OUT 1 155: #define STAT_ABORTED 2 156: #define STAT_OVERFLOW 3 157: 158: 159: void my_conrec_close ( 160: my_conrec * cr_ptr 161: , int status 162: ) { 163: 164: if (cr_ptr->fp) { 165: apr_status_t rv = APR_SUCCESS; 166: char kbuf[32]; 167: 168: apr_file_printf(cr_ptr->fp, "0\r\n"); 169: 170: rv = apr_rfc822_date(kbuf, apr_time_now()); 171: if (rv == APR_SUCCESS) { 172: apr_file_printf(cr_ptr->fp, "End-Date: %s\r\n", kbuf); 173: } 174: switch (status) { 175: case STAT_NORMAL: /* FIN パケット検出による正常終了 */ 176: apr_file_printf(cr_ptr->fp, "Status: %d NORMAL\r\n", status); 177: break; 178: case STAT_TIME_OUT: /* タイムアウトによる強制終了 */ 179: apr_file_printf(cr_ptr->fp, "Status: %d TIME_OUT\r\n", status); 180: break; 181: case STAT_ABORTED: /* プロセス終了による強制終了 */ 182: apr_file_printf(cr_ptr->fp, "Status: %d ABORTED\r\n", status); 183: break; 184: case STAT_OVERFLOW: /* 応答待ちバッファあふれによる強制終了 */ 185: apr_file_printf(cr_ptr->fp, "Status: %d OVERFLOW\r\n", status); 186: break; 187: } 188: apr_file_printf(cr_ptr->fp, "\r\n"); 189: apr_file_close(cr_ptr->fp); 190: cr_ptr->fp = NULL; 191: } 192: if (cr_ptr->pool) { 193: apr_pool_destroy(cr_ptr->pool); 194: cr_ptr->pool = NULL; 195: } 196: 197: memset(cr_ptr, 0, sizeof(my_conrec)); 198: 199: count_active_conrec_data--; 200: } 201: 202: /* 203: * 返り値: 204: * エラー時は NULL 205: */ 206: 207: my_conrec *my_conrec_get ( 208: const char *c_ipaddr 209: , apr_uint16_t c_port 210: , const char *s_ipaddr 211: , apr_uint16_t s_port 212: ) { 213: my_conrec *cr_ptr = NULL; 214: int i=0; 215: for (i=0; i<CONREC_TAB_SIZE; i++) { 216: cr_ptr = & conrec_tab[i]; 217: if (! cr_ptr->stat) { 218: continue; 219: } 220: if (time(NULL) - cr_ptr->last_time >= TIME_OUT_SEC) { 221: if(DD)puts("#Time UP!."); 222: my_conrec_close(cr_ptr, STAT_TIME_OUT); 223: continue; 224: } 225: if (!strcmp(c_ipaddr, cr_ptr->c_ipaddr) && c_port==cr_ptr->c_port && 226: !strcmp(s_ipaddr, cr_ptr->s_ipaddr) && s_port==cr_ptr->s_port) { 227: if(0)puts("Found!"); 228: return cr_ptr; 229: } 230: } 231: 232: return NULL; 233: } 234: 235: my_conrec * my_conrec_new ( 236: const char *c_ipaddr 237: , apr_uint16_t c_port 238: , const char *s_ipaddr 239: , apr_uint16_t s_port 240: ) { 241: my_conrec *cr_ptr = NULL; 242: int i=0; 243: for (i=0; i<CONREC_TAB_SIZE; i++) { 244: cr_ptr = & conrec_tab[i]; 245: if (cr_ptr->stat > 0) { 246: if (time(NULL) - cr_ptr->last_time < TIME_OUT_SEC) { 247: continue; 248: } else { 249: my_conrec_close(cr_ptr, STAT_TIME_OUT); 250: } 251: } 252: 253: cr_ptr->stat = CLOSED; 254: strcpy (cr_ptr->c_ipaddr, c_ipaddr); 255: cr_ptr->c_port = c_port; 256: strcpy (cr_ptr->s_ipaddr, s_ipaddr); 257: cr_ptr->s_port = s_port; 258: cr_ptr->start_time = apr_time_now(); 259: cr_ptr->last_time = time(NULL); 260: 261: snprintf(cr_ptr->name, 43, "%s:%d-%s:%d", c_ipaddr, c_port, s_ipaddr, 262: s_port); 263: 264: cr_ptr->id = count_id++; 265: 266: count_active_conrec_data++; 267: return cr_ptr; 268: } 269: 270: return NULL; 271: } 272: 273: void my_conrec_open ( 274: my_conrec * cr_ptr 275: ) { 276: apr_status_t rv = APR_SUCCESS; 277: rv = apr_pool_create(& cr_ptr->pool, NULL); 278: 279: if (rv != APR_SUCCESS) { 280: return; 281: } 282: 283: { 284: apr_time_exp_t tm; 285: char *out_filename = NULL; 286: char tbuf[16]; /* YYYYMMDD-hhmmss */ 287: int retsize = 0; 288: 289: apr_time_exp_lt(&tm, cr_ptr->start_time); 290: apr_strftime(tbuf, &retsize, 16, "%Y%m%d-%H%M%S", &tm); 291: 292: out_filename = apr_psprintf(cr_ptr->pool, 293: "%s/%s-%05u-%s-%u-%s-%u.txt", 294: log_dir, tbuf, cr_ptr->id, cr_ptr->c_ipaddr, cr_ptr->c_port, 295: cr_ptr->s_ipaddr, cr_ptr->s_port); 296: 297: if(DD)printf("#%s\n", out_filename); 298: 299: rv = apr_file_open(& cr_ptr->fp, out_filename, 300: APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE|APR_FOPEN_BINARY, 301: APR_OS_DEFAULT, cr_ptr->pool); 302: 303: if (rv != APR_SUCCESS) { 304: if(DD)printf("#ERROR: %s (%u)\n", out_filename, cr_ptr->fp); 305: return; 306: } 307: 308: apr_file_printf(cr_ptr->fp, "Watcher: %s\r\n", watcher_str); 309: apr_file_printf(cr_ptr->fp, "Session-Id: %s-%05u\r\n", tbuf, cr_ptr->id); 310: apr_file_printf(cr_ptr->fp, "Client: %s:%u\r\n", cr_ptr->c_ipaddr, 311: cr_ptr->c_port); 312: apr_file_printf(cr_ptr->fp, "Server: %s:%u\r\n", cr_ptr->s_ipaddr, 313: cr_ptr->s_port); 314: { 315: char kbuf[32]; 316: rv = apr_rfc822_date(kbuf, cr_ptr->start_time); 317: if (rv == APR_SUCCESS) { 318: apr_file_printf(cr_ptr->fp, "Date: %s\r\n", kbuf); 319: } 320: apr_file_printf(cr_ptr->fp, "\r\n"); 321: } 322: } 323: } 324: 325: 326: void my_conrec_record( 327: my_conrec *cr_ptr 328: , apr_byte_t direction_flag 329: , my_tcp_pkt *d 330: ) { 331: int i=0; 332: 333: if (! cr_ptr->fp) { 334: return; 335: } 336: apr_file_printf(cr_ptr->fp, "#%c,seq_no=%u,ack_no=%u,[", 337: (direction_flag)?'C':'S', d->tcp_seq_no, d->tcp_ack_no 338: ); 339: if (d->tcp_urg_bit) { 340: apr_file_printf(cr_ptr->fp, "urg:"); 341: } 342: if (0) if (d->tcp_ack_bit) { /* ACK ビットは必ず 1 になる */ 343: apr_file_printf(cr_ptr->fp, "ack:"); 344: } 345: if (d->tcp_psh_bit) { 346: apr_file_printf(cr_ptr->fp, "psh:"); 347: } 348: if (d->tcp_rst_bit) { 349: apr_file_printf(cr_ptr->fp, "rst:"); 350: } 351: if (d->tcp_syn_bit) { 352: apr_file_printf(cr_ptr->fp, "syn:"); 353: } 354: if (d->tcp_fin_bit) { 355: apr_file_printf(cr_ptr->fp, "fin:"); 356: } 357: apr_file_printf(cr_ptr->fp, "],size=%u", d->tcp_payload_size); 358: apr_file_printf(cr_ptr->fp, "\r\n"); 359: 360: if (tcp_payload_hex_dump_flag && d->tcp_payload_size) { 361: for (i=0; i<d->tcp_payload_size; i++) { 362: if (!i || i%32 == 0) { 363: apr_file_printf(cr_ptr->fp, "# "); 364: } 365: apr_file_printf(cr_ptr->fp, "%02X", d->tcp_payload_pos[i]); 366: if (i && i%32 == 31) { 367: apr_file_printf(cr_ptr->fp, "\r\n"); 368: } 369: } 370: if (i%32 != 0) { /* */ 371: apr_file_printf(cr_ptr->fp, "\r\n"); 372: } 373: } 374: } 375: 376: void my_conrec_set( 377: my_conrec *cr_ptr 378: , apr_byte_t direction_flag 379: , my_tcp_pkt *d 380: ) { 381: if (direction_flag) { 382: if (cr_ptr->c_data_size == 0 && d->tcp_seq_no > cr_ptr->c_seq_no) { 383: cr_ptr->c_seq_no = d->tcp_seq_no; 384: } 385: if (d->tcp_seq_no + d->tcp_payload_size <= cr_ptr->c_seq_no + cr_ptr->c_data_size) { 386: apr_file_printf(cr_ptr->fp, "#WARNING: my_conrec_set (1) already set!\r\n"); 387: } else if (cr_ptr->c_seq_no + cr_ptr->c_data_size == d->tcp_seq_no) { 388: if (cr_ptr->c_data_size + d->tcp_payload_size < TCP_PAYLOAD_BUFFER_SIZE) { 389: memcpy(cr_ptr->c_data + cr_ptr->c_data_size, d->tcp_payload_pos, d->tcp_payload_size); 390: cr_ptr->c_data_size += d->tcp_payload_size; 391: } else { 392: apr_file_printf(cr_ptr->fp, "#ERROR: cr_ptr->c_data overflow!\r\n"); 393: my_conrec_close(cr_ptr, STAT_OVERFLOW); 394: } 395: } else { 396: apr_file_printf(cr_ptr->fp, "#WARNING: my_conrec_set (2)\r\n"); 397: } 398: } else { 399: if (cr_ptr->s_data_size == 0 && d->tcp_seq_no > cr_ptr->s_seq_no) { 400: cr_ptr->s_seq_no = d->tcp_seq_no; 401: } 402: if (d->tcp_seq_no + d->tcp_payload_size <= cr_ptr->s_seq_no + cr_ptr->s_data_size) { 403: apr_file_printf(cr_ptr->fp, "#WARNING: my_conrec_set (3) already set!\r\n"); 404: } else if (cr_ptr->s_seq_no + cr_ptr->s_data_size == d->tcp_seq_no) { 405: if (cr_ptr->s_data_size + d->tcp_payload_size < TCP_PAYLOAD_BUFFER_SIZE) { 406: memcpy(cr_ptr->s_data + cr_ptr->s_data_size, d->tcp_payload_pos, d->tcp_payload_size); 407: cr_ptr->s_data_size += d->tcp_payload_size; 408: } else { 409: apr_file_printf(cr_ptr->fp, "#ERROR: cr_ptr->s_data overflow!\r\n"); 410: my_conrec_close(cr_ptr, STAT_OVERFLOW); 411: } 412: } else { 413: apr_file_printf(cr_ptr->fp, "#WARNING: my_conrec_set (4)\r\n"); 414: } 415: } 416: } 417: 418: void my_conrec_ack( 419: my_conrec *cr_ptr 420: , apr_byte_t direction_flag 421: , my_tcp_pkt *d 422: ) { 423: if (direction_flag) { 424: if (d->tcp_ack_no == cr_ptr->s_seq_no + cr_ptr->s_data_size) { 425: if (cr_ptr->s_data_size > 0 && cr_ptr->fp) { 426: apr_size_t len = cr_ptr->s_data_size; 427: apr_file_printf(cr_ptr->fp, "S%u\r\n", cr_ptr->s_data_size); 428: apr_file_write(cr_ptr->fp, cr_ptr->s_data, &len); 429: apr_file_printf(cr_ptr->fp, "\r\n"); 430: cr_ptr->s_seq_no = d->tcp_ack_no; 431: cr_ptr->s_data_size = 0; 432: } 433: } else { 434: apr_file_printf(cr_ptr->fp, 435: "#WARNING: my_conrec_ack (1): (s_seq_no=%u)+(s_data_size=%u)!=(ack_no=%u)\r\n", 436: cr_ptr->s_seq_no, cr_ptr->s_data_size, d->tcp_ack_no); 437: } 438: } else { 439: if (d->tcp_ack_no == cr_ptr->c_seq_no + cr_ptr->c_data_size) { 440: if (cr_ptr->c_data_size > 0 && cr_ptr->fp) { 441: apr_size_t len = cr_ptr->c_data_size; 442: apr_file_printf(cr_ptr->fp, "C%u\r\n", cr_ptr->c_data_size); 443: apr_file_write(cr_ptr->fp, cr_ptr->c_data, &len); 444: apr_file_printf(cr_ptr->fp, "\r\n"); 445: cr_ptr->c_seq_no = d->tcp_ack_no; 446: cr_ptr->c_data_size = 0; 447: } 448: } else { 449: apr_file_printf(cr_ptr->fp, 450: "#WARNING: my_conrec_ack (2): (c_seq_no=%u)+(c_data_size=%u)!=(ack_no=%u)\r\n", 451: cr_ptr->c_seq_no, cr_ptr->c_data_size, d->tcp_ack_no); 452: } 453: } 454: } 455: 456: /* パケット(ディレクションとコードビット)による状態遷移 */ 457: 458: void my_tcp_trans (apr_byte_t direction_flag, my_tcp_pkt *d) { 459: 460: my_conrec *cr_ptr = NULL; 461: 462: char *client_ip = NULL; 463: apr_uint16_t client_port = 0; 464: char *server_ip = NULL; 465: apr_uint16_t server_port = 0; 466: 467: if (direction_flag) { 468: client_ip = d->ip_src_addr; 469: client_port = d->tcp_src_port; 470: server_ip = d->ip_dst_addr; 471: server_port = d->tcp_dst_port; 472: } else { 473: client_ip = d->ip_dst_addr; 474: client_port = d->tcp_dst_port; 475: server_ip = d->ip_src_addr; 476: server_port = d->tcp_src_port; 477: } 478: 479: if (direction_flag && d->tcp_syn_bit && !d->tcp_ack_bit) { 480: cr_ptr = my_conrec_new(client_ip, client_port, server_ip, server_port); 481: if (!cr_ptr) { 482: if(D2)puts("what's up ?! (1)"); 483: if(D2)printf("active=%d\n", count_active_conrec_data); 484: return; 485: } 486: cr_ptr->stat = SYN1; 487: cr_ptr->c_seq_no = d->tcp_seq_no; 488: return; 489: } 490: 491: cr_ptr = my_conrec_get(client_ip, client_port, server_ip, server_port); 492: if (!cr_ptr) { 493: return; 494: } 495: 496: 497: if (cr_ptr->stat == SYN1) { 498: if (!direction_flag && d->tcp_syn_bit) { 499: cr_ptr->stat = SYN2; 500: cr_ptr->s_seq_no = d->tcp_seq_no; 501: } 502: return; 503: } 504: 505: if (cr_ptr->stat == SYN2) { 506: if (direction_flag) { 507: cr_ptr->stat = ESTAB; 508: cr_ptr->c_seq_no = d->tcp_seq_no; 509: cr_ptr->s_seq_no = d->tcp_ack_no; 510: my_conrec_open(cr_ptr); 511: 512: if(D2)printf("[%s],%c,", cr_ptr->name, direction_flag?'C':'S'); 513: if(D2)printf("OPENED. active=%d\n", count_active_conrec_data); 514: return; 515: } 516: } 517: 518: my_conrec_record(cr_ptr, direction_flag, d); 519: my_conrec_ack(cr_ptr, direction_flag, d); 520: if (d->tcp_payload_size != 0) { 521: if (d->tcp_rst_bit) { 522: /* 再送パケットの処理がここに入る… */ 523: } 524: my_conrec_set(cr_ptr, direction_flag, d); 525: } 526: 527: if (cr_ptr->stat == ESTAB) { 528: 529: 530: if (direction_flag && d->tcp_fin_bit) { 531: cr_ptr->stat = C_FIN1; 532: // cr_ptr->c_seq_no++; 533: // cr_ptr->s_seq_no; 534: if(0)printf("[%s],%c,", cr_ptr->name, direction_flag?'C':'S'); 535: if(0)printf("C_FIN1.\n"); 536: return; 537: } 538: 539: if (!direction_flag && d->tcp_fin_bit) { 540: cr_ptr->stat = S_FIN1; 541: cr_ptr->c_seq_no++; /* このあたり、やや手探り… */ 542: cr_ptr->s_seq_no++; 543: if(0)printf("[%s],%c,", cr_ptr->name, direction_flag?'C':'S'); 544: if(0)printf("S_FIN1.\n"); 545: return; 546: } 547: 548: } 549: 550: if (cr_ptr->stat == C_FIN1) { 551: if (!direction_flag) { 552: if (cr_ptr->s_data_size == 0) { 553: if(D2)printf("[%s],%c,", cr_ptr->name, direction_flag?'C':'S'); 554: my_conrec_close(cr_ptr, STAT_NORMAL); 555: if(D2)printf("C_FIN1-ACK-CLOSED. active=%d\n", count_active_conrec_data); 556: } else { 557: cr_ptr->stat = C_FIN2; 558: } 559: 560: return; 561: } 562: } 563: 564: if (cr_ptr->stat == C_FIN2) { 565: if (cr_ptr->s_data_size == 0) { 566: if(D2)printf("[%s],%c,", cr_ptr->name, direction_flag?'C':'S'); 567: my_conrec_close(cr_ptr, STAT_NORMAL); 568: if(D2)printf("C_FIN1-ACK-CLOSED. active=%d\n", count_active_conrec_data); 569: } 570: } 571: 572: if (cr_ptr->stat == S_FIN1) { 573: if (direction_flag) { 574: if(D2)printf("[%s],%c,", cr_ptr->name, direction_flag?'C':'S'); 575: my_conrec_close(cr_ptr, STAT_NORMAL); 576: if(D2)printf("S_FIN1-ACK-CLOSED. active=%d\n", count_active_conrec_data); 577: return; 578: } 579: } 580: 581: } 582: 583: /* 584: * 指定されたホストネームのIPアドレスの文字列を返す関数 585: * hostname に "" を指定した場合、動作するホストのIPアドレスが返る。 586: */ 587: 588: char * get_host_addr(const char * hostname, apr_pool_t *pool) { 589: apr_status_t rv = APR_SUCCESS; 590: apr_sockaddr_t *sa = NULL; 591: char *ipaddr = NULL; 592: rv = apr_sockaddr_info_get (&sa, hostname, APR_UNSPEC, 0, 0, pool); 593: if (rv != APR_SUCCESS) { 594: return NULL; 595: } 596: 597: rv = apr_sockaddr_ip_get (&ipaddr, sa); 598: if (rv != APR_SUCCESS) { 599: return NULL; 600: } 601: 602: return ipaddr; 603: } 604: 605: void print_usage (apr_file_t *out) { 606: apr_getopt_option_t *ptr = (apr_getopt_option_t *)opt_option; 607: 608: apr_file_printf(out, "Usage: %s ", PROG_NAME); 609: while (ptr && ptr->name) { 610: if (ptr->has_arg) { 611: apr_file_printf(out, "[ -%c <arg> | --%s <arg> ] ", ptr->optch, 612: ptr->name); 613: } else { 614: apr_file_printf(out, "[ -%c | --%s ] ", ptr->optch, ptr->name); 615: } 616: ptr++; 617: } 618: apr_file_printf(out, "\n"); 619: ptr = (apr_getopt_option_t *)opt_option; 620: while (ptr && ptr->name) { 621: apr_file_printf(out, "\t-%c, --%s\t: %s\n", ptr->optch, ptr->name, 622: ptr->description); 623: ptr++; 624: } 625: 626: } 627: 628: /* 629: * コマンドライン引数の処理 630: */ 631: 632: int my_pcap_init ( 633: int ac 634: , char **av 635: , my_pcap_params *params 636: , apr_file_t *astderr 637: , apr_pool_t *pool 638: ) { 639: apr_status_t rv = APR_SUCCESS; 640: 641: apr_getopt_t *opt = NULL; 642: int opt_ch = 0; 643: const char *opt_arg = NULL; 644: 645: const char * interface_str = NULL; 646: 647: if (ac < 2) { 648: print_usage(astderr); 649: return 0; 650: } 651: 652: rv = apr_getopt_init(&opt, pool, ac, (const char * const *)av); 653: 654: if (rv != APR_SUCCESS) { 655: apr_file_printf(astderr, "ERROR: apr_getopt_init\n"); 656: return 0; 657: } 658: 659: while ((rv = apr_getopt_long(opt, opt_option, &opt_ch, &opt_arg)) 660: == APR_SUCCESS) { 661: 662: switch (opt_ch) { 663: case 'p': 664: target_port = atoi(opt_arg); 665: break; 666: 667: case 'i': 668: interface_str = opt_arg; 669: break; 670: 671: case 'l': 672: log_dir = opt_arg; 673: break; 674: 675: case 'H': 676: tcp_payload_hex_dump_flag = 1; 677: break; 678: 679: #if defined(WIN32) || defined(WINDOWS) || defined(MSVC) 680: 681: case 'D': 682: { 683: char errbuf[80]; 684: if (! disp_devices(astderr, errbuf, sizeof(errbuf))) { 685: apr_file_printf(astderr, "ERROR: disp_devices: %s\n", errbuf); 686: } 687: } 688: return 0; 689: break; 690: 691: #endif 692: 693: case 'h': 694: print_usage(astderr); 695: return 0; 696: } 697: 698: } 699: 700: if (rv != APR_EOF || target_port<=0 || !interface_str || !log_dir) { 701: print_usage(astderr); 702: return 0; 703: } 704: 705: /* libpcap 用パラメータのセット */ 706: params->device = interface_str; 707: params->filter = apr_psprintf(pool, "tcp port %d", target_port); 708: 709: watcher_str = get_host_addr("", pool); 710: memset(conrec_tab, 0, sizeof(conrec_tab)); 711: return 1; 712: } 713: 714: void my_pcap_main( 715: apr_pool_t *pool 716: , apr_file_t *out 717: , my_tcp_pkt *d 718: ) { 719: 720: apr_byte_t direction_flag = 0; 721: 722: if (!d || !pool || !out) { 723: return; 724: } 725: 726: if (d->tcp_dst_port == target_port) { 727: direction_flag = 1; 728: } 729: 730: my_tcp_trans(direction_flag, d); 731: } 732: 733: /* 734: * 終期化処理 735: * コネクションテーブルの強制クローズ 736: */ 737: 738: void my_pcap_finally ( 739: apr_file_t *out 740: ) { 741: 742: int i=0; 743: my_conrec *cr_ptr = NULL; 744: for (i=0; i<CONREC_TAB_SIZE; i++) { 745: cr_ptr = & conrec_tab[i]; 746: if (cr_ptr->stat) { 747: my_conrec_close(cr_ptr, STAT_ABORTED); 748: } 749: } 750: apr_file_printf(out, "done.\n"); 751: }
KAKU PROJECT (2009) |