linux下网络监听与发送数据包的方法(即libpcap、libnet两种类库的使用方法)
2013-03-13 15:13
435 查看
linux下可以用libpcap函数库实现监听数据包,使用libnet 函数库发送数据包 安装: 在命令行下apt-get install 就可以了 libpcap的使用: /* author hjj date 2011-1-21 function:capture packet with the ruler and output the packet information modify 2011-1-23 function:get dns packet */ #include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<pcap.h> #include<netinet/in.h> #include<netinet/tcp.h> #include<string.h> #include<stdlib.h> #include<arpa/inet.h> #define ETHER_ADDR_LEN 6 /*以太网头*/ struct sniff_ethernet { u_char ether_dhost[ETHER_ADDR_LEN]; u_char ether_shost[ETHER_ADDR_LEN]; u_short ether_type; }; /*IP头*/ struct sniff_ip { u_char ip_vhl; u_char ip_tos; u_short ip_len; u_short ip_id; u_short ip_off; #define IP_RF 0x8000 #define IP_DF 0x4000 #define IP_MF 0x2000 #define IP_OFFMASK 0x1fff u_char ip_ttl; u_char ip_p; u_short ip_sum; struct in_addr ip_src,ip_dst; }; /*TCP头*/ typedef u_int tcp_seq; struct sniff_tcp { u_short th_sport; u_short th_dport; tcp_seq th_seq; tcp_seq th_ack; u_char th_offx2; u_char th_flags; u_short th_win; u_short th_sum; u_short th_urp; }; /*UDP报头*/ struct sniff_udp { u_short udp_sport; u_short udp_dport; u_short udp_len; u_short udp_sum; }; /*DNS报头*/ struct sniff_dns { u_short dns_id; u_short dns_flag; u_short dns_ques; u_short dns_ans; u_short dns_auth; u_short dns_add; u_int8_t *dsn_data; }; //数据包到达回调函数 void packetcall(u_char *user,const struct pcap_pkthdr *pcap_head,const u_char *packet); char *ipstr(struct in_addr s_addr); char* getpackettype(u_short packet_type); char* toString(u_long s); //由u_char[6]获取网卡地址字符串 char *getMac(u_char *host); int main(int argc,char **argv) { char *dev,errbuf[PCAP_ERRBUF_SIZE]; pcap_t *handler; struct bpf_program fp; char filter_exp[50]="ip and dst 172.20.92.118"; if(argc==3) { sprintf(filter_exp,"dst %s and dst port %s",argv[1],argv[2]); } if(argc==5) { sprintf(filter_exp,"dst %s and dst port %s or src %s and src port %s",argv[1],argv[2],argv[3],argv[4]); } bpf_u_int32 mask; bpf_u_int32 net; struct pcap_pkthdr header; const u_char *packet; dev=pcap_lookupdev(errbuf); if(dev==NULL) { fprintf(stderr,"could not find default device:%s\n",errbuf); return 2; } printf("device:%s\n",dev); if(pcap_lookupnet(dev,&net,&mask,errbuf)==-1) { fprintf(stderr,"counld not get netmask for device %s;%s\n",dev,errbuf); net=0; mask=0; } handler=pcap_open_live(dev,BUFSIZ,1,10000,errbuf); if(handler==NULL) { fprintf(stderr,"could not open device %s;%s",dev,errbuf); return 2; } if(pcap_compile(handler,&fp,filter_exp,0,net)==-1) { fprintf(stderr,"counld not parse filter %s;%s\n",filter_exp,pcap_geterr(handler)); return 2; } if(pcap_setfilter(handler,&fp)==-1) { fprintf(stderr,"counld not install filter %s;%s\n",filter_exp,pcap_geterr(handler)); return 2; } //捕获数据包 int packetnums=20; packet=pcap_loop(handler,packetnums,packetcall,NULL); pcap_close(handler); return 0; } //数据包到达回调函数 void packetcall(u_char *user,const struct pcap_pkthdr *pcap_head,const u_char *packet) { static int count=1;//数据包计数 struct sniff_ethernet *ethernet;//以太网包头 struct sniff_ip *ip;//ip包头 struct sniff_udp *udp;//udp包头 struct sniff_dns *dns;//dns报头 const u_char *payload;//数据包负载的数据 int pay_size;//数据包负载的数据大小 ethernet=(struct sniff_ethernet*)(packet); ip=(struct sniff_ip*)(packet + sizeof(struct sniff_ethernet)); udp=(struct sniff_udp*)(packet + sizeof(struct sniff_ethernet)+sizeof(struct sniff_ip)); dns=(struct sniff_dns*)(packet + sizeof(struct sniff_ethernet) + sizeof(struct sniff_ip) + sizeof(struct sniff_udp)); payload=(u_char *)(packet+sizeof(struct sniff_ethernet)+sizeof(struct sniff_ip)+sizeof(struct sniff_udp)+sizeof(struct sniff_dns)); pay_size=ntohs(udp->udp_len)-sizeof(struct sniff_udp)-sizeof(struct sniff_dns); printf("-------------数据包:%d\n",count); printf("数据包类型:%s\n",getpackettype(ethernet->ether_type)); printf("源地址:%X:%X:%X:%X:%X:%X\n", (ethernet->ether_shost)[0], (ethernet->ether_shost)[1], (ethernet->ether_shost)[2], (ethernet->ether_shost)[3], (ethernet->ether_shost)[4], (ethernet->ether_shost)[5]); printf("目的地址:%X:%X:%X:%X:%X:%X\n", (ethernet->ether_dhost)[0], (ethernet->ether_dhost)[1], (ethernet->ether_dhost)[2], (ethernet->ether_dhost)[3], (ethernet->ether_dhost)[4], (ethernet->ether_dhost)[5]); printf("From:%s\n",inet_ntoa(ip->ip_src)); printf("To:%s\n",inet_ntoa(ip->ip_dst)); printf("源端口:%d\n",ntohs(udp->udp_sport)); printf("目的端口:%d\n",ntohs(udp->udp_dport)); printf("DNS查询问题数%d\n",ntohs(dns->dns_ques)); if(pay_size>0) { printf("Payload data size %d\n",pay_size); const u_char *ch=payload; int i,j; for(i=0;i<ntohs(dns->dns_ques);i++) { //获取各查询名 printf("第%d个查询名\n",i); int k=1;//标志符号; while(1) { if(*ch==0) break; u_int8_t identify_size=*ch; printf("\t第%d个标志符号\n",k); ch++; for(j=0;j<identify_size;j++,ch++) { if(isprint(*ch)) { printf("%c",*ch); }else { printf("."); } } k++; } } } count++; } libnet的使用 /* author hjj date 2011-1-20 function: send an arp packet to all machine on local net */ #include<stdio.h> #include<libnet.h> #define MAC_ADDR_LEN 6 #define IP_ADDR_LEN 4 #define LIBNET_DNS_H 0xc int main(int argc,char **argv) { libnet_t *net_t=NULL; char *dev="eth0"; char err_buf[LIBNET_ERRBUF_SIZE]; libnet_ptag_t p_tag; unsigned char src_mac[MAC_ADDR_LEN]={0x00,0x00,0xf1,0xe8,0x0e,0xc8};//发送者网卡地址 unsigned char dst_mac[MAC_ADDR_LEN]={0xff,0xff,0xff,0xff,0xff,0xff};//接收者网卡地址 char *src_ip_str="172.20.92.117"; if(argc==2) { if(strcmp(argv[1],"-h")==0||strcmp(argv[1],"--help")==0) { printf("%s","help message"); }else { src_ip_str=argv[1]; } } unsigned long src_ip,dst_ip=0; src_ip=libnet_name2addr4(net_t,src_ip_str,LIBNET_RESOLVE);//将字符串类型的ip转换为顺序网络字节流 net_t=libnet_init(LIBNET_LINK_ADV,dev,err_buf);//初始化发送包结构 if(net_t==NULL) { printf("libnet_init error\n"); exit(0) } p_tag=libnet_build_arp( ARPHRD_ETHER,//hardware type ethernet ETHERTYPE_IP,//protocol type MAC_ADDR_LEN,//mac length IP_ADDR_LEN,//protocol length ARPOP_REPLY,//op type (u_int8_t*)src_mac,//source mac addr这里的作用是更新目的地的arp表 (u_int8_t*)&src_ip,//source ip addr (u_int8_t*)dst_mac,//source mac addr (u_int8_t*)&dst_ip,//dest ip addr NULL,//payload 0,//payload length net_t,//libnet context 0//0 stands to build a new one ); if(-1 == p_tag) { printf("libnet_build_arp error"); exit(0); } //以太网头部 p_tag=libnet_build_ethernet(//create ethernet header (u_int8_t*)dst_mac,//dest mac addr (u_int8_t*)src_mac,//source mac addr ETHERTYPE_ARP,//protocol type NULL,//payload 0,//payload length net_t,//libnet context 0//0 to build a new one ); if(-1 == p_tag) { printf("libnet_build_ethernet error!\n"); exit(1); } int res; if(-1==(res=libnet_write(net_t))) { printf("libnet_write error!\n"); exit(1); } libnet_destroy(net_t); return 0; }
![](http://common.cnblogs.com/images/copycode.gif)
转自:http://hi.baidu.com/henujava/blog/item/20ea29c2c4ecf6c9d0006074.html
相关文章推荐
- linux下网络监听与发送数据包的方法(即libpcap、libnet两种类库的使用方法)
- linux下网络监听与发送数据包的方法(即libpcap、libnet两种类库的使用方法)
- java在线聊天项目0.3版本 制作客户端窗体,实现发送按钮和回车发送信息功能,使用ActionListener监听事件中actionPerformed方法(用内部类和匿名内部类两种方法)
- linux使用tcpdump命令监视指定网络数据包的方法
- 读取linux下的网络设备的mac地址与发送原始数据包
- Android系列之网络(三)----使用HttpClient发送HTTP请求(分别通过GET和POST方法发送数据)
- Android系列之网络(三)----使用HttpClient发送HTTP请求(分别通过GET和POST方法发送数据)
- linux使用tcpdump抓包工具抓取网络数据包,多示例演示
- linux下网络编程 SOCKET使用方法
- 【Linux网络编程】原始套接字实例:发送 UDP 数据包
- linux 下获取当前网络连接状态的两种方法
- Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
- 使用echarts类库,在后台封装option,提供两种使用struts2传递参数到页面的方法
- 使用UDP协议编写一个网络程序,设置接收端程序的监听端口是8001,发送端发送的数据是“Hello, world”。
- Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
- Linux使用tcpdump抓取网络数据包示例
- Linux C语言编程-Linux网络通信--Linux上使用套接字(socket)来发送信息---知识点总结+实例
- 网络内Linux与Windows之间的文件资源共享的两种方法
- linux下终端分屏使用的两种方法(screen和tmux)
- iOS学习之UISwitch控件两种使用方法和监听