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) |