Good evening. I’m writing a small program in C, which should get the mac addresses of all active devices from the IP range 192.168.0.1-192.168.255.255 (the command line cannot be used). Display the result on the console ip = mac. To solve the problem, an ARP request was chosen. How advisable is it to use it? Will I be able to get the mac address of a subnet that I am not in? My C code unfortunately does not output anything. Help me please
#include<linux/if_ether.h>
#include <netinet/if_ether.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netpacket/packet.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/ether.h>
#define BUFFER_SIZE 256
struct arp_header {
uint16_t hardware_type;
uint16_t protocol_type;
uint8_t hardware_len;
uint8_t protocol_len;
uint16_t opcode;
uint8_t sender_mac[6];
uint8_t sender_ip[4];
uint8_t target_mac[6];
uint8_t target_ip[4];
};
void create_arp_request(uint8_t *sender_mac, uint8_t *sender_ip, uint8_t *target_ip, uint8_t *packet) {
// Fill Ethernet header
struct ethhdr *eth = (struct ethhdr *) packet;
uint8_t broadcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
memcpy(eth->h_dest, broadcast_mac, ETH_ALEN); // Destination MAC address (broadcast)
memcpy(eth->h_source, sender_mac, ETH_ALEN); // Source MAC address
eth->h_proto = htons(ETH_P_ARP); // ARP frame type
// Fill ARP header
struct arp_header arp;
memset(&arp, 0, sizeof(struct arp_header));
arp.hardware_type = htons(ARPHRD_ETHER);
arp.protocol_type = htons(ETH_P_IP);
arp.hardware_len = ETH_ALEN;
arp.protocol_len = sizeof(in_addr_t);
arp.opcode = htons(ARPOP_REQUEST);
memcpy(arp.sender_mac, sender_mac, ETH_ALEN);
memcpy(arp.sender_ip, sender_ip, sizeof(in_addr_t));
memset(arp.target_mac, 0, ETH_ALEN); // Target MAC address (unknown)
memcpy(arp.target_ip, target_ip, sizeof(in_addr_t));
// Copy ARP header to packet array
memcpy(packet + sizeof(struct ethhdr), &arp, sizeof(struct arp_header));
}
void receive_arp_responses(int socket_fd, uint8_t *sender_ip) {
while (1) {
uint8_t buffer[BUFFER_SIZE];
struct sockaddr_ll recvaddr;
socklen_t recvaddrlen = sizeof(recvaddr);
// Wait for data reception
ssize_t packet_len = recvfrom(socket_fd, buffer, sizeof(buffer), 0, (struct sockaddr *) &recvaddr,
&recvaddrlen);
// Check for reception error
if (packet_len == -1) {
perror("Failed to receive packet");
break;
}
// Get Ethernet and ARP headers
struct ethhdr *eth = (struct ethhdr *) buffer;
struct arp_header *arp = (struct arp_header *) (buffer + sizeof(struct ethhdr));
// Check if the received packet is an ARP response and the sender IP matches the target IP
if (ntohs(eth->h_proto) == ETH_P_ARP &&
memcmp(arp->sender_ip, sender_ip, 4) == 0 &&
ntohs(arp->opcode) == ARPOP_REPLY) {
// Print information about the ARP response
printf("ARP Response received:\n");
printf("Sender MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", arp->sender_mac[0], arp->sender_mac[1],
arp->sender_mac[2], arp->sender_mac[3], arp->sender_mac[4], arp->sender_mac[5]);
printf("Sender IP: %d.%d.%d.%d\n", arp->sender_ip[0], arp->sender_ip[1], arp->sender_ip[2],
arp->sender_ip[3]);
// Additional processing of the received ARP response
}
}
}
int main() {
int delay = 1;
uint8_t packet[sizeof(struct ethhdr) + sizeof(struct arp_header)];
int socket_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (socket_fd == -1) {
perror("Failed to create socket");
return 1;
}
// Specify the listening interface
struct sockaddr_ll sa;
memset(&sa, 0, sizeof(struct sockaddr_ll));
sa.sll_family = AF_PACKET;
sa.sll_protocol = htons(ETH_P_ARP);
sa.sll_ifindex = if_nametoindex("eth0");
// Bind the socket to the interface
if (bind(socket_fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_ll)) == -1) {
perror("Failed to bind socket");
close(socket_fd);
return 1;
}
// Create ARP request
uint8_t sender_mac[6] = {0xC5, 0xA6, 0x93, 0x5A, 0x9E, 0xQS}; // Sender MAC address
uint8_t sender_ip[4] = {192, 168, 0, 101}; // Sender IP address
// Send ARP request for a range of target IP addresses
for (int i = 1; i <= 101; i++) {
uint8_t target_ip[4] = {192, 168, 0, i}; // Iterate over IP address range
create_arp_request(sender_mac, sender_ip, target_ip, packet);
int num_bytes = sendto(socket_fd, packet, sizeof(struct ethhdr) + sizeof(struct ether_arp), 0,
(struct sockaddr *) &sa, sizeof(struct sockaddr_ll));
// Send ARP request
if (sendto(socket_fd, packet, sizeof(packet), 0, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
perror("Failed to send ARP request");
close(socket_fd);
return 1;
}
sleep(delay);
}
receive_arp_responses(socket_fd, sender_ip);
close(socket_fd);
return 0;
}