qfedu-network-advanced-level/day6/n4.c

80 lines
3.0 KiB
C
Raw Permalink Normal View History

2023-09-11 20:58:01 +08:00
/*单播ARP应答*/
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ether.h>
#include <netpacket/packet.h>
#include <sys/ioctl.h>
#include <net/if.h> // ifreq
#include <unistd.h>
#include <string.h> // bzero
#include <stdio.h>
// 发送原始数据报
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name);
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name)
{
// 1. 获取网络接口类型(通过网卡名查找网卡索引)
struct ifreq ether_req;
bzero(&ether_req, sizeof(ether_req));
strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name
if (ioctl(fd, SIOCGIFINDEX, &ether_req) == -1)
{
perror("ioctl");
return -1;
}
// 2. 选择发送数据的网络接口索引(选择合适的网卡索引)
struct sockaddr_ll sll;
bzero(&sll, sizeof(sll));
sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue
// 3. 发送数据
ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll));
return len;
}
int main(int argc, char const *argv[])
{
// 创建原始套接字
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock_fd < 0)
{
perror("raw socket");
return -1;
}
// 组ARP应答报文(如果是ARP欺骗则源MAC为0x00,0x00,0x00,0x00,0x00,0x00)
uint32_t src_ip = inet_addr("10.12.156.204"); // 发送的 ip 地址
uint32_t dst_ip = inet_addr("10.12.156.178"); // 点分十进制转换为数字字符串
unsigned char *src_ip_p = (unsigned char *)&src_ip; // src_ip 的字符类型指针
unsigned char *dst_ip_p = (unsigned char *)&dst_ip;
unsigned char buf[] = {
0x00, 0x0c, 0x29, 0xf7, 0x81, 0x4c, /*目的MAC地址*/
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /* 源MAC地址 */
0x08, 0x06, /* ARP帧类型 */
0x00, 0x01, /* 硬件类型 */
0x08, 0x00, /* 协议类型(IP协议0x0800) */
0x06, 0x04, /* 硬件地址长度(MAC地址长度) 和 协议地址长度(IP 地址长度) */
0x00, 0x02, /* OP操作类型(ARP应答 = 2) */
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /* 发送端MAC地址 */
src_ip_p[0], src_ip_p[1], src_ip_p[2], src_ip_p[3], /* 源(发送端) IP 地址 */
0x00, 0x0c, 0x29, 0xf7, 0x81, 0x4c, /*接收端MAC地址*/
dst_ip_p[0], dst_ip_p[1], dst_ip_p[2], dst_ip_p[3] /* 接收端 IP 地址 */
};
// 单播发送ARP应答
ssize_t len = send_datapacket(sock_fd, buf, sizeof(buf), "ens38");
if (len > 0)
{
printf("send arp success! \n");
}
close(sock_fd);
return 0;
}