设为首页 加入收藏

TOP

Linux 网络编程——原始套接字实例:MAC 地址扫描器
2015-07-16 12:57:33 来源: 作者: 【 】 浏览:7
Tags:Linux 网络编程 原始 套接字 实例 MAC 地址 扫描器

如果 A (192.168.1.1 )向 B (192.168.1.2 )发送一个数据包,那么需要的条件有 ip、port、使用的协议(TCP/UDP)之外还需要 MAC 地址,因为在以太网数据包中 MAC 地址是必须要有的。那么怎样才能知道对方的 MAC 地址?答案是:它通过 ARP 协议来获取对方的 MAC 地址。


ARP(Address Resolution Protocol,地址解析协议),是 TCP/IP 协议族中的一个,主要用于查询指定 ip 所对应的的 MAC(通过 ip 找 MAC)。


请求方使用广播来发送请求,应答方使用单播来回送数据。收到返回消息后将该 IP 地址和物理地址存入本机 ARP 缓存中并保留一定时间,下次请求时直接查询 ARP 缓存以节约资源。


以机器 A 获取机器 B 的 MAC 为例,A 广播发送一个 ARP 请求包,和 A 同在一个局域网的主机都会收到这个请求包,每个机器都会比较自己的 ip 和请求包的目的 ip 是不是一样的,如果不一样,就丢弃这个请求包,结果,只有 B 机器符合条件,B 机器单独给 A 发送 ARP 应答包,应答包带上了 B 的 ip 所对应的 MAC 地址,当 A 收到这个应答包后,就把 B 的 ip 以及其对应的 MAC 地址存入本机 ARP 缓存中。



在 Linux 查看 ARP 缓存表:arp



在 Windows 查看 ARP 缓存表:arp -a



ARP头部



1、Dest MAC:目的 MAC 地址


2、Src MAC:源 MAC 地址


3、帧类型:0x0806


4、硬件类型:1(以太网)


5、协议类型:0x0800(IP地址)


6、硬件地址长度:6


7、协议地址长度:4


8、OP:1(ARP请求),2(ARP应答),3(RARP请求),4(RARP应答)


先查看 ubuntu 的 ip 和 MAC 地址:



源代码下载


------------------------------------------分割线------------------------------------------


具体下载目录在 /2015年资料/4月/7日/Linux 常用编辑器之Vim/


------------------------------------------分割线------------------------------------------


完整代码如下:


#include
#include
#include
#include ? ? //struct ifreq
#include ? ?//ioctl、SIOCGIFADDR
#include
#include ? //ETH_P_ALL
#include ?//struct sockaddr_ll
#include


int main(int argc,char *argv[])
{
?//1.创建通信用的原始套接字
?int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
?
?//2. 根据各种协议首部格式构建发送数据报
?unsigned char send_msg[1024] = {
? //--------------组MAC--------14------
? 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //dst_mac: FF:FF:FF:FF:FF:FF
? 0x00, 0x0c, 0x29, 0x97, 0xc7,0xc1, //src_mac: 00:0c:29:97:c7:c1
? 0x08, 0x06,? ? ? ?//类型:0x0806 ARP协议
?
? //--------------组ARP--------28-----
? 0x00, 0x01, 0x08, 0x00,? ? //硬件类型1(以太网地址),协议类型0x0800(IP)?
? 0x06, 0x04, 0x00, 0x01,? ? //硬件、协议地址分别是6、4,op:(1:arp请求,2:arp应答)
? 0x00, 0x0c, 0x29, 0x97, 0xc7,0xc1,?//发送端的MAC地址
? 10,? 221,? 0, 11,? ? ? //发送端的IP地址
? 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,?//目的MAC地址(由于要获取对方的MAC,所以目的MAC置零)
? 10, 221, 20, 10? ? //目的IP地址
?};
?
?//3.数据初始化
?struct sockaddr_ll sll;? ? ?//原始套接字地址结构
?struct ifreq ethreq;? ? ?//网络接口地址
?strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);?//指定网卡名称
?
?//4.将网络接口赋值给原始套接字地址结构
?ioctl(sock_raw_fd, SIOCGIFINDEX, (char *)?req);
?bzero(&sll, sizeof(sll));
?sll.sll_ifindex = ethreq.ifr_ifindex;
?
?//5. 发送 ARP 请求包
?int len = sendto(sock_raw_fd, send_msg, 42, 0 , (struct sockaddr *)&sll, sizeof(sll));
?if(len == -1)
?{
? perror("sendto");
?}
?
?//6.接收对方的ARP应答
?unsigned char recv_msg[1024] = {0};
?recvfrom(sock_raw_fd, recv_msg, sizeof(recv_msg), 0, NULL, NULL);
?if(recv_msg[21] == 2)? ?//ARP应答
?{
? char resp_mac[18] = "";? //arp响应的MAC
? char resp_ip[16] = "";? //arp响应的IP
?
? sprintf(resp_mac, "%02x:%02x:%02x:%02x:%02x:%02x", \
? recv_msg[22],recv_msg[23],recv_msg[24],recv_msg[25],recv_msg[26],recv_msg[27]);
? sprintf(resp_ip, "%d.%d.%d.%d", recv_msg[28], recv_msg[29], recv_msg[30], recv_msg[31]);
? printf("IP:%s - MAC:%s\n",resp_ip, resp_mac);
?}
?
?return 0;
}


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇使用 Go 构建一个解释型语言 下一篇C++中的容器

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: