tcp_record.c

最終更新:2010/1/15

tcp_record.c

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: }
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)