linux利用raw socket抓包

本文介绍了一个在Linux环境下使用raw socket捕获网络包的程序示例。通过创建一个PF_PACKET类型的socket,设置为SOCK_RAW模式,并启用混杂模式(IFF_PROMISC),可以接收到经过特定网卡的所有数据包。示例中还展示了如何接收并发送数据包,以及显示部分包内容的函数`showpacket`。
摘要由CSDN通过智能技术生成

来自:http://www.diybl.com/course/6_system/linux/Linuxjs/20090930/177633.html

#include <sys/socket.h>

# include   < sys / ioctl . h >
# include   < fcntl . h >
# include   < unistd . h >
# include   < netinet / if_ether . h >
# include   < netinet / ip . h >
# include   < netinet / udp . h >
# include   < netinet / tcp . h >
# include   < net / if . h >
# include   < netdb . h >
# include   < stdio . h >
# include   < stdlib . h >
# include   < string . h >
# include   < linux / if_packet . h >
# include   < linux / errno . h >

int  socket_init ( void ) ;
int  showpacket ( unsigned   char *  buffer ) ;
int  sendfd , sock ;
struct  sockaddr_ll  in_addr ;
struct  sockaddr_ll dest ;
struct  ifreq ifr ;


int  main ( argc , argv )
    int  argc ;
    char   * argv [ ] ;
{
    socklen_t  destlen ;
    struct  ethhdr  * eth_hdr ;
    int  recv_len ,  socklen , flag  =  0 , on = 1 , n = 0 ;
    unsigned   char  buffer [ 65536 ] ;
    int  myflag = 0 ;
    struct  packet_mreq mr ;
    int  state = 0 ;
    int  recv_buf_len , buflen ;
    int  i = 0 ;
   
    memset ( & mr , 0 , sizeof ( mr ) ) ;
    socklen = sizeof ( struct  sockaddr_ll ) ;
   
    if ( argc  <  2 )
    {
        printf ( "\n invalid argument!! \n" ) ;
        exit ( 0 ) ;
    }

   sock  =  socket_init ( ) ;
   sendfd = socket ( PF_PACKET , SOCK_RAW , htons ( ETH_P_ALL ) ) ;
  
   strcpy ( ifr . ifr_name , "eth0" ) ;
   ioctl ( sendfd , SIOCGIFINDEX , & ifr ) ;
   mr . mr_ifindex = ifr . ifr_ifindex ;
   mr . mr_type = PACKET_MR_PROMISC ;
   if ( setsockopt ( sendfd , SOL_PACKET , PACKET_ADD_MEMBERSHIP , & mr , sizeof ( mr ) ) = = - 1 )
      {
        perror ( " can not set to promisc" ) ;
        exit ( 0 ) ;
      }
     if ( strcmp ( argv [ 1 ] ,   "all" )   = =  0 )
        flag  =  0 ;
    else   if ( strcmp ( argv [ 1 ] ,   "debug" )   = =  0 )
        flag  =  1 ;
    else   {
        printf ( "\n wrong argument!!\n" ) ;
        exit ( 0 ) ;

   }

   while(1)
   {
       memset(&dest, 0x0, socklen);
       memset(&in_addr, 0x0, socklen);
        recv_len = recvfrom(sock, buffer, sizeof(buffer), 0,
           (struct sockaddr *)&in_addr, &socklen);
        showpacket(buffer);
       if(in_addr.sll_pkttype==PACKET_OUTGOING){printf("won't send me again;\n");continue;} 
        dest.sll_family=AF_PACKET;
        dest.sll_ifindex =ifr.ifr_ifindex;
        dest.sll_halen=htons(ETH_HLEN); 
       memmove(&dest.sll_addr,buffer,sizeof(buffer[0])*8);
        n=sendto(sendfd,buffer,recv_len,0,(struct sockaddr*)&dest,sizeof(dest));
      printf(" send n=%d\n",n);

   }
   return 0;
}
int socket_init()
{
   struct ifreq ifr;
   int sock;
   memset(&ifr, 0x0, sizeof(struct ifreq));

   if((sock = socket(PF_PACKET, SOCK_RAW, htons(0x0003))) < 0)
   {
       perror(" socket ");
       exit(0);
   }

   strcpy(ifr.ifr_name, "eth0");
   if(ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
   {
       perror("siocgifflags");
       exit(0);
   }

   
    ifr.ifr_flags |= IFF_PROMISC;
   if(ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
   {
       perror("fejwaio?");
       exit(0);
   }
   return sock;
}

int showpacket(unsigned char* buffer)
{
   int i=0;
   unsigned char buff[50];
   memmove(buff,buffer,50); 
   for(i=0;i<50;i++)
   {
   if(i==25)printf("\n");
       printf("%2x ",buff[i]);
   }
   printf("\n");
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值