void die(char *why, int n)
{
perror(why);
exit(n);
}
int do_promisc(char *nif, int sock )
{
struct ifreq ifr;
strncpy(ifr.ifr_name, nif,strlen(nif)+1);
if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) //获得flag
{
die("ioctl", 2);
}
ifr.ifr_flags |= IFF_PROMISC; //重置flag标志
if(ioctl(sock, SIOCSIFFLAGS, &ifr) == -1 ) //改变模式
{
die("ioctl", 3);
}
}
//修改网卡成PROMISC(混杂)模式
char buf[40960];
main()
{
struct sockaddr_in addr;
struct ether_header *peth;
struct iphdr *pip;
struct tcphdr *ptcp;
struct udphdr *pudp;
char mac[16];
int i,sock, r, len;
char *data;
char *ptemp;
char ss[32],dd[32];
if((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) //建立socket
//man socket可以看到上面几个宏的意思
{
die("socket", 1);
}
do_promisc("eth0", sock); //eth0为网卡名称
system("ifconfig");
for(;;)
{
len = sizeof(addr);
r = recvfrom(sock,(char *)buf,sizeof(buf), 0, (struct sockaddr *)&addr,&len);
//调试的时候可以增加一个输出r的语句判断是否抓到包
buf[r] = 0;
ptemp = buf;
peth = (struct ether_header *)ptemp;
ptemp += sizeof(struct ether_header); //指针后移eth头的长度
pip = (struct ip *)ptemp; //pip指向ip层的包头
ptemp += sizeof(struct ip);//指针后移ip头的长度
switch(pip->protocol) //根据不同协议判断指针类型
{
case IPPROTO_TCP:
ptcp = (struct tcphdr *)ptemp; //ptcp指向tcp头部
printf("TCP pkt :FORM:[%s]:[%d]
",inet_ntoa(*(struct in_addr*)&(pip->saddr)),ntohs(ptcp->source));
printf("TCP pkt :TO:[%s]:[%d]
",inet_ntoa(*(struct in_addr*)&(pip->daddr)),ntohs(ptcp->dest));
break;
case IPPROTO_UDP:
pudp = (struct udphdr *)ptemp; //ptcp指向udp头部
printf("UDP pkt:
len:%d payload len:%d from %s:%d to %s:%d
",
r,
ntohs(pudp->len),
inet_ntoa(*(struct in_addr*)&(pip->saddr)),
ntohs(pudp->source),
inet_ntoa(*(struct in_addr*)&(pip->daddr)),
ntohs(pudp->dest)
);
break;
case IPPROTO_ICMP:
printf("ICMP pkt:%s
",inet_ntoa(*(struct in_addr*)&(pip->saddr)));
break;
case IPPROTO_IGMP:
printf("IGMP pkt:
");
break;
default:
printf("Unkown pkt, protocl:%d
", pip->protocol);
break;
} //end switch
perror("dump");
}
}
/*
[playmud@fc3 test]$ gcc -v
Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.2/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
Thread model: posix
gcc version 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)
************************eth的结构**************************************
struct ether_header
{
u_int8_t ether_dhost[ETH_ALEN]; // destination eth addr
u_int8_t ether_shost[ETH_ALEN]; // source ether addr
u_int16_t ether_type; // packet type ID field
} __attribute__ ((__packed__));
***********************IP的结构***********************************
struct iphdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
#else
# error "Please fix
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
};
***********************TCP的结构****************************
struct tcphdr
{
u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
# if __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res1:4;
u_int16_t doff:4;
u_int16_t fin:1;
u_int16_t syn:1;
u_int16_t rst:1;
u_int16_t psh:1;
u_int16_t ack:1;
u_int16_t urg:1;
u_int16_t res2:2;
# elif __BYTE_ORDER == __BIG_ENDIAN
u_int16_t doff:4;
u_int16_t res1:4;
u_int16_t res2:2;
u_int16_t urg:1;
u_int16_t ack:1;
u_int16_t psh:1;
u_int16_t rst:1;
u_int16_t syn:1;
u_int16_t fin:1;
# else
# error "Adjust your
# endif
u_int16_t window;
u_int16_t check;
u_int16_t urg_ptr;
};
***********************UDP的结构*****************************
struct udphdr
{
u_int16_t source;
u_int16_t dest;
u_int16_t len;
u_int16_t check;
};
*************************************************************
*/