From 94ae687abfd456400271b30adca43361f29766a5 Mon Sep 17 00:00:00 2001 From: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Wed, 18 Dec 2024 19:01:15 +0200 Subject: [PATCH] only broadcast MAC addr works for regular ARP requests. Refactor link_open --- main.c | 104 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 36 deletions(-) diff --git a/main.c b/main.c index 96c39eb..e85b128 100644 --- a/main.c +++ b/main.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -12,6 +13,7 @@ #include #include +#define FRAME_MIN_LEN 64 #define MTU 1500 void parse_mac(const char* str, uint8_t* mac) { @@ -38,26 +40,19 @@ struct linkinterface { socklen_t if_len; uint8_t host[ETH_ALEN]; - uint8_t gateway[ETH_ALEN]; int fd; // raw socket int if_idx; }; -struct linkinterface* link_parse(const char* if_name, const char* gateway) { +struct linkinterface* link_open(const char* if_name) { struct linkinterface* link = (struct linkinterface*)malloc(sizeof(struct linkinterface)); link->if_name = strdup(if_name); link->if_len = strlen(link->if_name); - parse_mac(gateway, link->gateway); - - return link; -} - -int link_open(struct linkinterface* link) { link->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (link->fd < 0) { - return 1; + goto _bad0; } setsockopt(link->fd, SOL_SOCKET, SO_BINDTODEVICE, link->if_name, link->if_len); @@ -66,18 +61,24 @@ int link_open(struct linkinterface* link) { memset(&netlink, '\0', sizeof(netlink)); strncpy(netlink.ifr_ifrn.ifrn_name, link->if_name, IFNAMSIZ-1); if (ioctl(link->fd, SIOCGIFINDEX, &netlink) < 0) { - return 1; + goto _bad1; } link->if_idx = netlink.ifr_ifru.ifru_ivalue; // index memset(&netlink, '\0', sizeof(netlink)); strncpy(netlink.ifr_ifrn.ifrn_name, link->if_name, IFNAMSIZ-1); if (ioctl(link->fd, SIOCGIFHWADDR, &netlink) < 0) { - return 1; + goto _bad1; } memcpy(link->host, netlink.ifr_ifru.ifru_hwaddr.sa_data, ETH_ALEN); // MAC - return 0; + return link; +_bad1: + close(link->fd); +_bad0: + free(link->if_name); + free(link); + return NULL; } void link_free(struct linkinterface* link) { @@ -86,24 +87,38 @@ void link_free(struct linkinterface* link) { free(link); } -ssize_t link_send(struct linkinterface* link, uint16_t type, uint8_t* packet, size_t len) { - struct ether_header* ether = (struct ether_header*)packet; +ssize_t link_send(struct linkinterface* link, const uint8_t* dstAddr, + uint16_t type, uint8_t* packet, size_t len) +{ + // ETHER FRAME MUST NOT BE LESS THAN 64 (60) + size_t frame_len = MAX(60, len + sizeof(struct ether_header)); + uint8_t* frame = (uint8_t*)malloc(frame_len); + memset(frame, '\0', frame_len); + + struct ether_header* ether = (struct ether_header*)frame; memcpy(ether->ether_shost, link->host, ETH_ALEN); - memcpy(ether->ether_dhost, link->gateway, ETH_ALEN); + memcpy(ether->ether_dhost, dstAddr, ETH_ALEN); ether->ether_type = htons(type); + // copy packet data + memcpy(frame + sizeof(struct ether_header), packet, len); + struct sockaddr_ll ll_addr = {0}; ll_addr.sll_family = PF_PACKET; - //ll_addr.sll_protocol = htons(type); ll_addr.sll_ifindex = link->if_idx; ll_addr.sll_halen = ETH_ALEN; - memcpy(ll_addr.sll_addr, link->gateway, ETH_ALEN); + memcpy(ll_addr.sll_addr, dstAddr, ETH_ALEN); - return sendto(link->fd, packet, len, 0, + size_t sent = sendto(link->fd, frame, frame_len, 0, (const struct sockaddr*)&ll_addr, sizeof(ll_addr)); + free(frame); + + return sent; } -ssize_t link_recv(struct linkinterface* link, uint16_t type, uint8_t* packet, size_t len) { +ssize_t link_recv(struct linkinterface* link, const uint8_t* srcAddr, + uint16_t type, uint8_t* packet, size_t len) +{ char buffer[MTU]; uint16_t want_type = htons(type); do { @@ -112,9 +127,9 @@ ssize_t link_recv(struct linkinterface* link, uint16_t type, uint8_t* packet, si struct ether_header* ether = (struct ether_header*)buffer; // check received packet's source MAC - // if its someone else than gateway - skip - if (memcmp(ether->ether_shost, link->gateway, ETH_ALEN)) { - continue; // not our gateway + // if its someone else than source - skip + if (memcmp(ether->ether_shost, srcAddr, ETH_ALEN)) { + continue; // not our source } if (memcmp(ether->ether_dhost, link->host, ETH_ALEN)) { continue; // not our host @@ -131,7 +146,7 @@ ssize_t link_recv(struct linkinterface* link, uint16_t type, uint8_t* packet, si // TODO: timeout } -#define ARP_HW_ETHER 0x000F +#define ARP_HW_ETHER 0x0001 #define ARP_PT_IP 0x0800 #define ARP_OP_REQUEST 1 @@ -142,8 +157,6 @@ ssize_t link_recv(struct linkinterface* link, uint16_t type, uint8_t* packet, si #define INART_OP_REPLY 9 typedef struct arp_packet_s { - struct ether_header ether; - uint16_t hrd; // Hardware address space (e.g., Ethernet, Packet Radio Net.) uint16_t pro; // Protocol address space. For Ethernet hardware, this is from the set of type fields ether_typ$. uint8_t hln; // byte length of each hardware address @@ -157,32 +170,51 @@ typedef struct arp_packet_s { int main(int argc, char** argv) { // ifname hostMAC gatewayMAC targetMAC - struct linkinterface* link = link_parse(argv[1], argv[2]); - - uint8_t target[ETH_ALEN]; - parse_mac(argv[3], target); - - if (link_open(link) < 0) { + struct linkinterface* link = link_open(argv[1]); + if (!link) { perror("link_open"); return 1; } print_mac(link->host); + uint8_t target[ETH_ALEN]; + parse_mac(argv[2], target); + uint8_t ip[4] = {192, 168, 100, 3}; - // test arp send + // test InARP send + // arp_packet_t arp; + // arp.hrd = htons(ARP_HW_ETHER); + // arp.pro = htons(ARP_PT_IP); + // arp.hln = ETH_ALEN; + // arp.pln = 4; + // arp.op = htons(INARP_OP_REQUEST); + // memcpy(arp.sha, link->host, ETH_ALEN); + // memcpy(arp.spa, ip, 4); + // memcpy(arp.tha, target, ETH_ALEN); + // memset(arp.tpa, '\0', 4); + uint8_t targetIp[4] = {192, 168, 100, 4}; + arp_packet_t arp; arp.hrd = htons(ARP_HW_ETHER); arp.pro = htons(ARP_PT_IP); arp.hln = ETH_ALEN; arp.pln = 4; - arp.op = htons(INARP_OP_REQUEST); + arp.op = htons(ARP_OP_REQUEST); memcpy(arp.sha, link->host, ETH_ALEN); memcpy(arp.spa, ip, 4); - memcpy(arp.tha, target, ETH_ALEN); - memset(arp.tpa, '\0', 4); + memset(arp.tha, '\0', ETH_ALEN); + memcpy(arp.tpa, targetIp, 4); - ssize_t sent = link_send(link, ETHERTYPE_ARP, (uint8_t*)&arp, sizeof(arp)); + + const uint8_t broadcast[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + // ssize_t sent = link_send(link, ETHERTYPE_ARP, (uint8_t*)&arp, sizeof(arp)); + // printf("sent %ld\n", sent); + + // sent = link_send(link, target, ETHERTYPE_ARP, (uint8_t*)&arp, sizeof(arp)); + // printf("sent %ld\n", sent); + + ssize_t sent = link_send(link, broadcast, ETHERTYPE_ARP, (uint8_t*)&arp, sizeof(arp)); printf("sent %ld\n", sent); link_free(link);