一个简单的抓包程序&代码(linux)
(2013-02-27 11:09:30)
标签:
it抓包pcap网络tcpdump |
分类: 软件开发 |
最近测试媒体流的时候,
有时候需要分析抓包,趁着有空研究了一下pcap的文件头和包头,以及。
自己写了一个简单的抓包程序,该程序在抓包同时会打印ip和udp的信息。
写这个是为后续从抓包中提取rtp载荷做准备。当然,如果你没有tcpdump也可以用这个抓包。这里面有很多功能还可以完善比如校验和之类的。
注意这个程序只能用root用户执行。因为只有在root下才能让网卡处于混杂模式抓所有的包
首先是makefile文件,非常简单:
INC_FLAGS:= -I./ -I../
cc:=gcc
mysniffer: ff_sniffer.c ff_tcpip.c
ff_tcpip.h
$(cc) $(INC_FLAGS) ff_sniffer.c ff_tcpip.c
-o mysniffer
其次是头文件 ff_tcpip.h :
#ifndef __FF_TCPIP_H__
#define __FF_TCPIP_H__
typedef int int32;
typedef unsigned int u_int32;
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef struct ip_hdr{//ipv4头部
#ifdef __LITTLE_ENDIAN_BITFIELD
u_char ip_length:4,
#else
u_char ip_version:4,
#endif
u_char ip_tos;
u_short ip_total_length;
u_short ip_id;
u_short ip_flags;
u_char ip_ttl;
u_char ip_protocol;
u_short ip_cksum;
u_int32 ip_source;
u_int32 ip_dest;
}__attribute__((packed)) IP_HDR;
//注意__attribute__((packed))很重要,
它保证了结构体里面的元素存储位置不会被优化
typedef struct udp_hdr{//udp头部
u_short s_port;
u_short d_port;
u_short length;
u_short cksum;
}__attribute__((packed)) UDP_HDR;
typedef struct psd_header{//伪头部,用于计算校验和
u_int32 s_ip;//source ip
u_int32 d_ip;//dest ip
u_char mbz;//0
u_char proto;//proto type
u_short plen;//length
}__attribute__((packed)) PSD_HEADER;
typedef struct _MAC_FRAME_HEADER{
char m_cDstMacAddress[6]; //目的mac地址
char m_cSrcMacAddress[6]; //源mac地址
short m_cType;
//上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp
}__attribute__((packed)) MAC_FRAME_HDR;
typedef struct pcap_file_header {
u_int32 magic;
u_short version_major;
u_short version_minor;
int32 thiszone;
u_int32 sigfigs;
u_int32 snaplen;
u_int32 linktype;
}__attribute__((packed)) PCAP_FILE_HDR;
typedef struct pcap_pkthdr {
u_int32 iTimeSecond;
u_int32 iTimeSS;
u_int32 caplen;
u_int32 len;
}__attribute__((packed)) PCAP_PKT_HDR;
unsigned short checksum(unsigned short* buffer, int
size);
void ip_analyze_pkt(void *buffer, int size);
void ip_ass_pcap_filehead(PCAP_FILE_HDR *pcap_file_hdr);
void ip_ass_pcap_pkthead(PCAP_PKT_HDR *pcap_pkt_hdr, int
size);
#endif
然后是tcpip的核心程序:
ff_tcpip.c
#include "ff_tcpip.h"
#include <stdio.h>
#include <string.h>
#include <linux/in.h>
#include <sys/time.h>
#ifdef ANDROID_LOG
#include <android/log.h>
#define LOGI(format,...)
//__android_log_print(ANDROID_LOG_INFO
,"hello_hl","file[%s] line[%d] "format"",__FILE__, __LINE__
,##__VA_ARGS__)
#define LOGE(format,...)
__android_log_print(ANDROID_LOG_ERROR,"hello_hl","file[%s]
line[%d] "format"",__FILE__, __LINE__ ,##__VA_ARGS__)
#else
#define LOGI(format,...) printf("file[%s]
line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__)
#define LOGE(format,...) printf("file[%s]
line[%d] "format"\n",__FILE__, __LINE__ ,##__VA_ARGS__)
#endif
unsigned short checksum(unsigned short* buffer, int
size)//校验和
{
}
void ip_analyze_pkt(void *buffer, int size){
UDP_HDR *udp_hdr;
IP_HDR *ip_hdr;
MAC_FRAME_HDR *mac_hdr;
char *p,*q;
int n=0xFF,proto;
mac_hdr = buffer;
ip_hdr = buffer + sizeof(MAC_FRAME_HDR);
udp_hdr = buffer + sizeof(MAC_FRAME_HDR) +
sizeof(IP_HDR);
p = mac_hdr->m_cSrcMacAddress;
q = mac_hdr->m_cDstMacAddress;
LOGI("MAC: %.2X:X:X:X:X:X==>"
q[0]&n, q[1]&n,
q[2]&n,q[3]&n,
q[4]&n, q[5]&n);
p =
(char*)&ip_hdr->ip_source;
q =
(char*)&ip_hdr->ip_dest;
LOGI("IP: %d.%d.%d.%d => %d.%d.%d.%d",
}
void ip_ass_pcap_pkthead(PCAP_PKT_HDR *pcap_pkt_hdr, int
size){
struct timeval ts;
gettimeofday(&ts,NULL);
pcap_pkt_hdr->iTimeSS = ts.tv_usec;
pcap_pkt_hdr->iTimeSecond = ts.tv_sec;
pcap_pkt_hdr->caplen = size;
pcap_pkt_hdr->len = size;
}
void ip_ass_pcap_filehead(PCAP_FILE_HDR *pcap_file_hdr){
pcap_file_hdr->magic = 0xa1b2c3d4;
pcap_file_hdr->version_major = 0x02;
pcap_file_hdr->version_minor = 0x04;
pcap_file_hdr->thiszone = 0x00;
pcap_file_hdr->sigfigs = 0x00;
pcap_file_hdr->snaplen = 0xff;
pcap_file_hdr->linktype = 0x01;
}
主程序ff_sniffer.c :
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include
<linux/if_ether.h>
#include <linux/in.h>
#include <stdlib.h>
#include "ff_tcpip.h"
#define BUFFER_MAX 2048
FILE *File_Save=NULL;
int Sock_Src;
int main(int argc, char *argv[])
{
}
编译完之后,sudo ./mysniffer xxx.cap
即可抓包到xxx.cap中,能用wireshark看。 同时可以再命令行看到ip信息。
正如你看到的,我这个程序只抓前100个包。想抓多少你自己可以修改。
参考文章:
http://blog.csdn.net/yhangleo/article/details/8484597