tcprepplayソース解析
9394 ワード
一:前言:
tcprepplayの著者らはsendpacket()関数を書く際に、BPF、libpcap、libdnet、and Linux's PF_をサポートする汎用パケット送信apiインタフェースを書くことを望んでいると述べた.PACKETは、libnetが活動性に欠けているため、libpcapサポートモジュールが比較的新しく、非linuxサポートが欠けているため、著者らはこの4つを同時にサポートすることを決定した.彼らのマッチング順序は以下の通りであり、プラットフォームが最初にマッチングした関数をサポートする場合、それを使用して発注する.libpcapは信頼できる方法でMACアドレスを取得することができないため、PF_代わりにPACKET or BPF.
51 * 1. PF_PACKET send() (int)send(sp->handle.fd, (void *)data, len, 0);linuxでは52*2を使用します.BPF send() write(sp->handle.fd, (void *)data, len); freebsdでは53*3を用いる.libdnet eth_send() eth_send(sp->handle.ldnet, (void*)data, (size_t)len); 54 * 4. pcap_inject() pcap_inject(sp->handle.pcap, (void*)data, len);{
return (p->inject_op(p, buf, size));
}
handle->inject_op = pcap_inject_linux;
pcap_inject_linux(pcap_t *handle, const void *buf, size_t size){
ret = send(handle->fd, buf, size, 0);
} 55 * 5. pcap_sendpacket() pcap_sendpacket(sp->handle.pcap, data, (int)len);/* out of buffers,or hit max PHY speed,silently retry*/キャッシュから送信または最大速度で送信
{ if (p->inject_op(p, buf, size) == -1) return (-1); return (0); }
(1)PF_PACKET:linuxで使用し、プロトコルスタックを経ずにユーザー層に直接データを送受信する
(2)BPF:類Unixシステム上のデータリンク層の一種の原始インタフェースであり、原始リンク層のパッケージの送受信を提供し、bsdシステム上で使用し、プロトコルスタックを経ず、直接ユーザー層にデータを送受信する
(3)libnet、1つの小型のインタフェース関数ライブラリ、1つの簡単な統一的なネットワークプログラミングインタフェースを創立して異なるオペレーティングシステムの低層のネットワークプログラミングの違いを遮蔽して、libnetは現在Linux、FreeBSD、Solaris、WindowsNTなどのオペレーティングシステムの上で運行することができて、しかも統一的なインタフェースを提供しました
(4)libpcap:1つのネットワークがパケットのオープンソースをキャプチャし、tcpdump、snortなどの有名なソフトウェアパケットによって使用される.ほとんどのunixプラットフォームで作業できます.libpcapをlinuxで正常に動作させるには、カーネルに「packet」プロトコルをサポートする必要があります.つまり、カーネルをコンパイルするときに構成オプションCONFIGを開く必要があります.PACKET(オプションはデフォルトでオン).Windowsバージョンはwinpcapです.
pcap_Inject()はOpenBSDに由来し、p->inject_を呼び出すop,pcap_inject_linux,sendはデータを送信します.
pcap_send-packet()はWinPcap、pcap_に由来するInject実装と同様に,インタフェースを変更しただけで,0を返すと成功,−1は失敗を示す.両方の関数は互換性のために提供されます.
1,tcpreplayはtcpreplay tcpbridge tcpprep tcprewriteなどいくつかのソフトウェアからなるパッケージがある.
http://tcpreplay.sourceforge.net/
http://packages.debian.org/sid/sparc/tcpreplay
http://tcpreplay.synfin.net/wiki/Download#Source
http://tcpreplay.synfin.net/
以上のサイトでは、説明やソースのダウンロードができますが、すべて英語です.
2、ここで主にtcpreplayのソースコードを見ます
tcpreplayのソースコードは/tcpreplay-3.4.4/srcの下にあります
(1)使用した送信パケットの関数をsend_にカプセル化する.packets.cファイルの下のsend_packets(pcap,file_idx)関数では、
(2)send_packets(pcap,file_idx)の送信関数はsendpackにカプセル化する.c(/tcpreplay-3.4/src/common)ファイルのsendpacket(sendpacket_t*sp,const u_char*data,size_t len)関数に、.
(3)
sendpack()の送信関数はsend()またはwriteにカプセル化され、
#ifdef HAVE_PF_PACKET
#undef INJECT_METHOD
#define INJECT_METHOD "PF_PACKET send()"
#if defined HAVE_BPF && ! defined INJECT_METHOD
#undef INJECT_METHOD
#define INJECT_METHOD "bpf send()"
245 #elif defined HAVE_BPF
246 retcode = write(sp->handle.fd, (void *)data, len);
---------------------------------------eth_send()------------------------------------
267 #elif defined HAVE_LIBDNET
268 retcode = eth_send(sp->handle.ldnet, (void*)data, (size_t)len);
(4),send()と
write():sendto()をカプセル化した関数で、connectが接続決定インタフェースを確立してからのみ使用できます.
struct sendpacket_s {
tcpr_dir_t cache_dir;
int open;
char device[20];
char errbuf[SENDPACKET_ERRBUF_SIZE];
COUNTER retry_enobufs;
COUNTER retry_eagain;
COUNTER failed;
COUNTER sent;
COUNTER bytes_sent;
COUNTER attempt;
enum sendpacket_type_t handle_type;
union sendpacket_handle handle;
struct tcpr_ether_addr ether;
#ifdef HAVE_PF_PACKET
struct sockaddr_ll sa;
#endif
};
union sendpacket_handle {
pcap_t *pcap;
int fd;
#ifdef HAVE_LIBDNET
eth_t *ldnet;
#endif
};
struct pcap [pcap-int.h]
{
int fd;/* ファイル記述語、実際にはsocket*/
/*socketではselect()やpoll()などのI/O多重型関数を使用できます*/
int selectable_fd;
int snapshot;/* ユーザが望む取得パケットの最大長*/
int linktype;/* デバイスタイプ*/
int tzoff;/*タイムゾーン位置は、実際には使用されていません*/
int offset;/*境界位置合わせオフセット*/
int break_loop;/* 強制的にリードパケットサイクルから飛び出したフラグ*/
struct pcap_sf sf;/* パッケージをファイルに保存する関連構成データ構造*/
struct pcap_md md;/* 具体的には以下の*/
int bufsize;/* リードバッファの長さ*/
u_char buffer;/* リードバッファポインタ*/
u_char *bp;
int cc;
u_char *pkt;
/*関連抽象操作の関数ポインタ、最終的に特定のオペレーティングシステムの処理関数*/
int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *);
int (*setfilter_op)(pcap_t *, struct bpf_program *);
int (*set_datalink_op)(pcap_t *, int);
int (*getnonblock_op)(pcap_t *, char *);
int (*setnonblock_op)(pcap_t *, int, char *);
int (*stats_op)(pcap_t *, struct pcap_stat *);
void (*close_op)(pcap_t *);
/*BPFフィルタコードがカーネルで実行できない場合は、それを保存してユーザ空間で実行*/
struct bpf_program fcode;
/*関数呼び出しエラー情報バッファ*/
char errbuf[PCAP_ERRBUF_SIZE + 1];
/*現在のデバイスでサポートされている変更可能なデータリンクタイプの数*/
int dlt_count;
/*変更可能なデータリンクタイプ番号チェーンテーブル、linuxでは使用されていません*/
int *dlt_list;
/*パケットのヘッダをカスタマイズし、パケットの取得時間、取得長さ、実際の長さについて説明する[pcap.h]*/
struct pcap_pkthdr pcap_header;
};
完全なpcap構造体コード.
tcprepplayの著者らはsendpacket()関数を書く際に、BPF、libpcap、libdnet、and Linux's PF_をサポートする汎用パケット送信apiインタフェースを書くことを望んでいると述べた.PACKETは、libnetが活動性に欠けているため、libpcapサポートモジュールが比較的新しく、非linuxサポートが欠けているため、著者らはこの4つを同時にサポートすることを決定した.彼らのマッチング順序は以下の通りであり、プラットフォームが最初にマッチングした関数をサポートする場合、それを使用して発注する.libpcapは信頼できる方法でMACアドレスを取得することができないため、PF_代わりにPACKET or BPF.
51 * 1. PF_PACKET send() (int)send(sp->handle.fd, (void *)data, len, 0);linuxでは52*2を使用します.BPF send() write(sp->handle.fd, (void *)data, len); freebsdでは53*3を用いる.libdnet eth_send() eth_send(sp->handle.ldnet, (void*)data, (size_t)len); 54 * 4. pcap_inject() pcap_inject(sp->handle.pcap, (void*)data, len);{
return (p->inject_op(p, buf, size));
}
handle->inject_op = pcap_inject_linux;
pcap_inject_linux(pcap_t *handle, const void *buf, size_t size){
ret = send(handle->fd, buf, size, 0);
} 55 * 5. pcap_sendpacket() pcap_sendpacket(sp->handle.pcap, data, (int)len);/* out of buffers,or hit max PHY speed,silently retry*/キャッシュから送信または最大速度で送信
{ if (p->inject_op(p, buf, size) == -1) return (-1); return (0); }
(1)PF_PACKET:linuxで使用し、プロトコルスタックを経ずにユーザー層に直接データを送受信する
(2)BPF:類Unixシステム上のデータリンク層の一種の原始インタフェースであり、原始リンク層のパッケージの送受信を提供し、bsdシステム上で使用し、プロトコルスタックを経ず、直接ユーザー層にデータを送受信する
(3)libnet、1つの小型のインタフェース関数ライブラリ、1つの簡単な統一的なネットワークプログラミングインタフェースを創立して異なるオペレーティングシステムの低層のネットワークプログラミングの違いを遮蔽して、libnetは現在Linux、FreeBSD、Solaris、WindowsNTなどのオペレーティングシステムの上で運行することができて、しかも統一的なインタフェースを提供しました
(4)libpcap:1つのネットワークがパケットのオープンソースをキャプチャし、tcpdump、snortなどの有名なソフトウェアパケットによって使用される.ほとんどのunixプラットフォームで作業できます.libpcapをlinuxで正常に動作させるには、カーネルに「packet」プロトコルをサポートする必要があります.つまり、カーネルをコンパイルするときに構成オプションCONFIGを開く必要があります.PACKET(オプションはデフォルトでオン).Windowsバージョンはwinpcapです.
pcap_Inject()はOpenBSDに由来し、p->inject_を呼び出すop,pcap_inject_linux,sendはデータを送信します.
pcap_send-packet()はWinPcap、pcap_に由来するInject実装と同様に,インタフェースを変更しただけで,0を返すと成功,−1は失敗を示す.両方の関数は互換性のために提供されます.
1,tcpreplayはtcpreplay tcpbridge tcpprep tcprewriteなどいくつかのソフトウェアからなるパッケージがある.
http://tcpreplay.sourceforge.net/
http://packages.debian.org/sid/sparc/tcpreplay
http://tcpreplay.synfin.net/wiki/Download#Source
http://tcpreplay.synfin.net/
以上のサイトでは、説明やソースのダウンロードができますが、すべて英語です.
2、ここで主にtcpreplayのソースコードを見ます
tcpreplayのソースコードは/tcpreplay-3.4.4/srcの下にあります
(1)使用した送信パケットの関数をsend_にカプセル化する.packets.cファイルの下のsend_packets(pcap,file_idx)関数では、
(2)send_packets(pcap,file_idx)の送信関数はsendpackにカプセル化する.c(/tcpreplay-3.4/src/common)ファイルのsendpacket(sendpacket_t*sp,const u_char*data,size_t len)関数に、.
(3)
sendpack()の送信関数はsend()またはwriteにカプセル化され、
#ifdef HAVE_PF_PACKET
#undef INJECT_METHOD
#define INJECT_METHOD "PF_PACKET send()"
#if defined HAVE_BPF && ! defined INJECT_METHOD
#undef INJECT_METHOD
#define INJECT_METHOD "bpf send()"
245 #elif defined HAVE_BPF
246 retcode = write(sp->handle.fd, (void *)data, len);
---------------------------------------eth_send()------------------------------------
267 #elif defined HAVE_LIBDNET
268 retcode = eth_send(sp->handle.ldnet, (void*)data, (size_t)len);
(4),send()と
write():sendto()をカプセル化した関数で、connectが接続決定インタフェースを確立してからのみ使用できます.
struct sendpacket_s {
tcpr_dir_t cache_dir;
int open;
char device[20];
char errbuf[SENDPACKET_ERRBUF_SIZE];
COUNTER retry_enobufs;
COUNTER retry_eagain;
COUNTER failed;
COUNTER sent;
COUNTER bytes_sent;
COUNTER attempt;
enum sendpacket_type_t handle_type;
union sendpacket_handle handle;
struct tcpr_ether_addr ether;
#ifdef HAVE_PF_PACKET
struct sockaddr_ll sa;
#endif
};
union sendpacket_handle {
pcap_t *pcap;
int fd;
#ifdef HAVE_LIBDNET
eth_t *ldnet;
#endif
};
struct pcap [pcap-int.h]
{
int fd;/* ファイル記述語、実際にはsocket*/
/*socketではselect()やpoll()などのI/O多重型関数を使用できます*/
int selectable_fd;
int snapshot;/* ユーザが望む取得パケットの最大長*/
int linktype;/* デバイスタイプ*/
int tzoff;/*タイムゾーン位置は、実際には使用されていません*/
int offset;/*境界位置合わせオフセット*/
int break_loop;/* 強制的にリードパケットサイクルから飛び出したフラグ*/
struct pcap_sf sf;/* パッケージをファイルに保存する関連構成データ構造*/
struct pcap_md md;/* 具体的には以下の*/
int bufsize;/* リードバッファの長さ*/
u_char buffer;/* リードバッファポインタ*/
u_char *bp;
int cc;
u_char *pkt;
/*関連抽象操作の関数ポインタ、最終的に特定のオペレーティングシステムの処理関数*/
int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *);
int (*setfilter_op)(pcap_t *, struct bpf_program *);
int (*set_datalink_op)(pcap_t *, int);
int (*getnonblock_op)(pcap_t *, char *);
int (*setnonblock_op)(pcap_t *, int, char *);
int (*stats_op)(pcap_t *, struct pcap_stat *);
void (*close_op)(pcap_t *);
/*BPFフィルタコードがカーネルで実行できない場合は、それを保存してユーザ空間で実行*/
struct bpf_program fcode;
/*関数呼び出しエラー情報バッファ*/
char errbuf[PCAP_ERRBUF_SIZE + 1];
/*現在のデバイスでサポートされている変更可能なデータリンクタイプの数*/
int dlt_count;
/*変更可能なデータリンクタイプ番号チェーンテーブル、linuxでは使用されていません*/
int *dlt_list;
/*パケットのヘッダをカスタマイズし、パケットの取得時間、取得長さ、実際の長さについて説明する[pcap.h]*/
struct pcap_pkthdr pcap_header;
};
完全なpcap構造体コード.
245 struct pcap {
246 #ifdef WIN32
247 ADAPTER *adapter;
248 LPPACKET Packet;
249 int nonblock;
250 #else
251 int fd;
252 int selectable_fd;
253 int send_fd;
254 #endif /* WIN32 */
255
256 #ifdef HAVE_LIBDLPI
257 dlpi_handle_t dlpi_hd;
258 #endif
259 int snapshot;
260 int linktype; /* Network linktype */
261 int linktype_ext; /* Extended information stored in the linktype field of a file */
262 int tzoff; /* timezone offset */
263 int offset; /* offset for proper alignment */
264 int activated; /* true if the capture is really started */
265 int oldstyle; /* if we're opening with pcap_open_live() */
266
267 int break_loop; /* flag set to force break from packet-reading loop */
268
269 #ifdef PCAP_FDDIPAD
270 int fddipad;
271 #endif
272
273 #ifdef MSDOS
274 void (*wait_proc)(void); /* call proc while waiting */
275 #endif
276
277 struct pcap_sf sf;
278 struct pcap_md md;
279 struct pcap_opt opt;
280
281 /*
282 * Read buffer.
283 */
284 int bufsize;
285 u_char *buffer;
286 u_char *bp;
287 int cc;
288
289 /*
290 * Place holder for pcap_next().
291 */
292 u_char *pkt;
293
294 /* We're accepting only packets in this direction/these directions. */
295 pcap_direction_t direction;
296
297 /*
298 * Methods.
299 */
300 activate_op_t activate_op;
301 can_set_rfmon_op_t can_set_rfmon_op;
302 read_op_t read_op;
303 inject_op_t inject_op;
304 setfilter_op_t setfilter_op;
305 setdirection_op_t setdirection_op;
306 set_datalink_op_t set_datalink_op;
307 getnonblock_op_t getnonblock_op;
308 setnonblock_op_t setnonblock_op;
309 stats_op_t stats_op;
310
311 /*
312 * Routine to use as callback for pcap_next()/pcap_next_ex().
313 */
314 pcap_handler oneshot_callback;
315
316 #ifdef WIN32
317 /*
318 * These are, at least currently, specific to the Win32 NPF
319 * driver.
320 */
321 setbuff_op_t setbuff_op;
322 setmode_op_t setmode_op;
323 setmintocopy_op_t setmintocopy_op;
324 #endif
325 cleanup_op_t cleanup_op;
326
327 /*
328 * Placeholder for filter code if bpf not in kernel.
329 */
330 struct bpf_program fcode;
331
332 char errbuf[PCAP_ERRBUF_SIZE + 1];
333 int dlt_count;
334 u_int *dlt_list;
335 int tstamp_type_count;
336 u_int *tstamp_type_list;
337
338 struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
339 };