ktcpdump3.c

最終更新:2010/1/12

ktcpdump3.c

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