一:前言:
tcpreplay的作者在写sendpacket()函数时说:希望写一个通用的数据包发送api接口支持BPF, libpcap, libdnet, and Linux's PF_PACKET,因为libnet缺乏活动性,libpcap支持模块比较新,并且缺乏非linux支持,所以作者决定同时支持这四个,他们的匹配顺序如下,如果平台支持其中最先匹配的函数,就使用它发包。由于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,一个小型的接口函数库,建立一个简单统一的网络编程接口以屏蔽不同操作系统低层网络编程的差别,libnet目前可以在Linux、FreeBSD、Solaris、WindowsNT等操作系统上运行,并且提供了统一的接口
(4) libpcap:一个网络捕获数据包的开放源码,被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.4/src/common)文件中的sendpacket(sendpacket_t *sp, const u_char *data, size_t len)函数里,。
struct pcap [pcap-int.h]
{};
完整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 };