📄 mprobe_pbuffer.c
字号:
/*
文件名:mprobe_pbuffer.c
*/
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
//#include "packet_memory.h"
#include "inet.h"
#include "mprobe_pbuffer.h"
#include "inet.h"
#include "probe_main.h"
//extern packet_array * __packet_buffer ;
extern u_int32_t print_num;
/* 缺省的缓冲区大小 */
#ifndef MPROBE_PBUFFER_DEFAULT_CAPACITY
#define MPROBE_PBUFFER_DEFAULT_CAPACITY 2*KB
#endif /* #ifndef MPROBE_PBUFFER_DEFAULT_CAPACITY */
/*****************************************************************************/
/*
_pbuffer_packet_validate - 检查数据的合法性并购造packet_t结构
->@const uint8_t * packet : 采集到的数据封包
->@uint16_t len : 采集到的数据封包的长度
->@time_t tm : 数据封包采集时间
<->@unsigned char *validate : 是否是因为数据报损坏而无法构造packet_t,是返回1
!packet_t * : 构造成功的packet_t结构指针,构造失败或者采集到的数据封包
不符合要求,将返回NULL
*/
packet_t *
_pbuffer_packet_validate(const uint8_t * packet , uint16_t len ,
time_t tm , unsigned char * validate) ;
/*
_pbuffer_flush_cache - 将一个队列的数据加入至另外一个队列
->@packets_t * target_cache : 被加入的队列
->@packets_t * source_cache : 加入的队列,该队列将被清空
!void
*/
void
_pbuffer_flush_cache(packets_t * target_cache , packets_t * source_cache) ;
/*
_pbuffer_insert_packet - 将packet_t放入缓冲队列
->@pbuffer_t * pbuffer : 数据封包缓冲区
->@packet_t * packet : 用于存放数据封包的结构
!int : 放入成功,返回0,否则返回-1
*/
int
_pbuffer_insert_packet(pbuffer_t * pbuffer , packet_t * packet) ;
/*
_pbuffer_destroy_queue - 释放缓存数据封包队列
->@packets_t * packets : 数据封包队列
!void :
*/
void
_pbuffer_destroy_queue(packets_t * packets) ;
/*****************************************************************************/
/*
pbuffer_open - 打开缓冲区
->@unsigned long capacity : 缓冲区的容量
!pbuffer_t * : 缓冲区句柄
*/
void *
pbuffer_open(unsigned long capacity)
{
pbuffer_t * pbuffer = NULL ;
if(capacity < MPROBE_PBUFFER_DEFAULT_CAPACITY)
capacity = MPROBE_PBUFFER_DEFAULT_CAPACITY;
pbuffer = malloc(sizeof(pbuffer_t)) ;
if(pbuffer == NULL){
return pbuffer ;
}
bzero(pbuffer , sizeof(pbuffer_t)) ;
pbuffer->max_memory = capacity ;
pbuffer->full_memory = 0 ;
pthread_mutex_init(&(pbuffer->mutex) , NULL) ;
pthread_cond_init(&(pbuffer->cond_full) , NULL) ;
pthread_cond_init(&(pbuffer->cond_empty) , NULL) ;
TAILQ_INIT(&(pbuffer->buffer)) ;
TAILQ_INIT(&(pbuffer->cache)) ;
TAILQ_INIT(&(pbuffer->prefetch)) ;
return pbuffer ;
}
/*
pbuffer_close - 关闭缓冲区
->@void * pbuffer : 缓冲区句柄
!void
*/
void
pbuffer_close(void * pbuffer)
{
pbuffer_t * tmp = (pbuffer_t *)pbuffer ;
if(!tmp)
return;
/* 释放缓存队列 */
pthread_mutex_lock(&(tmp->mutex)) ;
_pbuffer_destroy_queue(&(tmp->buffer)) ;
_pbuffer_destroy_queue(&(tmp->prefetch)) ;
_pbuffer_destroy_queue(&(tmp->cache)) ;
tmp->cache_memory = 0 ;
tmp->use_memory = 0 ;
tmp->prefetch_memory = 0 ;
pthread_mutex_unlock(&(tmp->mutex)) ;
pthread_mutex_destroy(&(tmp->mutex)) ;
pthread_cond_destroy(&(tmp->cond_empty)) ;
pthread_cond_destroy(&(tmp->cond_full)) ;
free(tmp) ;
return;
}
/*
pbuffer_insert_packet - 将待分析的数据封包放入缓冲区
->@pbuffer_t * pbuffer : 缓冲区句柄
->@const uint8_t * packet : 数据封包
->@uint16_t len : 数据封包长度
->@time_t tm : 数据封包捕获时间
!int : 放入成功,返回0,否则返回-1
*/
int
pbuffer_insert_packet(void * pbuffer , const uint8_t * packet , uint16_t len , time_t tm)
{
packet_t * p = NULL ;
pbuffer_t * buffer = (pbuffer_t *)pbuffer ;
unsigned char validate = 0 ;
if(!pbuffer || !packet || !len){
return -1 ;
}
p = _pbuffer_packet_validate(packet , len , tm , &validate) ;
if(p == NULL){
if(validate == 0){/* 已经没有空间可以供分配了 */
((pbuffer_t *)pbuffer)->full_memory = 1 ;/* 告诉取用数据封包的线程,系统没有空间分配了 */
pthread_cond_broadcast(&(((pbuffer_t *)pbuffer)->cond_full)) ;
struct timespec tm ;
bzero(&tm , sizeof(struct timespec)) ;
tm.tv_nsec = 40000 ;
nanosleep(&tm , NULL) ;
return -1 ;
}else{
return -1 ;
}
}
return _pbuffer_insert_packet(buffer , p) ;
}
/*
pbuffer_get_packet - 从缓冲区中取得采集到的待分析的数据封包
->@pbuffer_t * pbuffer : 缓冲区句柄
!packet_t * : 取得的数据包
*/
packet_t *
pbuffer_get_packet(void * pbuffer)
{
pbuffer_t * buffer = (pbuffer_t *)pbuffer ;
packet_t * tmp = NULL ;
assert(pbuffer) ;
if(buffer->prefetch_memory != 0){/* 预取队列有数据,先从这里取 */
assert((buffer->prefetch).tqh_first != NULL) ;
if(buffer->full_memory == 1){/*??*/
fprintf(stdout , "pbuffer delete all session nodes\n") ;
buffer->full_memory = 0 ;
}
tmp = (buffer->prefetch).tqh_first ;
TAILQ_REMOVE(&(buffer->prefetch) , tmp , _list) ;
buffer->prefetch_memory -= tmp->size ;
assert(buffer->prefetch_memory >= 0) ;
return tmp ;
}
/* 预取队列空了,从缓冲区中取出数据 */
pthread_mutex_lock(&(buffer->mutex)) ;
assert(buffer->prefetch_memory == 0) ;
while((buffer->buffer).tqh_first == NULL){
if(buffer->full_memory == 1){/* ?? */
fprintf(stdout , "pbuffer delete all session nodes\n") ;
buffer->full_memory = 0 ;
}
pthread_cond_wait(&(buffer->cond_full) , &(buffer->mutex)) ;
}
_pbuffer_flush_cache(&(buffer->prefetch) , &(buffer->buffer)) ;
buffer->prefetch_memory = buffer->use_memory ;
buffer->use_memory = 0 ;
pthread_mutex_unlock(&(buffer->mutex)) ;
pthread_cond_broadcast(&(buffer->cond_empty)) ;
tmp = (buffer->prefetch).tqh_first ;
assert(tmp) ;
TAILQ_REMOVE(&(buffer->prefetch) , tmp , _list) ;
buffer->prefetch_memory -= tmp->size ;
return tmp ;
}
/*****************************************************************************/
/*
_pbuffer_packet_validate - 检查数据的合法性并购造packet_t结构
->@const uint8_t * packet : 采集到的数据封包
->@uint16_t len : 采集到的数据封包的长度
->@time_t tm : 数据封包采集时间
<->@unsigned char *validate : 是否是因为数据报损坏而无法构造packet_t,是返回1
!packet_t * : 构造成功的packet_t结构指针,构造失败或者采集到的数据封包
不符合要求,将返回NULL
*/
packet_t *
_pbuffer_packet_validate(const u_int8_t * packet , u_int16_t len ,
time_t tm , unsigned char * validate)
{
packet_t * p = NULL ;
u_int8_t * ip_packet = NULL ;
u_int8_t * t_packet = NULL ;
u_int16_t t_len = 0 ;
assert(validate) ;
if(!packet || !len){
*validate = 1 ;
return p ;
}
if ( len > 1536)
{
printf("packet too big len = %d\n", len);
*validate = 1 ;
return p;
}
/*
if(len < sizeof(struct ether_header) || !ETHER_TYPE_IP(packet))
return p ;
if(len < sizeof(struct ether_header) + sizeof(struct ip))
return p ;
if(sizeof(struct ether_header) + IP_TOTAL_LEN(ip_packet) != len)
return p ;
*/
if ( ETHER_TYPE_IP(packet))
{
ip_packet = IP_PACKET(packet) ;
}else if(ETHER_TYPE_8021Q(packet))
{
if(E8021Q_TYPE_IP( E8021Q_PACKET(packet)) )
ip_packet = E8021Q_PACKET(packet) + 4;/* 4 是 802.1q 的头长 */
else
{
*validate = 1 ;
return p;
}
}else
{
*validate = 1 ;
return p;
}
if(!IP_FRAG_NO(ip_packet)){
*validate = 1 ;
return p ;
}
/* 对传输层协议进行判断 */
if(IP_PROTO_TCP(ip_packet)){/* TCP数据 */
struct ether_header * eth = (struct ether_header *)packet ;
t_packet = ip_packet + IP_HDR_LEN(ip_packet) ;
t_len = IP_TOTAL_LEN(ip_packet) - IP_HDR_LEN(ip_packet) ;
if ( t_len > 1500 - 20 || t_len < 20)
{
// printf("tcp packet len error len = %d\n", t_len);
// int i;
// for(i=0;i<len;i++)
// printf("%02x-",packet[i]);
// printf("\n");
printf("IP_TOTAL_LEN = %d IP_HDR_LEN = %d\n",IP_TOTAL_LEN(ip_packet), IP_HDR_LEN(ip_packet));
*validate = 1 ;
return p;
}
u_int32_t tcp_hdr_len;
tcp_hdr_len = TCP_HDR_LEN(t_packet);
if ( tcp_hdr_len < 20)
{
// printf("tcp_hdr_len error len is %d\n",tcp_hdr_len);
*validate = 1 ;
return p;
}
p = malloc( t_len * sizeof(u_int8_t) + sizeof(packet_t)) ;
if(p == NULL){
fprintf(stdout , "malloc memory failed\n") ;
*validate = 0 ;
return p ;
}
memcpy(p->s_mac , eth->ether_shost , ETH_ALEN) ;
memcpy(p->d_mac , eth->ether_dhost , ETH_ALEN) ;
p->size = t_len * sizeof(u_int8_t) + sizeof(packet_t) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -