Arp packet or range IP

124 views Asked by At

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;
}
0

There are 0 answers