⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 catch.c

📁 自己编的linux下的网络监控程序源码
💻 C
字号:
//catch.c
//使用方法:catch〈网络接口名〉 > 〈输出文件名〉
//例如:catch etho > temp.txt
//结束方法:ctrl+c
//程序开始,读入头文件



#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/in_systm.h>
#include<netinet/ip.h>
#include<netinet/tcp.h>
#include<netinet/udp.h>
#include<netinet/if_ether.h>
#include<pcap.h> //pcap程序库
#include<netdb.h> //DNS检索使用 

#define MAXSTRINGSIZE 256 //字符串长度
#define MAXSIZE 1024 //主机高速缓存中的最大记录条数
#define DEFAULT_SNAPLEN 68 //数据包数据的长度


int packet_num;

typedef struct
{
unsigned long int ipaddr; //IP地址
char hostname[MAXSTRINGSIZE]; //主机名
}dnstable; //高速缓存数据结构

typedef struct 
{
dnstable table[MAXSIZE];
int front;
int rear;
}sequeue; 

sequeue * sq; //定义缓存队列


//选择网络设备
pcap_if_t * select_netdrv()
{
	pcap_if_t * alldevs;
  pcap_if_t * d;
  int inum;
  int i=0;
  pcap_t * adhandle;
  char errbuf[PCAP_ERRBUF_SIZE];  //错误信息缓冲区
  
  //取得网络设备列表
  if(pcap_findalldevs(&alldevs,errbuf)==-1)
  {
    fprintf(stderr,"Error in pcap_findalldevs:%s\n",errbuf);
    exit(1);
  }
  
  //显示网络设备列表
  for(d=alldevs;d;d=d->next)
  {
    printf("%d. %s",++i,d->name);
    if(d->description)
      printf("(%s)\n",d->description);
    else
      printf("(No description available)\n");
  }
  if(i==0)
  {
    printf("\nNo interfaces found! Make sure MinPcap is installed.\n");
    exit(1);
  }
  
  //选择网络设备
  printf("Enter the interface number(1-%d):",i);
  scanf("%d",&inum);
  if(inum<1||inum>i)
  {
    printf("\nInterface number out of range.\n");
    //释放设备列表
    pcap_freealldevs(alldevs);
    exit(1);
  }
  //跳转到已选择的网络适配器
  for(d=alldevs,i=0;i<inum-1;d=d->next,i++);
  return (d);
}
//输出MAC地址函数
void print_hwadd(u_char * hwadd)
{
	int i;
  for(i=0;i<5;++i)
  printf("%2x:",hwadd[i]);
  printf("%2x",hwadd[i]);
}


//输出IP地址的函数
void print_ipadd(u_char *ipadd)
{
	int i;
  for(i=0;i<3;++i)
  printf("%d.",ipadd[i]);
  printf("%d",ipadd[i]);
}


//查询端口函数
void getportname(int portno,char portna[],char* proto)
{
if(getservbyport(htons(portno),proto)!=NULL)
{
strcpy(portna,getservbyport(htons(portno),proto)->s_name);
}
else
sprintf(portna,"%d",portno);
}


/*
//将IP转化为DNS名
void iptohost(unsigned long int ipad,char* hostn)
{
struct hostent * shostname;
int m,n,i;
m=sq->rear;
n=sq->front;
for(i=n%MAXSIZE;i=m%MAXSIZE;i=(++n)%MAXSIZE)
{
//检查IP是否第一次出现
if(sq->table[i].ipaddr==ipad)
{
strcpy(hostn,sq->table[i].hostname);
break;
}
}
if(i=m%MAXSIZE)
{//不存在则从域名服务器查询并把结果放入高速缓存
if((sq->rear+1)%MAXSIZE==sq->front) //判队满
sq->front=(sq->front+1)%MAXSIZE; //出队列
sq->table[i].ipaddr=ipad;
shostname=gethostbyaddr((char*)&ipad,sizeof(ipad),AF_INET);
if(shostname!=NULL)
strcpy(sq->table[i].hostname,shostname->h_name);
else
strcpy(sq->table[i].hostname,"");
sq->rear=(sq->rear+1)%MAXSIZE;
}
}
*/


void print_hostname(u_char* ipadd)
{
unsigned long int ipad;
char hostn[MAXSTRINGSIZE];
ipad=*((unsigned long int *)ipadd);
/*
iptohost(ipad,hostn);
if(strlen(hostn)>0)
printf("%s",hostn);
else
*/
print_ipadd(ipadd);
}



//处理数据包的函数
void packet_proce(u_char* packets,const struct pcap_pkthdr * header,const u_char *pp)
{
struct ether_header * eth; //以太网帧报头指针
struct ether_arp * arph; //ARP报头
struct ip * iph; //IP报头
struct tcphdr * tcph;//TCP报头
struct udphdr * udph;//UDP报头
u_short srcport,dstport; //端口号
char protocol[MAXSTRINGSIZE]; //协议类型名
char srcp[MAXSTRINGSIZE],dstp[MAXSTRINGSIZE]; //端口名
unsigned int ptype; //协议类型变量
u_char * data; //数据包数据指针
u_char tcpudpdata[MAXSTRINGSIZE]; //数据包数据
int i;
time_t timep;

time(&timep);//取得当前时间
packet_num++;

eth=(struct ether_header *)pp;
ptype=ntohs(((struct ether_header *)pp)->ether_type);

if((ptype==ETHERTYPE_ARP)||(ptype==ETHERTYPE_REVARP))//ARP或RARP数据包
{
arph=(struct ether_arp *)(pp+sizeof(struct ether_header));
if(ptype==ETHERTYPE_ARP)
printf("arp ");
else
printf("rarp "); //输出协议类型
print_hwadd((u_char *)&(arph->arp_sha));
printf("(");
print_hostname((u_char *)&(arph->arp_spa));
printf(")\n->");
print_hwadd((u_char *)&(arph->arp_tha));
printf("(");
print_hostname((u_char *)&(arph->arp_tpa));
printf(")\n\tpacketlen:%d",header->len);
}
else if(ptype==ETHERTYPE_IP) //IP数据报
{
iph=(struct ip *)(pp+sizeof(struct ether_header));
if(iph->ip_p==1) //ICMP报文
{
strcpy(protocol,"icmp");
srcport=dstport=0;
}
else if(iph->ip_p==6) //TCP报文
{
strcpy(protocol,"tcp");
tcph=(struct tcphdr *)(pp+sizeof(struct ether_header)+4*iph->ip_hl);
srcport=ntohs(tcph->source);
dstport=ntohs(tcph->dest);
data=(u_char *)(pp+sizeof(struct ether_header)+4*iph->ip_hl+4*tcph->doff);
for(i=0;i<MAXSTRINGSIZE-1;++i)
{
if(i>=header->len-sizeof(struct ether_header)-4*iph->ip_hl-4*tcph->doff)
break;
//else
tcpudpdata[i]=data[i];
}
} //TCP数据处理完毕
else if(iph->ip_p=17) //UDP报文
{
strcpy(protocol,"udp");
udph=(struct udphdr *)(pp+sizeof(struct ether_header)+4*iph->ip_hl);
srcport=ntohs(udph->source);
dstport=ntohs(udph->dest);
data=(u_char *)(pp+sizeof(struct ether_header)+4*iph->ip_hl+8);
for(i=0;i<MAXSTRINGSIZE-1;++i)
{
if(i>=header->len-sizeof(struct ether_header)-4*iph->ip_hl-8)
break;
else
tcpudpdata[i]=data[i];
}
}
tcpudpdata[i]='\0';
getportname(srcport,srcp,protocol);
getportname(dstport,dstp,protocol);


//-------输出部分-----
//printf("ip ");
printf("\n\n--------------------Packet %d --------------------------\n",packet_num);
printf("captured at %s ",ctime(&timep));
print_hwadd(eth->ether_shost);
printf("(");
print_hostname((u_char *)&(iph->ip_src));
printf(")[%s:%s]->\n",protocol,srcp);
print_hwadd(eth->ether_dhost);
printf("(");
print_hostname((u_char *)&(iph->ip_dst));
printf(")[%s:%s]\n",protocol,dstp);
printf("ttl:%d packetlen:%d",iph->ip_ttl,header->len);
printf("\n%s\n",tcpudpdata);
printf("--------------------endpacket--------------------------");
}
printf("\n");
}




//Main函数取数据包并初始化程序环境
int main(int argc,char ** argv)
{
	//sq->rear=-1;
  //sq->front=-1; //初始化队列
  pcap_if_t * net_drv;
  char ebuf[PCAP_ERRBUF_SIZE];
  struct pcap * pd;
  //设置PCAP程序库
  net_drv=select_netdrv();
  if((pd=pcap_open_live(net_drv->name,DEFAULT_SNAPLEN,1,1000,ebuf))==NULL)
  {
    (void)fprintf(stderr,"%s",ebuf);
    exit(1);
  }
  //循环取数据包
  //改变参数-1为其它值,可确定取数据包的个数,这里为无限个
  if(pcap_loop(pd,-1,packet_proce,NULL)<0)
  {
    (void)fprintf(stderr,"pcap_loop:%s\n",pcap_geterr(pd));
    exit(1);
  }
  pcap_close(pd);
  exit(0);
}
//程序结束

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -