Files
linux/ARP编程/代码/test.c
BecauseY a903236e4e 上传
2020-06-30 19:17:29 +08:00

175 lines
4.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <net/if_arp.h>
#include <linux/if_packet.h>
struct arppacket
{
struct arphdr ar_head;/*硬件类型、协议、地址长度、操作码*/
unsigned char ar_sha[ETH_ALEN];/*发送方MAC*/
struct in_addr ar_sip;/*发送方IP*/
unsigned char ar_tha[ETH_ALEN];;/*目的MAC*/
struct in_addr ar_tip;/*目的IP*/
}__attribute__((packed));
int main(int argc, char **argv)
{
//初始化及参数检查
struct in_addr pingaddr;
struct in_addr netaddr;
struct in_addr netmask;
struct sockaddr_ll hwaddr;
memset(&netaddr, 0, sizeof(netaddr));
memset(&netmask, 0, sizeof(netmask));
memset(&hwaddr, 0, sizeof(hwaddr));
//输入错误,显示正确输入格式
if(argc != 2)
{
perror("Usage: ./test xxx.xxx.xxx.xxx\n");
exit(-1);
}
//参数错误输入的不是ip地址
if(inet_aton(argv[1], &pingaddr) < 0)
{
perror("not a correct ip address\n");
exit(-1);
}
// 注册原始套接字
int fd = socket(PF_PACKET, SOCK_RAW, htonl(0x0003));
// 获得网卡信息
char buf[1024];
struct ifconf ifc;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if(ioctl(fd, SIOCGIFCONF, &ifc) == -1)
{
perror("get net interface error\n");
exit(-1);
}
// get correct net interface
int flag = 0;
int i;
struct ifreq *ifrPtr;
int networkNum = ifc.ifc_len / sizeof(struct ifreq);
for(i = 0; i < networkNum; i++)
{
ifrPtr = ((struct ifreq*)buf) + i;
if(ioctl(fd, SIOCGIFADDR, ifrPtr) == -1)
{
perror("get ip address error\n");
exit(-1);
}
netaddr = ((struct sockaddr_in*)&(ifrPtr->ifr_addr))->sin_addr;
if(ioctl(fd, SIOCGIFNETMASK, ifrPtr) == -1)
{
perror("get netmask error\n");
exit(-1);
}
netmask = ((struct sockaddr_in*)&(ifrPtr->ifr_netmask))->sin_addr;
// 设置sockaddr_ll地址
if((pingaddr.s_addr & netmask.s_addr) == (netaddr.s_addr & netmask.s_addr))
{
hwaddr.sll_family = PF_PACKET;
hwaddr.sll_protocol = htons(ETH_P_ARP);
hwaddr.sll_hatype = ARPHRD_ETHER;
hwaddr.sll_pkttype = PACKET_OTHERHOST;
hwaddr.sll_halen = ETH_ALEN;
if(ioctl(fd, SIOCGIFINDEX, ifrPtr) == -1)
{
perror("get net interface index error\n");
exit(-1);
}
hwaddr.sll_ifindex = ifrPtr->ifr_ifindex;
if(ioctl(fd, SIOCGIFHWADDR, ifrPtr) == -1)
{
perror("get net interface hwaddr error\n");
exit(-1);
}
memcpy(hwaddr.sll_addr, ifrPtr->ifr_hwaddr.sa_data, ETH_ALEN);
flag = 1;
break;
}
}
if(flag != 1)
{
perror("can not find correct net interface\n");
exit(-1);
}
// 构建ARP请求包
char ef[ETH_FRAME_LEN];
//使p_eth指向以太网帧的帧头
struct ethhdr *p_eth = (struct ethhdr*)ef;
//目的以太网地址
memset(p_eth->h_dest, 0xff, ETH_ALEN);
//源以太网地址
memcpy(p_eth->h_source, hwaddr.sll_addr, ETH_ALEN);
//设置协议类型
p_eth->h_proto = htons(ETH_P_ARP);
//定位ARP包地址
struct arppacket *p_arp = (struct arppacket*)(ef + ETH_HLEN);
//硬件类型
p_arp->ar_head.ar_hrd = htons(ARPHRD_ETHER);/*arp硬件类型*/
p_arp->ar_head.ar_pro = htons(ETH_P_IP); /*协议类型*/
p_arp->ar_head.ar_hln = ETH_ALEN; /*硬件地址长度*/
p_arp->ar_head.ar_pln = 4; /*IP地址长度*/
p_arp->ar_head.ar_op = htons(ARPOP_REQUEST);
/*复制源以太网地址*/
memcpy(p_arp->ar_sha, hwaddr.sll_addr, ETH_ALEN);
/*源IP地址*/
p_arp->ar_sip = netaddr;
/*复制目的以太网地址*/
memset(p_arp->ar_tha, 0, ETH_ALEN);
//目的IP地址
p_arp->ar_tip = pingaddr;
//绑定网卡
if(bind(fd, (struct sockaddr*)&hwaddr, sizeof(struct sockaddr_ll)) == -1)
{
perror("bind network error\n");
exit(-1);
}
//发送以太网帧
write(fd, ef, 60);
//读取并打印目的MAC
while(1)
{
read(fd, ef, sizeof(ef));
struct arppacket *recv_arp = (struct arppacket*)(ef+ETH_HLEN);
if(recv_arp->ar_tip.s_addr == netaddr.s_addr)
{
printf("Find %s 's mac:",argv[1]);
for (i = 0; i < ETH_ALEN - 1; i++)
printf("%02x-", recv_arp->ar_sha[i]);
printf("%02x\n", recv_arp->ar_sha[ETH_ALEN - 1]);
break;
}
}
return 0;
}