diff --git a/main.c b/main.c index 9200fba..a6c3ff4 100644 --- a/main.c +++ b/main.c @@ -8,11 +8,10 @@ #include #include #include -#include -typedef uint8_t mac_t[6]; +#define MTU 1500 -void parse_mac(const char* str, mac_t mac) { +void parse_mac(const char* str, uint8_t* mac) { char* s = strdup(str); char* octet = strtok(s, ":"); int i = 0; @@ -26,27 +25,79 @@ void parse_mac(const char* str, mac_t mac) { free(s); } -int main(int argc, char** argv) { - // ifname hostMAC gatewayMAC targetMAC +void print_mac(uint8_t* mac) { + printf("%02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} - mac_t host, gateway, target; - parse_mac(argv[2], host); - parse_mac(argv[3], gateway); - parse_mac(argv[4], target); +struct linkinterface { + char* if_name; + socklen_t if_len; - int raw = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (raw < 0) { - perror("socket"); + uint8_t host[ETH_ALEN]; + uint8_t gateway[ETH_ALEN]; + + int fd; // raw socket +}; + +struct linkinterface* link_parse(const char* if_name, const char* host, const char* gateway) { + struct linkinterface* link = (struct linkinterface*)malloc(sizeof(struct linkinterface)); + link->if_name = strdup(if_name); + link->if_len = strlen(link->if_name); + + parse_mac(host, link->host); + parse_mac(gateway, link->gateway); +} + +int link_open(struct linkinterface* link) { + link->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (link->fd < 0) { return 1; } - setsockopt(raw, SOL_SOCKET, SO_BINDTODEVICE, argv[1], strlen(argv[1])); + setsockopt(link->fd, SOL_SOCKET, SO_BINDTODEVICE, link->if_name, link->if_name); +} + +void link_free(struct linkinterface* link) { + close(link->fd); + free(link->if_name); + free(link); +} + +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 + uint8_t pln; // byte length of each protocol address + uint16_t op; // opcode (ares_op$REQUEST | ares_op$REPLY) + uint8_t sha[ETH_ALEN]; // Hardware address of sender of this packet + uint8_t spa[4]; // Protocol address of sender of this packet + uint8_t tha[ETH_ALEN]; // Hardware address of sender of this packet + uint8_t tpa[4]; // Protocol address of sender of this packet +} __attribute__((packed)) arp_packet_t; + +#define ARP_OP_REQUEST 0x01 +#define ARP_OP_REPLY 0x02 + +int main(int argc, char** argv) { + // ifname hostMAC gatewayMAC targetMAC + struct linkinterface* link = link_parse(argv[1], argv[2], argv[3]); + + uint8_t target[ETH_ALEN]; + parse_mac(argv[4], target); + + link_open(link); // test receive while (1) { - uint8_t packet[1500]; - ssize_t rd = recv(raw, packet, 1500, 0); - printf("%lu\n", rd); + uint8_t packet[MTU]; + ssize_t rd = recv(link->fd, packet, MTU, 0); + + struct ether_header *ether = (struct ether_header *)&packet[0]; + print_mac(ether->ether_shost); } + link_free(link); return 0; } \ No newline at end of file