Chinaunix首页 | 论坛 | 博客
  • 博客访问: 221635
  • 博文数量: 38
  • 博客积分: 2060
  • 博客等级: 大尉
  • 技术积分: 388
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-17 10:10
文章分类

全部博文(38)

文章存档

2011年(1)

2009年(37)

我的朋友

分类: LINUX

2009-08-16 15:07:32

这两天闲着没事,练练手,没什么技术含量,大部分时间花在折腾输出逻辑上了,汗!涉及到的一些细节包括:
  • 数据链路层的访问
  • 将网卡设置为混杂模式
  • 以太网桢头,IP头,TCP/UDP头的部分内容
  • getopt_long的使用方法

程序只输出了部分必要的信息,具体的信息可以根据自己的需要进行修改。

使用方法:

NAME

rawsocket - A simple sniffer

SYNOPSIS

rawsocket [-i] [-r] [-a] [-g] [-c] [-v] [-t [port]] [-u [port]] [-p ifname]

DESCRIPTION

I am not good in english. rawsocket is sniffer than can sniff most pakage on local network. it also has the capacity of setting the NIC(network interface card) to promiscuous mode. etc.

OPTIONS

-i, --ip

monitor IP pakage.

-r, --rarp

monitor RARP pakage.

-a, --arp

monotor ARP pakage.

-g, --igmp

monotor IGMP pakage.

-c, --icmp

monitor ICMP pakage.

-v, --version

print version

-t[port], --tcp=[port]

monitor tcp port port.

-u[port], --udp=[port]

monitor udp port port.

-pifname, --promisc=ifname

set the NIC ifname to promiscuous mode.

AUTHORS

famdestiny

author

NOTES

None

#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);
            }
        }
    }
}

阅读(2429) | 评论(0) | 转发(0) |
0

上一篇:递归求螺旋数组

下一篇:搭建KDE开发环境

给主人留下些什么吧!~~