📄 ipdumpinlinux.cpp
字号:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#define _FAVOR_BSD
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#ifdef _linux
#include <linux/sockios.h>
#include <linux/if.h>
#else
#include <sys/ioct1.h>
#include <net/bpf.h>
#include <net/if.h>
#include <fcntl.h>
#endif
#define MAXSIZE 4096
#define OPTNUM 8
#define ON 1
#define OFF 0
enum{ETHER,ARP,IP,TCP,UDP,ICMP,DUMP,ALL};
#define _linux
int open_bpf(char*ifname);
#endif
void print_ethernet(struct ether_header*eth);
void print_arp(struct ether_arp*arp);
void print_ip(struct ip*ip);
void print_icmp(struct icmp*icmp);
void print_tcp(struct tcphdr*tcp);
void print_udp(struct udphdr*udp);
void dump_packet(unsigned char*buff,int len);
char * mac_ntoa(u_char*d);
char * tcp_ftoa(int flag);
char * ip_ttoa(int flag);
char * ip_ftoa(int flag);
void help(char*cmd);
int main(int argc, char * * argv)
{
struct ether_header * eth; /* Ethernet报头的结构体 */
struct ether_arp * arp; /* ARP包的结构体 */
struct ip * ip; /* IP报头的结构体 */
struct icmp * icmp; /* ICMP报头的结构体 */
struct tcphdr * tcp; /* TCP报头的结构体 */
struct udphdr * udp; /* UDP报头的结构体 */
int s; /* 套结字描述符 */
int len; /* 接收到数据的长度 */
int c; /* 使用getopt()所获得的字符 */
int disp; /* 是否在屏幕上显示的标志 */
char buff[MAXSIZE]; /* 接收数据缓冲区 */
char * p; /* 显示报头的初始作业用指针 */
char * p0; /* 显示包的初始作业用指针 */
char ifname[256]="xl0"; /* FreeBSD的接口名称 */
int opt[OPTNUM]; /* 显示可选域的标志 */
extern int optind; /* getopt()的全局变量 */
#ifnder_linux
int bpf_len; /* 使用BPF接收到的数据 */
struct bpf_hdr * bp; /* BPF报头的结构体 */
#endif
/* 显示包的种类的初始值*/
opt[ETHER] = OFF;
opt[ARP] = ON;
opt[IP] = ON;
opt[TCP] = ON;
opt[UDP] = ON;
opt[ICMP] = ON;
opt[DUMP] = OFF;
opt[ALL] = OFF;
/* 命令行可选域的检查 */
while((c=getopt(argc,argv,"aei:p:dh"))!=EOF){
switch(c){
case'a': /*all*/
opt[ALL]=ON;
break;
case'i': /*if name*/
strcpy(ifname,optarg);
break;
case'e': /*ethernet*/
opt[ETHER]=ON;
break;
case'd': /*dump*/
opt[DUMP]=ON;
break;
case'p': /*protocol*/
opt[ARP]=OFF;
opt[IP]=OFF;
opt[TCP]=OFF;
opt[UDP]=OFF;
opt[ICMP]=OFF;
optind- -;
while(argv[optind]!=NULL&&argv[optind][0]!='-'){
if(strcmp(argv[optind],"arp")==0) /* arp */
opt[ARP]=ON;
else if(strcmp(argv[optind],"ip")==0) /* ip */
opt[IP]=ON;
else if(strcmp(argv[optind],"tcp")==0) /* tcp */
opt[TCP]=ON;
else if(strcmp(argv[optind],"udp")==0) /* udp */
opt[UDP]=ON;
else if(strcmp(argv[optind],"icmp")==0) /* icmp */
opt[ICMP]=ON;
else if(strcmp(argv[optind],"other")==0) /* other */
;
else{
help(argv[0]);
exit(EXIT_FAILURE);
}
optind++;
}
break;
case'h': /* help */
case'?':
default:
help(argv[0]);
exit(EXIT_FAILURE);
break;
}
}
if(optind<argc){
while(optind<argc)
printf("%s",argv[optind++]);
printf("\n");
help(argv[0]);
exit(EXIT_FAILURE);
}
#ifdef _ _linux
if((s=socket(AF_INET,SOCK_PACKET,htons(ETH_P_ALL)))<0){
perror("socket");
exit(EXIT_FAILURE);
}
if(strcmp(ifname,"xl0")!=0){
struct sockadrr sa;
memset(&sa,0,sizeof sa);
sa.sa_family=AF_INET;
strcpy(sa.sa_data,ifname);
if(bimd(s,&sa,sizeof sa)<0){
perror("bind");
exit(EXIT_FAILURE);
}
}
#else
if((s=open_bpf(ifname))<0)
exit(EXIT_FAILURE);
bpf_len=0;
#endif
while(1){
#ifndef _linux
/* 来自BPF的输入*/
if(bpf_len<=0){
/* 一次取出多个包*/
if((bpf_len=read(s,buff,MAXSIZE))<0){
perror("read");
exit(EXIT_FAILURE);
}
bp=(struct bpf_hdr*)buff;
}else{
/* 移动到BPF的下一个包的指针 */
bp=(struct bpf_hdr*)((char*)bp+bp->bh_hdrlen+bp->bh_caplen);
bp=(struct bpf_hdr*)BPF_WORDALIGN((int)bp);
}
/* 设置Ethernet报头的初始指针 */
p=po=(char*)bp+bp->bh_hdrlen;
len=bp->bh_caplen;
#ifder DEBUG
/* 显示BPF报头的结构体*/
printf("bpf_len=%d,",bpf_len);
printf("hdrlen=%d,",bp->bh_hdrlen);
printf("caplen=%d,",bp->bh_caplen);
printf("datalen=%d\n",bp->bh_datalen);
#endif;
/* 为了进行下一个while循环的处理 */
bpf_len-=BPF_WORDALIGN(bp->bh_hdrlen+bp->bh_caplen);
#else
/* 来自linux SOCK_PACKET的输入 */
if((len=read(s,buff,MAXSIZE))<0){
perror("read");
exit(EXIT_FAILURE);
}
/* 设置Ethernet报头的初始指针 */
p=po=buff;
#endif
/*
* 显示包的子程序
*/
disp=OFF; /* 是否在屏幕上输出的标志 */
/* Ethernet报头结构体的设定 */
eth=(struct ether_header*)p;
p=p+sizeof(struct ether_header);
if(ntohs(eth->ether_type)==ETHERTYPE_ARP){
if(opt[ARP]==ON){
if(opt[ETHER]==ON)
print_ethernet(eth);
arp=(struct ether_arp*)p;
print_arp(arp);
disp=ON;
}
}else if (ntohs(eth->ether_type)==ETHERTYPE_IP){
ip=(struct ip*)p;
p=p+((int)(ip->ip_hl)<<2);
if(opt[IP]==ON&&opt[TCP]==OFF&&opt[UDP]==OFF&&opt[ICMP]==OFF){
if(opt[ETHER]==ON)
print_ethernet(eth);
print_ip(ip);
disp=ON;
}
switch(ip->ip_p){
case IPPROTO_TCP;
tcp=(struct tcphdr*)p;
p=p+((int)(tcp->th_off)<<2);
if(opt[TCP]==ON){
if(opt[IP]==ON){
if(opt[ETHER]==ON)
print_ethernet(eth);
print_ip(ip);
}
print_tcp(tcp);
disp=ON;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
break;
case IPPROTO_UDP;
udp=(struct udphdr * );
p=p + sizeof(struct udphdr);
if (opt[UDP]==ON){
if (opt[IP]==ON){
if (opt[ENTER]==ON)
print_ethernet(eth);
print_ip(ip);
}
print_udp(udp);
disp = ON;
}
break;
case IPPROTO_ICMP;
icmp=(struct icmp * )p;
p=p+sizeof(struct udphdr);
if(opt[ICMP]==ON){
if (opt[IP]==ON){
if (opt[ENTER]==ON)
print_Ethernet(eth);
print_ip(ip);
}
print_icmp(icmp);
disp = ON;
}
break;
default;
if (opt[ALL]==ON){
if (opt[IP]==ON){
if (opt[ENTER]==ON)
print_Ethernet(eth);
print_ip(ip);
}
printf("protocol:unknow\n");
disp = ON;
}
break;
}
}else{
if (opt[ALL]==ON){
if (opt[ENTER]==ON)
print_ethernet(eth);
print("protocol:unknow\n");
disp = ON;
}
}
if (disp==ON){
if(opt[DUMP]==ON)
dump_packet(p0,len);
printf("\n");
}
}
return EXIT_SUCCESS;
}
/*
*char *mac_ntoa(u_char * d);
* 功能
* 将一个在数组中存储的MAC地址转换为字符串
* 实际参数
* u_char*d;存储MAC地址的区域的初始地址
* 返回值
* 变换为一个字符串的MAC地址
*/
char *mac_ntoa(u_char * d)
{
static char str [50];/*保存变换为字符串的MAC地址*/
sprintf (str,"%02x:%02x:%02x:%02x:%02x:%02x",d[0],d[1],d[2],d[3],d[4],d[5]);
return str;
}
/*
* viod print_ethernet(struct ether_header * eth);
* 功能
* 显示Ethernet报头
* 实际参数
* struct ether_header*eth;指向Ethernet报头结构体指针
*返回值
* 无
*/
viod print_ethernet(struct ether_header *eth)
{
int type = ntohs (eth->ether_type);//ethernet类型
if (type <= 1500)
printf ("IEEE802.3 Ethernet Frame: \n");
else
printf("Ethernet Frame: \n");
printf("+-----------------+----------------"
"+----------------+\n");
printf("|Destination MAC Adress:
"% 17s|\n"mac_ntoa(eth->ether dhost));
printf("+-----------------+----------------"
"+----------------+\n");
printf("|Source MAC Adress:
"% 17s|\n"mac_ntoa(eth->ether dhost));
printf("+-----------------------+----------------------"
"+----------------+\n");
if (type<1500)
print("|length:%5u|\n",type);
else
printf("|ethernet tpye 0x % 04x |\n",type);
printf("+----------------+\n");
}
/*
*viod print_arp(struct ether_arp);
*功能
* 显示一个ARP包
*实际参数
* struct ether arp*arp;ARP包结构体的指针
*返回值
* 无
*/
viod print_arp(struct ether_arp * arp);
{
static char * arp_operation[]={
"Unfine",
"(ARP Request)",
"(ARPReplay)",
"(RARP Request)",
"(RARP Replay)",
};
/*显示可选域种类的字符串*/
int op = ntohs(arp->ea_hdr.ar_op);/*ARP可选域*/
if (op<=0||5<op)
op=0;
printf("protocol:ARP\n");
printf("+-----------------+-----------------+\n");
printf("| hadr Type:%2u%-11s| protocol:0x%04x%-9s|\n"),
ntohs(arp->ea_hdr.ar_hrd),
(ntohs(arp->ea_hdr.ar_hrd)==ARPHRD_ENTER)?"(Ethernet)":"(Notther)",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -