1:什么是arp协议

  参考文章:http://blog.csdn.net/tigerjibo/article/details/7351992

  全称是:Address Resolution Protocol 地址解析协议,也就是用IP地址获取MAC地址的工具。

2:什么时候使用arp

  arp是处于网络层的协议,但却是为链路层服务的,比如创建一个TCP的套接字,链路层、网络层、传输层的数据报文都是内核替你封装的(当然你要传递必要的参数),在内核封装链路层的报文时,必须得知道目的地的MAC地址(因为网卡收到的数据先经过链路层,如果发现报文的目的MAC不是自己一般会直接丢弃此报文,更没有可能进入协议栈了.有一个特殊情况是当网卡设置为混杂模式时,所有流经它的报文它都拿进协议栈处理),首先内核会在操作系统维护的arp缓存表中找目的IP是否对应了一个MAC,如果有就把这个MAC拿来使用,否则这时候arp就登场了.

  arp首先广播此IP地址(没有目的MAC),局域网中的主机就开始检查自己的IP,如果是这个IP就会单播回复,我是这个IP的主人,并且我的MAC地址是多少,收到此回复后操作系统就更新或者添加IP-MAC地址对到arp缓存表.这是在同一个局域网的情况下,如果目的地址不在同一局域网呢?情况就是根据路由表的下一跳地址,去解析这个地址的MAC,到达之后继续解析下一跳,直到到达目的地为止.

3:简单应用

  这是一个简单的在局域网中利用一个IP地址获取MAC地址的程序,根据arp协议,首先要使用arp广播这个IP地址,根据回复的单播报文获取到此IP的MAC,思路很简单,下面是源代码:

1:read_interface 获得源IP,源MAC,这两个参数在发送arp报文时需要用到

/*
用socket获得当前interface的信息
1:ip地址
2:mac地址
3:interface index
注:创建的是原始套接字,编译及执行都需要root权限
*/
int read_interface(const char* interface, uint32_t *sour_ip, uint8_t *sour_mac)
{
int fd;
int ret = ;
struct ifreq ifr;
struct sockaddr_in *ip_addr = NULL;
memset(&ifr, , sizeof(struct ifreq));
fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (fd > ){
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
//get interface ip
if (sour_ip) {
if (ioctl(fd, SIOCGIFADDR, &ifr) == ){
ip_addr = (struct sockaddr_in *) &ifr.ifr_addr;
printf("The sour_ip addr is:%s\n", inet_ntoa(ip_addr->sin_addr));
*sour_ip = ip_addr->sin_addr.s_addr;
} else {
perror("SIOCGIFADDR failed");
ret = -;
goto out;
}
} //get interface mac
if (sour_mac) {
if(ioctl(fd, SIOCGIFHWADDR, &ifr) == ){
memcpy(sour_mac, ifr.ifr_hwaddr.sa_data, );
printf("interface sour_mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
sour_mac[],sour_mac[],sour_mac[],sour_mac[],sour_mac[],sour_mac[]);
} else {
perror("SIOCGIFHWADDR failed");
ret = -;
goto out;
}
}
} else {
perror("read_interface socket failed");
ret = -;
}
out:
close(fd);
return ret;
}

2:arpping 封装arp报文发送并接收结果

int arpping(const uint8_t* sour_mac, const uint32_t sour_ip, const uint32_t dest_ip, const uint8_t* interface)
{
int s; /* raw socket */
int send_times = ;
int optval = ;
struct arpMsg arp;
struct sockaddr addr;
/* create a raw socket */
if ((s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -) {
perror("arpping open raw socket failed");
return -;
} /* 允许发送广播包,如果没有设置此option,即使目的MAC是FF:FF:FF:FF:FF:FF此报文也不会被操作系统发送出去! */
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -) {
perror("setsockoptetopt on raw socket failed");
close(s);
return -;
} /* 封装 Ethernet 报文 */
memset(&arp, , sizeof(arp));
memcpy(arp.ethhdr.h_dest, MAC_BROADCAST_ADDR, );
memcpy(arp.ethhdr.h_source, sour_mac, ); /* 封装 arp 报文 */
arp.htype = htons(ARPHRD_ETHER);
arp.ptype = htons(ETH_P_IP);
arp.hlen = ;
arp.plen = ;
arp.operation = htons(ARP_REQUEST);
memcpy(arp.sHaddr, sour_mac, );
memcpy(arp.sInaddr, &sour_ip, sizeof(sour_ip));
memcpy(arp.tInaddr, &dest_ip, sizeof(dest_ip)); /* 发送arp request 广播包*/
memset(&addr, , sizeof(addr));
strncpy(addr.sa_data, interface, sizeof(addr.sa_data));
if (sendto(s, &arp, sizeof(arp), , &addr, sizeof(addr)) < ){
perror("arpping sendto error");
return -;
} /* 获取返回数据(阻塞的) */
if (recv(s, &arp, sizeof(arp), ) < )
{
printf("no response\n");
return -;
}
printf("dest_mac: %02X:%02X:%02X:%02X:%02X:%02X\n",\
arp.sHaddr[],arp.sHaddr[],arp.sHaddr[],\
arp.sHaddr[],arp.sHaddr[],arp.sHaddr[]); return ;
}

3:main 函数

int main(int argc,char** argv)
{
int ret;
if(argc < ){
printf("need a dest ip\n");
return -;
}
uint32_t dest_ip = inet_addr(argv[]);
char *interface = "eth0";
uint32_t sour_ip;
uint8_t sour_mac[] = {};
/* 获取本地IP,MAC信息 */
read_interface(interface, &sour_ip, sour_mac); /* 调用arpping广播arp报文获取MAC地址 */
arpping(sour_mac, sour_ip, dest_ip, interface); return ;
}

4:头文件及结构体等

#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/ip.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h> #define MAC_BROADCAST_ADDR (uint8_t *)"/xff/xff/xff/xff/xff/xff"
#define ARP_REQUEST 1
#define ARP_REPLY 2
struct arpMsg {
struct ethhdr ethhdr; /* 链路层头部 */
u_short htype; /* 硬件类型 (ARPHRD_ETHER=1 表示以太网) */
u_short ptype; /* 协议类型 (ETH_P_IP=0x0800 表示IP协议类型) */
u_char hlen; /* 硬件地址长度 (6) */
u_char plen; /* 协议地址长度 (4) */
u_short operation; /* ARP 操作类型 (1:arp请求 2:arp应答)*/
u_char sHaddr[]; /* 源MAC地址 */
u_char sInaddr[]; /* 源IP地址 */
u_char tHaddr[]; /* 目的MAC地址 */
u_char tInaddr[]; /* 目的IP地址 */
u_char pad[]; /* 填充字节,因为爱以太网中传输的帧最小是64字节 */
};

arp协议及简单应用的更多相关文章

  1. arp协议简单介绍

    1. 什么是ARP? ARP (Address Resolution Protocol) 是个地址解析协议.最直白的说法是:在IP以太网中,当一个上层协议要发包时,有了该节点的IP地址,ARP就能提供 ...

  2. 浅谈ARP协议以及应用

    0. 前言 本章主要简单的介绍ARP的协议格式,主机如何发送和处理ARP报文,以及免费ARP. 1. ARP协议原理 ARP,全称Address Resolution Protocol,地址解析协议, ...

  3. ARP协议的基础知识

          关于ARP协议的基础知识 1.ARP的工作原理 本来我不想在此重复那些遍地都是的关于ARP的基本常识,但是为了保持文章的完整性以及照顾初学者,我就再啰嗦一些文字吧,资深读者可以直接跳过此节 ...

  4. ARP协议详解RARP

    简单来说,ARP协议是IP地址转换成MAC地址的协议.链路层协议.过程如下: 1:首先,每个主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址之间的对应关系. 2:当源主机要 ...

  5. ARP协议与ARP攻击入门

    一 ARP协议 ARP协议是一个年代相当"久远"的网络协议.ARP协议制定于1982年11月,英文全称:Address Resolution Protocol,即"地址解 ...

  6. ARP协议分析

    一.ARP概述 网络中所有的协议(HTTP.URL.FTP.TELNET.TCP.UDP.ARP ······)都包含在TCP/IP协议栈中,从使用上来看:其中大部分协议都是大家平常上网所接触到的,不 ...

  7. [图解]ARP协议(一)

    一.ARP概述 如果要在TCP/IP协议栈中选择一个"最不安全的协议",那么我会毫不犹豫把票投给ARP协议.我们经常听到的这些术语,包括"网络扫描"." ...

  8. 图解ARP协议(二)ARP攻击原理与实践

    一.ARP攻击概述 在上篇文章里,我给大家普及了ARP协议的基本原理,包括ARP请求应答.数据包结构以及协议分层标准,今天我们继续讨论大家最感兴趣的话题:ARP攻击原理是什么?通过ARP攻击可以做什么 ...

  9. 图解ARP协议(三)ARP防御篇-如何揪出“内鬼”并“优雅的还手”

    一.ARP防御概述 通过之前的文章,我们已经了解了ARP攻击的危害,黑客采用ARP软件进行扫描并发送欺骗应答,同处一个局域网的普通用户就可能遭受断网攻击.流量被限.账号被窃的危险.由于攻击门槛非常低, ...

随机推荐

  1. 简单的图片滑动效果插件 jQuery.iocnSlider.js

    近几日在制作一个客户引导页面,其中有一个图片展示而且带滑动的效果.好久没练手了,索性自己写一个插件吧. 依据设计原型,需要满足两套分辨率下图片不同的尺寸,所以在css中使用了media query的相 ...

  2. django request bug

    bug描述:django请求request接收数据时,如果参数中包含分号时,会导致分号后面的消息丢失. 比如前台js调用代码 $.post('/get_params', { "A" ...

  3. 一键部署pxe环境

    系统:Centos6.5 环境:VMware Workstation12 #!/bin/bash # Please prepare CentOS ISO image first # root pass ...

  4. C++字符串拼接和输入

    一 .char类型字符串以空字符结尾 1.以空字符结尾,空字符被写作\0,其ASCII码为0,用来标记字符串的结尾. char dog[4]={'a','b','c','d'}   //不是一个字符串 ...

  5. STM32F4编程手册学习2_内存模型

    STM32F4编程手册学习2_内存模型 1. 内存映射 MCU将资源映射到一段固定的4GB可寻址内存上,如下图所示. 内存映射将内存分为几块区域,每一块区域都有一个定义的内存类型,一些区域还有一些附加 ...

  6. Eclipse安装颜色主题,个性化你的IDE,让你的IDE焕然一新

    我们都知道eclipse默认的颜色主题是白色的背景,但是如果想改变代码编辑区的背景颜色,需要怎么办呢? 今天给大家介绍一个非常赞的eclipse,可以很方便的根据自己的需求选择喜欢的颜色主题,其他的不 ...

  7. 软件测试基础-Homework1

    The error was in my graduate work which was about game development.I broadcast some messages to the ...

  8. 第十七次ScrumMeeting会议

    第十七次Scrum Meeting 时间:2017/12/7 地点:线上+主235 人员:蔡帜 王子铭 游心 解小锐 王辰昱 李金奇 杨森 陈鑫 赵晓宇 照片: 目前工作进展 名字 今日 明天的工作 ...

  9. gcc与g++区别以及相关参数详解

    ---恢复内容开始--- 原文链接:g++和gcc的区别 一 .二者区别 gcc和g++都是GNU(一个组织)的编译器. 1.对于.c后缀的文件,gcc把它当做是C程序:g++当做是C++程序: 2. ...

  10. Unity3D 入门 - 工作区域介绍 与 入门示例

    一. 工作区域详解 1. Scence视图 (场景设计面板) scence视图简介 : 展示创建的游戏对象, 可以对所有的游戏对象进行 移动, 操作 和 放置; -- 示例 : 创建一个球体, 控制摄 ...