Chinaunix首页 | 论坛 | 博客
  • 博客访问: 73338
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 189
  • 用 户 组: 普通用户
  • 注册时间: 2015-08-24 20:56
文章分类

全部博文(21)

文章存档

2016年(1)

2015年(20)

我的朋友

分类: LINUX

2015-10-29 21:49:05

struct bpf_program fcode;  /*存放已经编译好的过滤表达式*/


获取网络接口(网卡)后,我们需要打开它:

pcap_t * pcap_open_live(const char * device, int snaplen, int promisc, int to_ms, char * errbuf)

功能:获得数据包捕获描述字

上面这个函数会返回指定接口的pcap_t类型指针,后面的所有操作都要使用这个指针。
第一个参数是获取的网络接口字符串,可以直接使用硬编码。
第二个参数是对于每个数据包,从开头要抓多少个字节,我们可以设置这个值来只抓每个数据包的头部,而不关心具体的内容。典型的以太网帧长度是1518字节,但其他的某些协议的数据包会更长一点,但任何一个协议的一个数据包长度都必然小于65535个字节。
第三个参数指定是否打开混杂模式(Promiscuous Mode),0表示非混杂模式,任何其他值表示混合模式。如果要打开混杂模式,那么网卡必须也要打开混杂模式,可以使用如下的命令打开eth0混杂模式:
ifconfig eth0 promisc
第四个参数指定需要等待的毫秒数,超过这个数值后,第3步获取数据包的这几个函数就会立即返回。0表示一直等待直到有数据包到来。

第五个参数是存放出错信息的数组。


struct ifreq 这个结构定义在/usr/include/net/if.h


GetMacFromDevice函数下的htons(0x0806)是指ARP协议。


IFNAMSIZ = IF_NAMESIZE = 16.


ioctl选项SIOCGIFHWADDR是获取MAC地址,SIOCGIFADDR是获取网卡IP地址。


pcap_compile()函数用于将用户制定的过滤策略编译到过滤程序中。
int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)
p:表示pcap会话句柄;
fp:存放编译以后的规则;
str:规则表达式格式的过滤规则(filter),同tcpdump中的filter;
optimize:制定优化选项:0 false, true;// 0表示以混杂模式监听所有符合过滤规则的数据包
netmask:监听接口的网络掩码;
返回值:-1表示操作失败,其他值表成功。
int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
 p:表示pcap的会话句柄;
 fp:表示经过编译后的过滤规则;
 返回值:-1表示操作失败,其他值表成功。
pcap_setfilter()函数用于应用过滤器。



pcap_next_ex(pcap_t* p,struct pcap_pkthdr** pkt_header,const u_char** pkt_data)

功能: 从interface或离线记录文件获取一个报文

参数: p: 已打开的捕捉实例的描述符

         pkt_header: 报文头

         pkt_data: 报文内容

返回值: 1: 成功

             0: 获取报文超时

             -1: 发生错误

             -2: 获取到离线记录文件的最后一个报文


Base64字符的最小单位是四个字符一组(也就是三个字节)

Base64编码:

static
void FillBase64Area(char area[])
{
	uint8_t version[20];
	const char Tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
			   "abcdefghijklmnopqrstuvwxyz"
			   "0123456789+/"; // 标准的Base64字符映射表
	uint8_t	c1,c2,c3;
	int	i, j;

	// 首先生成20字节加密过的H3C版本号信息
	FillClientVersionArea(version);

	// 然后按照Base64编码法将前面生成的20字节数据转换为28字节ASCII字符
	i = 0;
	j = 0;
	while (j < 24)
	{
		c1 = version[i++];
		c2 = version[i++];
		c3 = version[i++];
 
		// 第一个6位只需要让8位二进制右移两位
area[j++] = Tbl[ (c1&0xfc)>>2 ];
 
		// 第二个6位 = 第一个8位的后两位 + 第二个8位的前4位
area[j++] = Tbl[((c1&0x03)<<4)|((c2&0xf0)>>4) ];
 
 		// 第三个6位 = 第二个8位的后4位 + 第三个8位的前2位
area[j++] = Tbl[ ((c2&0x0f)<<2)|((c3&0xc0)>>6)];
 
                // 第4个6位 = 第三个8位的后6位
area[j++] = Tbl[ c3&0x3f ]; } c1 = version[i++]; c2 = version[i++]; area[24] = Tbl[ (c1&0xfc)>>2 ]; area[25] = Tbl[((c1&0x03)<<4)|((c2&0xf0)>>4)];
 
	// 需补两个6位,一个是最后一个8位的后4位补两个0,另一个对应异常的“=”
area[26] = Tbl[ ((c2&0x0f)<<2)];
 area[27] = '=';
} 


pcap_sendpacket()发送单个数据包函数原型: int pcap_sendpacket ( pcap_t * p, u_char * buf, int size ) 说明:该函数可以发送一个原始数据包到网络上。buf包含要发送到网络上的数据包的数据(包括协议头)。注意,MAC CRC不用包含,因为它是网卡驱动计算然后添加的。返回值为0说明数据包已经成功的发送了,否则返回-1。


感谢以下参考源:

http://blog.csdn.net/htttw/article/details/7521053

http://blog.csdn.net/headmaster110/article/details/7601296

http://www.cnblogs.com/hongru/archive/2012/01/14/2321397.html

http://blog.chinaunix.net/uid-502148-id-2392462.html

http://blog.sina.com.cn/s/blog_6cb117430100lz7q.html

阅读(1130) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~