最近劳动成果(send arp requset packet)

记得三周前
导师给我个题目: 通过ARP协议解析指定IP的MAC地址

当时我的网络协议方面的知识是一片空白
虽说是网络专业的 不过出于对刻板教育模式的BS 上课从来没听过 要么睡觉 要么看书
突然让我编程实现这个东西 当时非常的茫然

于是赶紧拉了几个仁兄一起研究ARP协议
搞清楚之后又陷入了茫然
因为即便是对协议封包了如指掌 也不知道从何下手去解析它

于是开始上网查资料 泡图书馆
没敢去问导师具体的做法 怕他觉得我无能

天天抱着N百页的《UNIX网络编程》啃
终于了解了网络编程的内幕
自己也搞了现成的代码改了改
但是都是socket套接口之类的服务器/客户端程序
而ARP协议的实现是不需要这些东东的 它是封装在OS中自动实现的

显然 路走错了
前几天去导师那说起这事
他无意中说了句有现成的库函数包可用 叫个libpcap
我如获至宝

呵呵
果然如此
libpcap & libnet 包
一个抓 一个发
都是现成的API函数调用
呵呵
高兴啊~~~

下面放个向指定IP发送ARP请求包的代码
需要libpcap libnet库支持
安装方式见 GOOGLE

 

/* send_arp.c 
* 编译:  #gcc -o send_arp send_arp.c -Wall -lnet -lpcap
*  运行: #./send_arp <destination IP address>
*
*
*/

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< unistd.h >
#include 
< sys / time.h >
#include 
< sys / types.h >
#include 
< sys / socket.h >
#include 
< netinet / in .h >
#include 
< arpa / inet.h >

#include 
< libnet.h >
#include 
< pcap.h >

#ifndef ETH_ALEN
#define  ETH_ALEN 6
#endif

#ifndef IP_ALEN
#define  IP_ALEN 4
#endif

static  u_char eth_xmas[ETH_ALEN]  =   {0xff0xff0xff0xff0xff0xff} ;
static  u_char eth_null[ETH_ALEN]  =   {0x000x000x000x000x000x00} ;

static  u_char eth_src[ETH_ALEN];
static  u_char eth_dst[ETH_ALEN]  =   {0xff0xff0xff0xff0xff0xff} ;

static  u_char ip_src[IP_ALEN];
static  u_char ip_dst[IP_ALEN] ;

int  main( int  argc,  char   ** argv)
{
  libnet_t 
*libnet = NULL;
  
char error[LIBNET_ERRBUF_SIZE];
  
int i, c;

  
if (getuid() && geteuid()) {
    fprintf(stderr, 
"must be run as root");
    exit(
1);
  }

  
if(argc != 2){
          printf(
"usage: %s <dst IP addr> ", argv[0]);
  }


  
// open libnet
  libnet = libnet_init(LIBNET_LINK, "eth0", error);
  
if(libnet == NULL) {
          fprintf(stderr, 
"libnet_init() failed: %s", error);
          exit(EXIT_FAILURE);
  }


  
// get dst ip address
  u_int32_t otherip;
  otherip 
= libnet_name2addr4(libnet, argv[1], LIBNET_RESOLVE);
  memcpy(ip_dst, (
char*)&otherip, IP_ALEN);
  printf(
"dst IP:  %d.%d.%d.%d ",ip_dst[0],ip_dst[1],ip_dst[2],ip_dst[3]);
  
  
// get hwaddr
  struct libnet_ether_addr *mymac;
  mymac 
= libnet_get_hwaddr(libnet);
  memcpy(eth_src, mymac, ETH_ALEN);

  
// get ipaddr
  u_int32_t myip;
  myip 
= libnet_get_ipaddr4(libnet);
  memcpy(ip_src, (
char*)&myip, IP_ALEN);
  printf(
"src IP:  %d.%d.%d.%d ",ip_src[0],ip_src[1],ip_src[2],ip_src[3]);
  
  
// print source MAC address
  printf(" ");
  
for (i = 0; i < ETH_ALEN - 1; i++{
    printf(
"%.2x:", (u_int8_t)eth_src[i]);
  }

  printf(
"%.2x", (u_int8_t)eth_src[ETH_ALEN - 1]);
  printf(
" ");

  
static libnet_ptag_t arp=0, eth=0;

  arp 
= libnet_build_arp(
     ARPHRD_ETHER,
     ETHERTYPE_IP,
     ETH_ALEN, IP_ALEN,
     ARPOP_REQUEST,
     eth_src, ip_src,
     eth_dst, ip_dst,
     NULL, 
0,
     libnet,
     
0);
  
  
if (arp == -1)
  
{
          fprintf(stderr, 
"Can't build ARP header: %s ", libnet_geterror(libnet));
          
goto bad;
  }


  eth 
= libnet_build_ethernet(
     eth_dst, eth_src,
     ETHERTYPE_ARP,
     NULL, 
0,
     libnet,
     eth);
  
if (eth == -1)
  
{
          fprintf(stderr, 
"Can't build ethernet header: %s ", libnet_geterror(libnet));
          
goto bad;
  }


  c 
= libnet_write(libnet);
  
if (c == -1)
  
{
          fprintf(stderr, 
"Can't send ARP packet: %s ", libnet_geterror(libnet));
          
goto bad;
  }


  libnet_destroy(libnet);
  
return 0;
bad:
  libnet_destroy(libnet);
  
return -1;
}
 



其实代码都是网上DOWN的
我只不过按照自己的意愿改了改
第一次干这样的活
有意思诶

下面放上抓包的代码:

 

 

/*cap_arp.c*/
/*
*        编译: #gcc -o cap_arp cap_arp.c -lnet -lpcap 
*        运行: #./cap_arp 
*/

#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< pcap.h >                  /* if this gives you an error try pcap/pcap.h */
#include 
< errno.h >
#include 
< sys / socket.h >
#include 
< netinet / in .h >
#include 
< arpa / inet.h >
#include 
< netinet / if_ether.h >          /* includes net/ethernet.h */

int  main( int  argc,  char   ** argv)
{
    
int i, cnt = 0;
    
char *dev;
    
char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t 
*descr;                /*you can man it */
    
const u_char *packet;
    
struct pcap_pkthdr hdr;        /* pcap.h */
    
struct ether_header *eptr;        /* net/ethernet.h */
    
struct in_addr addr;
    
char *net;                        /* dot notation of the network address */
    
char *mask;                        /* dot notation of the network mask    */
    bpf_u_int32 netp;                
/* ip          */
    bpf_u_int32 maskp;                
/* subnet mask */
    
int ret;                        /* return code */

    u_char 
*ptr;                /* printing out hardware header info */

    
/* grab a device to peak into... */
    dev 
= pcap_lookupdev(errbuf);

    
if (dev == NULL) {
        printf(
"%s ", errbuf);
        exit(
1);
    }


    printf(
"DEV: %s ", dev);

    
/* open the device for sniffing.

       pcap_t *pcap_open_live(char *device,int snaplen, int prmisc,int to_ms,
       char *ebuf)

       snaplen - maximum size of packets to capture in bytes
       promisc - set card in promiscuous mode?
       to_ms   - time to wait for packets in miliseconds before read
       times out
       errbuf  - if something happens, place error string here

       Note if you change "prmisc" param to anything other than zero, you will
       get all packets your device sees, whether they are intendeed for you or
       not!! Be sure you know the rules of the network you are running on
       before you set your card in promiscuous mode!!     
*/


    descr 
= pcap_open_live(dev, BUFSIZ, 0-1, errbuf);

    
if (descr == NULL) {
        printf(
"pcap_open_live(): %s ", errbuf);
        exit(
1);
    }


    
/*
       grab a packet from descr (yay!)                    
       u_char *pcap_next(pcap_t *p,struct pcap_pkthdr *h) 
       so just pass in the descriptor we got from         
       our call to pcap_open_live and an allocated        
       struct pcap_pkthdr                                 
*/

    
while (cnt < 2{
            
while((packet = (const u_char *)(pcap_next(descr, &hdr))) == NULL) {        /* dinna work *sob* */
                    printf(
"Didn't grab packet ");
                    exit(
1);
            }


        
/*  struct pcap_pkthdr {
           struct timeval ts;   time stamp 
           bpf_u_int32 caplen;  length of portion present 
           bpf_u_int32;         lebgth this packet (off wire) 
           }
         
*/


        
/* lets start with the ether header... */
        eptr 
= (struct ether_header *) packet;

        
/* check to see what packet type we have.. */
        
if (ntohs(eptr->ether_type) == ETHERTYPE_ARP) {
            
++cnt;
            printf(
"Grabbed packet of length %d ", hdr.len);
            printf(
"Recieved at time..... %s",
                   ctime((
const time_t *&hdr.ts.tv_sec));
            printf(
"Ethernet address length is %d ", ETHER_HDR_LEN);

            printf(
"Ethernet type hex:%x dec:%d is an ARP packet ",
                   ntohs(eptr
->ether_type), ntohs(eptr->ether_type));


            
/* THANK YOU RICHARD STEVENS!!! RIP */
            ptr 
= eptr->ether_dhost;
            i 
= ETHER_ADDR_LEN;
            printf(
"  Destination MAC Address:  ");
            
do {
                printf(
"%s%x", (i == ETHER_ADDR_LEN) ? " " : ":"*ptr++);
            }
 while (--> 0);
            printf(
"  Destination IP Address:  ");
            
{                        /* 显示IP和MASK地址 */
                ret 
= pcap_lookupnet(dev, &netp, &maskp, errbuf);

                
if (ret == -1{
                    printf(
"%s ", errbuf);
                    exit(
1);
                }


                
/* get the network address in a human readable form */
                addr.s_addr 
= netp;
                net 
= inet_ntoa(addr);

                
if (net == NULL) {        /* thanks Scott :-P */
                    perror(
"inet_ntoa");
                    exit(
1);
                }


                printf(
" NET: %s ", net);

                
/* do the same as above for the device's mask */
                addr.s_addr 
= maskp;
                mask 
= inet_ntoa(addr);

                
if (mask == NULL) {
                    perror(
"inet_ntoa");
                    exit(
1);
                }


                printf(
" MASK: %s ", mask);
            }


            ptr 
= eptr->ether_shost;
            i 
= ETHER_ADDR_LEN;
            printf(
"  Source Address:  ");
            
do {
                printf(
"%s%x", (i == ETHER_ADDR_LEN) ? " " : ":"*ptr++);
            }
 while (--> 0);

            printf(
" ********************************* ");
        }

    }


    
return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值