Linux抓包程序

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <string.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/if_ether.h>
#include <net/ethernet.h>
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);
    }
    return 0;
}
//修改网卡成PROMISC(混杂)模式
/*   =============================================================================================================下面是实现捕获和分析UDP协议数据包的函数定义  
=============================================================================================================*/   
void udp_protocol_packet_callback( u_char *packet_content)   
{   
    struct udphdr *udp_protocol;   
    // UDP协议数据变量   
    u_short source_port;   
    // 源端口号 
    u_short destination_port;   
    // 目的端口号    
    udp_protocol = (struct udphdr*)(packet_content + 14+20);   
    // 获得UDP协议数据内容 
    source_port = ntohs(udp_protocol->source);   
    // 获得源端口号 
    destination_port = ntohs(udp_protocol->dest);   
    // 获得目的端口号  
    printf("----------  UDP Protocol  (Transport  Layer)  ----------\n");   
    printf("Source port:%d\n", source_port);   
    printf("Destination port:%d\n", destination_port);   
    switch (destination_port)   
    //根据端口号判断应用层协议类型   
    {   
    case 138:   
        printf("NETBIOS Datagram Service\n");   
        break;   
        // 端口号为138,表示上层协议为NETBIOS 数据报服务    
    case 137:   
        printf("NETBIOS Name Service\n");   
        break;   
        // 端口号为137,表示上层协议为NETBIOS 名字服务    
    case 139:   
        printf("NETBIOS session service\n");   
        break;   
        // 端口号为139,表示上层协议为NETBIOS 会话服务    
    case 53:   
        printf("name-domain server \n");   
        break;   
        // 端口号为53,表示上层协议为域名服务 
    case 4000:   
        printf("QQ server \n");   
        break; 
    case 1863:   
        printf("MSN server \n");   
        break; 
    case 9001:   
        printf("OTHERS \n");   
        break;     
    default:   
        printf("NOT WELL-KNOWN PROTOCOL.\n");
        break; //其他没有分析 
    }   
}    /*   =============================================================================================================下面是实现捕获和分析TCP协议数据包的函数定义  
=============================================================================================================
*/   
void tcp_protocol_packet_callback( u_char *packet_content)   
{   
    struct tcphdr *tcp_protocol;   
    // TCP协议数据变量   
    u_short source_port;   
    // 源端口号 
    u_short destination_port;   
    // 目的端口号    
    tcp_protocol = (struct tcphdr*)(packet_content + 14+20);   
    // 获得UDP协议数据内容 
    source_port = ntohs(tcp_protocol->source);   
    // 获得源端口号 
    destination_port = ntohs(tcp_protocol->dest);   
    // 获得目的端口号  
    printf("----------  TCP Protocol  (Transport  Layer)  ----------\n");   
    printf("Source port:%d\n", source_port);   
    printf("Destination port:%d\n", destination_port);   
    switch (destination_port)   
    //根据端口号判断应用层协议类型   
    {   
    case 7:
        printf("ECHO server \n");
        break;
    case 21:
        printf("FTP server \n");
        break;
    case 23:
        printf("TELNET server \n");
        break;
    case 25:
        printf("SMTP server \n");
        break;
    case 53:
        printf("DNS server \n");
        break;
    case 80:
        printf("HTTP server \n");
        break;    
    case 2049:
        printf("NFS server \n");
        break;
    case 6667:
        printf("IRCD server \n");
        break;
    default:   
        printf("NOT WELL-KNOWN PROTOCOL.\n");
        break; //其他没有分析 
    }   
}   
/*  
=============================================================================================================
下面是分析IP协议的函数的定义  
============================================================================================================= 
*/   
void ip_protocol_packet_callback(  u_char *packet_content)   
{   
    struct iphdr *ip_protocol;    // IP协议变量  
    printf("----------  IP Protocol  (Network Layer)  ----------\n");   
    ip_protocol = (struct iphdr*)(packet_content + 14);   //获得IP协议数据内容 
    printf("Protocol:%d\n", ip_protocol->protocol);    //获得协议类型
    switch (ip_protocol->protocol) // 根据协议类型判断
    {
    case IPPROTO_TCP:
        printf("The Transport Layer Protocol is TCP\n");   
        break;   
        /* 上层协议为TCP协议 */   
    case IPPROTO_UDP:   
        printf("The Transport Layer Protocol is UDP\n");   
        break;   
        /* 上层协议为UDP协议 */   
    case IPPROTO_ICMP:   
        printf("The Transport Layer Protocol is ICMP\n");   
        break;   
        /* 上层协议为ICMP协议 */   
    case IPPROTO_IGMP:
        printf("The Transport Layer Protocol is IGMP\n");
        break;
    default:   
        break;   
    }   
    printf("TCP pkt :FORM:[%s]\n",inet_ntoa(*(struct in_addr*)&(ip_protocol->saddr)));
    printf("TCP pkt :TO:  [%s]\n",inet_ntoa(*(struct in_addr*)&(ip_protocol->daddr)));
    switch (ip_protocol->protocol)   
    {   
    case IPPROTO_TCP:  
        tcp_protocol_packet_callback(packet_content);
        break;   
    case IPPROTO_UDP:
        udp_protocol_packet_callback(packet_content);   
        break;    
    default:
        break;
    }   
} 
/*
=============================================================================================================
下面是分析以太网协议的回调函数的定义  
=============================================================================================================
*/   
void ethernet_protocol_packet_callback( u_char *packet_content)   
{   
    u_short ethernet_type;   /* 以太网类型 */   
    struct ether_header *ethernet_protocol;   /* 以太网协议变量 */   
    u_char *mac_string;   /* 以太网地址 */   
    static int packet_number = 1;   
    printf("**************************************************\n");   
    printf("The %d   packet is captured.\n", packet_number);   
    printf("--------   Ehternet Protocol (Link Layer)    --------\n");   
    ethernet_protocol = (struct ether_header*)packet_content;   
    /* 获得以太网协议数据内容 */   
    printf("Ethernet type is :\n");   
    ethernet_type = ntohs(ethernet_protocol->ether_type);   
    /* 获得以太网类型 */   
    printf("%04x\n", ethernet_type);   
    switch (ethernet_type)   
    {   
    case 0x0800:   
        printf("The network layer is IP protocol\n");   
        break;   
        /* 上层协议为IP协议 */   
    case 0x0806:   
        printf("The network layer is ARP protocol\n");   
        printf("----------  ARP Protocol   (Network Layer)  ----------\n");   
        break;   
        /* 上层协议为ARP协议 */   
    case 0x8035:   
        printf("The network layer is RARP protocol\n");   
        printf("----------  RARP Protocol   (Network Layer)  ----------\n");   
        break;   
        /* 上层协议为RARP协议 */   
    default:   
        break;   
    }   
    switch (ethernet_type)   
    {   
    case 0x0800:   
        ip_protocol_packet_callback( packet_content);   
        break;   
        // 上层协议为IP协议,就调用分析IP 协议的函数,注意参数的传递   
    default:   
        printf("Mac Source Address is : \n");   
        mac_string = ethernet_protocol->ether_shost;   
        printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));   
        //获得源以太网地址 
        printf("Mac Destination Address is : \n");   
        mac_string = ethernet_protocol->ether_dhost;   
        printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));   
        // 获得目的以太网地址  
        break;   
    }   
    printf("**************************************************\n");   
    packet_number++;   
}   

char buf[40960];
int main()
{
    struct sockaddr_in addr;
    int sock;
    int r = 0;    
    socklen_t len = 0;
    u_char *ptemp;
    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);
        if(recvfrom(sock,(char *)buf,sizeof(buf), 0, (struct sockaddr *)&addr,&len) > 0){
        }
        else{
            continue;
        }    
        //成功则返回接收到的字符数,失败返回-1,调试的时候可以增加一个输出r的语句判断是否抓到包
        buf[r] = 0;
        ptemp = buf;
        ethernet_protocol_packet_callback(ptemp);//调用以太网协议的回调函数
        usleep(1000);    
//        perror("dump");
    }
    return 0;
}
 

你可能感兴趣的:(linux)