#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h> //for htons
#include <linux/if_ether.h> //for ETH_P_ARP ETH_P_IP ...
#include <sys/ioctl.h>
#include <linux/if.h> //for IFF_PROMISC
#include <getopt.h> //for getopt_long
#define _GUN_SOURCE //for getopt_long
#define OUTPUT_ETH_NONE 0x0000
#define OUTPUT_ETH_IP 0x0001
#define OUTPUT_ETH_ARP 0x0002
#define OUTPUT_ETH_RARP 0x0004
#define OUTPUT_IP_ICMP 0x0008
#define OUTPUT_IP_IGMP 0x0010
#define OUTPUT_IP_TCP 0x0020
#define OUTPUT_IP_UDP 0x0040
#define OUTPUT_ETH_ALL 0xFFFF
#define IP_P_NONE 0x00
#define IP_P_ICMP 0x01
#define IP_P_IGMP 0x02
#define IP_P_TCP 0x06
#define IP_P_UDP 0x11
#define BUF_LEN 1516
//#define NEW_PF_PACKET
#define OLD_SOCK_PACKET
void output_pkg(ssize_t n, unsigned char *buf, unsigned short int eth_type, unsigned char ip_type)
{
unsigned short int src_port;
unsigned short int dst_port;
char src_ip_addr[16] = {0};
char dst_ip_addr[16] = {0};
printf("%d\t%02x:%02x:%02x:%02x:%02x:%02x > %02x:%02x:%02x:%02x:%02x:%02x\t0x%04x\t", n,
buf[6]&0xFF, buf[7]&0xFF, buf[8]&0xFF, buf[9]&0xFF, buf[10]&0xFF, buf[11]&0xFF,
buf[0]&0xFF, buf[1]&0xFF, buf[2]&0xFF, buf[3]&0xFF, buf[4]&0xFF, buf[5]&0xFF,
eth_type);
if(eth_type == ETH_P_ARP)
{
printf("\n");
}
else if(eth_type == ETH_P_RARP)
{
printf("\n");
}
else if(eth_type == ETH_P_IP)
{
if(ip_type == IP_P_ICMP)
{
strcpy(src_ip_addr, inet_ntoa(*((struct in_addr *)(&(buf[26])))));
strcpy(dst_ip_addr, inet_ntoa(*((struct in_addr *)(&(buf[30])))));
printf("0x%02x\t%s > %s\t", ip_type & 0xFF, src_ip_addr, dst_ip_addr);
}
else if(ip_type == IP_P_IGMP)
{
strcpy(src_ip_addr, inet_ntoa(*((struct in_addr *)(&(buf[26])))));
strcpy(dst_ip_addr, inet_ntoa(*((struct in_addr *)(&(buf[30])))));
printf("0x%02x\t%s > %s\t", ip_type & 0xFF, src_ip_addr, dst_ip_addr);
}
else if(ip_type == IP_P_TCP)
{
strcpy(src_ip_addr, inet_ntoa(*((struct in_addr *)(&(buf[26])))));
strcpy(dst_ip_addr, inet_ntoa(*((struct in_addr *)(&(buf[30])))));
src_port = ntohs(*((unsigned short int *)(buf+34)));
dst_port = ntohs(*((unsigned short int *)(buf+36)));
printf("0x%02x\t%s > %s\t%d>%d\t", ip_type & 0xFF, src_ip_addr, dst_ip_addr, src_port, dst_port);
}
else if(ip_type == IP_P_UDP)
{
strcpy(src_ip_addr, inet_ntoa(*((struct in_addr *)(&(buf[26])))));
strcpy(dst_ip_addr, inet_ntoa(*((struct in_addr *)(&(buf[30])))));
src_port = ntohs(*((unsigned short int *)(buf+34)));
dst_port = ntohs(*((unsigned short int *)(buf+36)));
printf("0x%02x\t%s > %s\t%d>%d\t", ip_type & 0xFF, src_ip_addr, dst_ip_addr, src_port, dst_port);
}
else
{
printf("0x%02x\t", ip_type & 0xFF);
}
printf("\n");
}
else
{
printf("\n");
}
}
#ifdef NEW_PF_PACKET
int set_promisc_mode(int fd, char *ifname)
{
struct ifreq req;
struct packet_mreq mreq;
bzero(&req, sizeof(req));
bzero(&mreq, sizeof(mreq));
strcpy(req.ifr_name, ifname);
if(ioctl(fd, SIOCGIFINDEX, &req) == -1)
{
return -1;
}
mreq.mr_ifindex = req.ifr_ifindex;
mreq.mr_type = PACKET_MR_PROMISC;
if(setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
return -1;
}
return 0;
}
#endif
#ifdef OLD_SOCK_PACKET
int set_promisc_mode(int fd, char *ifname)
{
struct ifreq req;
strcpy(req.ifr_name, ifname);
if(ioctl(fd, SIOCGIFFLAGS, &req) == -1)
{
return -1;
}
req.ifr_flags |= IFF_PROMISC;
if(ioctl(fd, SIOCSIFFLAGS, &req) == -1)
{
return -1;
}
return 0;
}
#endif
/*****************************************************
*options:
* i:ip, a:arp, r:rarp, g: igmp, c:icmp, t:tcp, u:udp
*
*
* **************************************************/
int main(int argc, char **argv)
{
int fd, opt, opt_promisc = 0;
char *if_name = "eth0";
ssize_t n;
unsigned short int pkg_to_output = OUTPUT_ETH_NONE;
unsigned short int eth_pkg_type = 0x0000;
unsigned short int src_port = 0;
unsigned short int dst_port = 0;
unsigned short int monitor_port = 0;
unsigned char ip_pkg_type = 0x00;
unsigned char buf[BUF_LEN] = {0};
int optidx;
static struct option long_options[] = {
{"ip", 0, 0, 'i'},
{"arp", 0, 0, 'a'},
{"rarp", 0, 0, 'r'},
{"icmp", 0, 0, 'c'},
{"igmp", 0, 0, 'g'},
{"tcp", 2, 0, 't'},
{"udp", 2, 0, 'u'},
{"version", 0, 0, 'v'},
{"promisc", 1, 0, 'p'},
{0, 0, 0, 0},
};
while((opt = getopt_long(argc, argv, "iargct::u::p:v", long_options, &optidx)) != -1)
{
switch(opt)
{
case 'i':
{
pkg_to_output |= OUTPUT_ETH_IP;
break;
}
case 'a':
{
pkg_to_output |= OUTPUT_ETH_ARP;
break;
}
case 'r':
{
pkg_to_output |= OUTPUT_ETH_RARP;
break;
}
case 'g':
{
pkg_to_output |= OUTPUT_ETH_IP;
pkg_to_output |= OUTPUT_IP_IGMP;
break;
}
case 'c':
{
pkg_to_output |= OUTPUT_ETH_IP;
pkg_to_output |= OUTPUT_IP_ICMP;
break;
}
case 't':
{
pkg_to_output |= OUTPUT_ETH_IP;
pkg_to_output |= OUTPUT_IP_TCP;
if(optarg != NULL)
{
monitor_port = (unsigned short int)atoi(optarg);
}
break;
}
case 'u':
{
pkg_to_output |= OUTPUT_ETH_IP;
pkg_to_output |= OUTPUT_IP_UDP;
if(optarg != NULL)
{
monitor_port = (unsigned short int)atoi(optarg);
}break;
}
case 'v':
{
printf("version 1.0\n");
exit(0);
}
case 'p':
{
opt_promisc = 1;
if_name = optarg;
break;
}
default:
{
printf("useage: rawsocket [-i] [-r] [-a] [-g] [-c] [-v] [-t [port]] [-u [port]] [-p ifname]\n");
return 0;
}
}
}
if (pkg_to_output == OUTPUT_ETH_NONE)
{
pkg_to_output = OUTPUT_ETH_ALL;
}
/***************************************
*Argument 2:
* SOCK_RAW: The packet includes the link layer header.
* SOCK_DGRAM: The packet don`t includes the link layer header.
*Argument 3:
* ETH_P_IP(0x0800): ip
* ETH_P_RARP(0x0806): arp
* ETH_P_ARP(0x8035): rarp
* *************************************/
if((fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1)
{
printf("create socket failed: %s\n", strerror(errno));
return 0;
}
if(opt_promisc == 1)
{
if(set_promisc_mode(fd, if_name) == -1)
{
printf("set promisc mode failed!\n");
exit(0);
}
}
while(1)
{
if((n = read(fd, buf, BUF_LEN)) == -1)
{
if(errno == EINTR)
{
continue;
}
else
{
printf("read error: %s\n", strerror(errno));
exit(0);
}
}
eth_pkg_type = ntohs((*(unsigned short int *)(buf+12)))&0xFFFF;
if((eth_pkg_type == ETH_P_ARP) && (pkg_to_output & OUTPUT_ETH_ARP)) //ARP:0x0806
{
output_pkg(n, buf, eth_pkg_type, IP_P_NONE);
}
else if((eth_pkg_type == ETH_P_RARP) && (pkg_to_output & OUTPUT_ETH_RARP)) //RARP:0x8035
{
output_pkg(n, buf, eth_pkg_type, IP_P_NONE);
}
else if((eth_pkg_type == ETH_P_IP) && (pkg_to_output & OUTPUT_ETH_IP)) //IP:0x0800
{
ip_pkg_type = buf[23];
if(((pkg_to_output & OUTPUT_IP_ICMP) && ip_pkg_type == IP_P_ICMP) || //ICMP:0x01
((pkg_to_output & OUTPUT_IP_IGMP) && ip_pkg_type == IP_P_IGMP)) //IGMP:0x02
{
output_pkg(n, buf, eth_pkg_type, ip_pkg_type);
}
else if((pkg_to_output & OUTPUT_IP_TCP) && ip_pkg_type == IP_P_TCP) //TCP:0x06
{
src_port = ntohs(*((unsigned short int *)(buf+34)));
dst_port = ntohs(*((unsigned short int *)(buf+36)));
if(monitor_port == dst_port || monitor_port == 0)
{
output_pkg(n, buf, eth_pkg_type, ip_pkg_type);
}
}
else if((pkg_to_output & OUTPUT_IP_UDP) && ip_pkg_type == IP_P_UDP) //UDP:0x11
{
src_port = ntohs(*((unsigned short int *)(buf+34)));
dst_port = ntohs(*((unsigned short int *)(buf+36)));
if(monitor_port == dst_port || monitor_port == 0)
{
output_pkg(n, buf, eth_pkg_type, ip_pkg_type);
}
}
else //unknown ip pakage
{
if((pkg_to_output == OUTPUT_ETH_ALL) || (pkg_to_output == OUTPUT_ETH_IP))
{
output_pkg(n, buf, eth_pkg_type, ip_pkg_type);
}
}
}
else //unknown eth pakage
{
if(pkg_to_output == OUTPUT_ETH_ALL)
{
output_pkg(n, buf, eth_pkg_type, IP_P_NONE);
}
}
}
}
|