一个用PF_PACKET写的抓包程序sniffer
[code]/** capture.c
*
* gcc -W -Wall -Wno-unused -ggdb -o capture capture.c
*
*/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <net/if.h>
#include <features.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <signal.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#define N 30
#define in
#define out
#define RET_OK 1
#define IP_PROTOCOL_TCP 0x06
#define IP_PROTOCOL_UDP 0x11
#define OFFSET_DMAC 0
#define OFFSET_SMAC 6
#define OFFSET_ETHER 12
#define OFFSET_IP_PROT 23
#define OFFSET_SIP 26
#define OFFSET_DIP 30
#define OFFSET_SPORT 34
#define OFFSET_DPORT 36
#define DEFAULT_DEVICE_NAME "eth0"
/* #define DEFAULT_RECORD_FILENAME "packet.dat" */
typedef unsigned char uchar;
int RecordFile;
int Packet;
int PacketCount = 0;
/* char *RecordFileName = DEFAULT_RECORD_FILENAME; */
char *DeviceName = DEFAULT_DEVICE_NAME;
short int DefaultFlag;
struct ifreq ifr;
/**********from handle***************************************************/
typedef enum __ETHER_TYPE {
ETHER_IP = 0, /* 0x0800 */
ETHER_ARP, /* 0x0806 */
ETHER_PPP, /* 0x880b */
ETHER_MPLS_U, /* 0x8847 */
ETHER_MPLS_M, /* 0x8848 */
ETHER_PPPOE_DIS, /* 0x8863 */
ETHER_PPPOE_SESS, /* 0x8864 */
ETHER_EAPOL, /* 0x888e */
ETHER_LWAPP, /* 0x88bb */
ETHER_MAX /* 0xffff */
}ETHER_TYPE_T;
uchar* Ether_Type_Desc[] = { \
"IP", \
"ARP", \
"PPP", \
"MPLS_UNICAST", \
"MPLS_MULTICAST", \
"PPPOE_DISCOVERY", \
"PPPOE_SESSION", \
"EAPOL", \
"LWAPP", \
"Unknown" \
};
typedef enum __IP_PROT_TYPE {
IP_PROT_TCP = 0, /* 0x06 */
IP_PROT_UDP, /* 0x11 */
IP_PROT_MAX, /* 0xFF */
}IP_PROT_TYPE_T;
uchar* Ip_Protocol_Desc[] = { \
"TCP", \
"UDP", \
"Unknown" \
};
typedef enum __UDP_PORT_TYPE {
UDP_PORT_CAPWAP_C = 0, /* 0x2fbf */
UDP_PORT_CAPWAP_D, /* 0x2fbe */
UDP_PORT_DNS, /* 0x35 */
UDP_PORT_DHCPS, /* 0x43 */
UDP_PORT_DHCPC, /* 0x44 */
UDP_PORT_MAX
}UDP_PORT_TYPE_T;
uchar* Udp_Port_Desc[] = { \
"capwap control", \
"capwap data", \
"dns", \
"dhcp server", \
"dhcp client", \
"Unknown" \
};
typedef enum __TCP_PORT_TYPE {
TCP_PORT_FTP_C = 0, /* 0x15 */
TCP_PORT_FTP_D, /* 0x16 */
TCP_PORT_TELNET, /* 0x17 */
TCP_PORT_SMTP, /* 0x19 */
TCP_PORT_HTTP, /* 0x50 */
TCP_PORT_MAX
}TCP_PORT_TYPE_T;
uchar* Tcp_Port_Desc[] = { \
"ftp control", \
"ftp data", \
"telnet", \
"smtp", \
"http", \
"Unknown" \
};
int decap(in void * packet,in int totalBytes)
{
uchar cur;
uchar cByte;
ETHER_TYPE_T eType;
IP_PROT_TYPE_T iType;
UDP_PORT_TYPE_T uType;
TCP_PORT_TYPE_T tType;
int protocol;
int number = 0;
printf("%-12s:","DST MAC");
while(number<totalBytes)
{
cur = ((uchar*) packet)[number];
if(number<6)
{
printf("%02x%s", \
cur, \
number<5?":":"");
number++;
}
else if(number<12)
{
if(number==6)
printf("\n%-12s:","SRC MAC");
printf("%02x%s", \
cur, \
number<11?":":"");
number++;
}
else if(number==12)
{
char tmp =((char*) packet)[number+1];
if(cur==0x08 && tmp == 0x00) eType = ETHER_IP;
else if (cur==0x08 && tmp == 0x06) eType = ETHER_ARP;
else eType = ETHER_MAX;
number += 2;
printf("\n%-12s:[%s][0x%02x%02x]","ETH TYPE",Ether_Type_Desc[eType],cur,tmp);
}
else
{
switch(eType)
{
case ETHER_IP:
if(number==OFFSET_IP_PROT)
{
protocol = (int)cur;
switch(protocol)
{
case 0x06:
iType = IP_PROT_TCP;
break;
case 0x11:
iType = IP_PROT_UDP;
break;
default:
iType = IP_PROT_MAX;
}
printf("\n%-12s:[%s][%d]"," IP PROT",Ip_Protocol_Desc[iType],protocol);
}
else if(number>=OFFSET_SIP && number<OFFSET_DIP)
{
if(number==OFFSET_SIP)
printf("\n%-12s:","SRC IP");
printf("%d%s", \
cur,(number<OFFSET_DIP-1)?".":"");
}
else if(number>=OFFSET_DIP && number<OFFSET_DIP+4)
{
if(number==OFFSET_DIP)
printf("\n%-12s:","DST IP");
printf("%d%s", \
cur,(number<OFFSET_DIP+3)?".":"");
}
else if(number>=OFFSET_SPORT && number<OFFSET_DPORT)
{
switch(iType)
{
case IP_PROT_TCP:
number += 1;
cByte = ((uchar*)packet)[number];
if(0x00==cur&&0x15==cByte) tType = TCP_PORT_FTP_C;
else if(0x00==cur&&0x16==cByte) tType = TCP_PORT_FTP_D;
else if(0x00==cur&&0x17==cByte) tType = TCP_PORT_TELNET;
else if(0x00==cur&&0x50==cByte) tType = TCP_PORT_HTTP;
else tType = TCP_PORT_MAX;
printf("\n%-12s:[%s][0x%02x%02x]","SRC PORT", \
(tType==TCP_PORT_MAX)? "???" : Tcp_Port_Desc[tType],cur,cByte);
number += 1;
cur = ((uchar*)packet)[number];
number += 1;
cByte = ((uchar*)packet)[number];
if(0x00==cur&&0x15==cByte) tType = TCP_PORT_FTP_C;
else if(0x00==cur&&0x16==cByte) tType = TCP_PORT_FTP_D;
else if(0x00==cur&&0x17==cByte) tType = TCP_PORT_TELNET;
else if(0x00==cur&&0x50==cByte) tType = TCP_PORT_HTTP;
else tType = TCP_PORT_MAX;
printf("\n%-12s:[%s][0x%02x%02x]","DST PORT", \
(tType==TCP_PORT_MAX) ? "???" : Tcp_Port_Desc[tType],cur,cByte);
break;
case IP_PROT_UDP:
number += 1;
cByte = ((uchar*)packet)[number];
if(0x00==cur&&0x35==cByte) uType = UDP_PORT_DNS;
else if(0x00==cur&&0x43==cByte) uType = UDP_PORT_DHCPS;
else if(0x00==cur&&0x44==cByte) uType = UDP_PORT_DHCPC;
else tType = UDP_PORT_MAX;
printf("\n%-12s:[%s][0x%02x%02x]","SRC PORT", \
uType==UDP_PORT_MAX?"???":Udp_Port_Desc[uType],cur,cByte);
number += 1;
cur = ((uchar*)packet)[number];
number += 1;
cByte = ((uchar*)packet)[number];
if(0x00==cur&&0x35==cByte) uType = UDP_PORT_DNS;
else if(0x00==cur&&0x43==cByte) uType = UDP_PORT_DHCPS;
else if(0x00==cur&&0x44==cByte) uType = UDP_PORT_DHCPC;
else uType = UDP_PORT_MAX;
printf("\n%-12s:[%s][0x%02x%02x]","DST PORT", \
uType==UDP_PORT_MAX?"???":Udp_Port_Desc[uType],cur,cByte);
break;
default:
;
}
}
else {}
break;
case ETHER_ARP:
break;
case ETHER_MAX:
break;
default:
break;
}
number++;
}
}
return RET_OK;
}
/*****************************************************************************/
void ArgInit( int argc, char **argv )
{
}
void Shutdown( int signum )
{
/*fdatasync( RecordFile ); */
/* close( RecordFile ); */
ifr.ifr_flags = DefaultFlag;
ioctl( Packet, SIOCSIFFLAGS, &ifr );
close( Packet );
fprintf( stdout, "Capture %d packets\n", PacketCount );
exit( 0 );
}
void AppInit( void )
{
/* RecordFile = open( RecordFileName, O_RDWR | O_CREAT | O_TRUNC );
if ( RecordFile < 0 )
{
fprintf( stderr, "can't open record file : [%s]\n", strerror(errno) );
exit( 1 );
} */
strcpy( ifr.ifr_name, DeviceName );
/*fchmod( RecordFile, 0644 );*/
signal( SIGINT, Shutdown );
signal( SIGTERM, Shutdown );
}
void PacketInit( void )
{
int r, flag;
Packet = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );
if ( Packet < 0 )
{
fprintf( stderr, "socket failed : [%s]\n", strerror(errno) );
exit( 1 );
}
r = ioctl( Packet, SIOCGIFFLAGS, &ifr );
if ( r < 0 )
{
fprintf( stderr, "ioctl failed : [%s]\n", strerror(errno) );
close( Packet );
exit( 1 );
}
DefaultFlag = ifr.ifr_flags;
ifr.ifr_flags |= IFF_PROMISC;
r = ioctl( Packet, SIOCSIFFLAGS, &ifr );
if ( r < 0 )
{
fprintf( stderr, "ioctl failed : [%s]\n", strerror(errno) );
close( Packet );
exit( 1 );
}
}
void CaptureLoop( void )
{
int n;
int t;
/* int i=N;*/
uchar buf[2048];
while( 1 )
{
t=0;
n = recvfrom( Packet, buf, sizeof(buf), 0, NULL, NULL );
if ( n <= 0 )
{
fprintf( stderr, "recvfrom error : [%s]\n", strerror(errno) );
break;
}
// write( RecordFile, &n, sizeof(n) );
// write( RecordFile, buf, n );
while((n-t)>=16)
{
int i;
printf("[");
for(i=0;i<16;i++)
printf("%02x ",buf[t+i]);
printf("]\t[");
for(i=0;i<16;i++)
{
char ch=buf[t+i];
if(isalnum(ch))
printf("%c",ch);
else
printf(".");
}
printf("]\n");
t+=16;
}
if(n>t)
{
int i=t;
printf("[");
while(i<n)
printf("%02x ",buf[i++]);
printf("]");
i=n-t;
i=16-i;
while(i--)
printf(" ");
printf("\t[");
i=t;
while(i<n)
{
char ch=buf[i++];
if(isalnum(ch))
printf("%c",ch);
else
printf(".");
}
printf("]\n");
}
decap(buf,n);
printf("\n\n");
}
PacketCount++;
/* i--;*/
/* fprintf( stdout, "Capture %d packets\n", PacketCount );*/
/* fdatasync( RecordFile );*/
/* close( RecordFile ); */
ifr.ifr_flags = DefaultFlag;
ioctl( Packet, SIOCSIFFLAGS, &ifr );
close( Packet );
}
int main( int argc, char **argv )
{
ArgInit( argc, argv );
AppInit();
PacketInit();
CaptureLoop();
return 0;
} [/code]
页:
[1]