ARP 协议

ARP 格式 struct arphdr { unsigned short int ar_hrd; /* Format of hardware address. */ unsigned short int ar_pro; /* Format of protocol address. */ unsigned char ar_hln; /* Length of hardware address. */ unsigned char ar_pln; /* Length of protocol address. */ unsigned short int ar_op; /* ARP opcode (command). */ }; struct ether_arp { struct arphdr ea_hdr; /* fixed-size header */ uint8_t arp_sha[ETH_ALEN]; /* sender hardware address */ uint8_t arp_spa[4]; /* sender protocol address */ uint8_t arp_tha[ETH_ALEN]; /* target hardware address */ uint8_t arp_tpa[4]; /* target protocol address */ }; Ethernet II 格式 typedef unsigned short __u16; typedef __u16 __bitwise __be16; struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ __be16 h_proto; /* packet type ID field */ } __attribute__((packed)); C 收发 ARP 报文 发 #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <linux/if_ether.h> #include <netinet/if_ether.h> #include <linux/if_packet.h> #include <net/if.h> #include <string.h> #include <net/if_arp.h> #include <arpa/inet.h> #include <unistd.h> int main() { // Create raw socket int socket_fd = socket(AF_PACKET, SOCK_RAW, 0); if (socket_fd < 0) { perror("create socket failed"); exit(1); } // Bind interface and get local mac struct sockaddr_ll local; local.sll_family = AF_PACKET; local.sll_ifindex = (int) if_nametoindex("eth0"); socklen_t local_len = sizeof local; if (bind(socket_fd, (struct sockaddr *) &local, local_len) < 0) { perror("bind dev failed"); exit(1); } getsockname(socket_fd, (struct sockaddr *) &local, &local_len); // Create packet unsigned char buf[256]; struct ethhdr *eh = (struct ethhdr *) buf; struct ether_arp *arp = (struct ether_arp *) (eh + 1); size_t size = (unsigned char *) (struct ether_arp *) (arp + 1) - buf; // Ethernet II header memset(eh->h_dest, 255, ETH_ALEN); memcpy(eh->h_source, local.sll_addr, ETH_ALEN); eh->h_proto = htons(ETH_P_ARP); // Arp header arp->ea_hdr.ar_hrd = htons(ARPHRD_ETHER); arp->ea_hdr.ar_pro = htons(ETH_P_IP); arp->ea_hdr.ar_hln = ETH_ALEN; arp->ea_hdr.ar_pln = 4; arp->ea_hdr.ar_op = htons(ARPOP_REQUEST); // Sender addr memcpy(arp->arp_sha, local.sll_addr, ETH_ALEN); struct in_addr src_ip; inet_aton("172.22.211.129", &src_ip); memcpy(arp->arp_spa, &src_ip.s_addr, 4); // Target addr memset(arp->arp_tha, 255, ETH_ALEN); struct in_addr dst_ip; inet_aton("172.22.208.1", &dst_ip); memcpy(arp->arp_tpa, &dst_ip.s_addr, 4); while (1) { if (send(socket_fd, buf, size, 0) < 0) { perror("send arp failed"); exit(1); } printf("send arp success\n"); sleep(1); } } 存在 char * 和 struct 的相互转化,因结构体个变量地址连续且排列顺序固定,所以可以这么做。——如此编程精巧但易出错,只能说不愧是 C! ...

三月 4, 2023  |  662 字  |  总阅读