125 lines
3.8 KiB
C
125 lines
3.8 KiB
C
#include <assert.h>
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include "defs.h"
|
|
|
|
#define ARP_MAX_PENDING_REQUESTS 32
|
|
#define ARP_TRANSLATION_TABLE_SIZE 128
|
|
|
|
typedef enum {
|
|
ARP_RESOLUTION_OK,
|
|
ARP_RESOLUTION_FAILED,
|
|
ARP_RESOLUTION_TIMEOUT,
|
|
} arp_resolution_status_t;
|
|
|
|
typedef struct arp_translation_table_entry_t arp_translation_table_entry_t;
|
|
struct arp_translation_table_entry_t {
|
|
arp_translation_table_entry_t *prev;
|
|
arp_translation_table_entry_t *next;
|
|
mac_address_t mac;
|
|
ip_address_t ip;
|
|
uint64_t timeout;
|
|
};
|
|
|
|
typedef struct {
|
|
uint64_t time;
|
|
arp_translation_table_entry_t *used_list_head;
|
|
arp_translation_table_entry_t *used_list_tail;
|
|
arp_translation_table_entry_t *free_list;
|
|
arp_translation_table_entry_t entries[ARP_TRANSLATION_TABLE_SIZE];
|
|
} arp_translation_table_t;
|
|
|
|
typedef struct arp_pending_request_t arp_pending_request_t;
|
|
struct arp_pending_request_t {
|
|
arp_pending_request_t *prev;
|
|
arp_pending_request_t *next;
|
|
ip_address_t ip;
|
|
uint64_t timeout;
|
|
void *callback_data;
|
|
void (*callback)(void*, arp_resolution_status_t status, mac_address_t);
|
|
};
|
|
|
|
typedef enum {
|
|
ARP_HARDWARE_ETHERNET = 1,
|
|
} arp_hardware_type;
|
|
|
|
typedef enum {
|
|
ARP_PROTOCOL_IP = 0x800,
|
|
} arp_protocol_type;
|
|
|
|
typedef enum {
|
|
ARP_OPERATION_REQUEST = 1,
|
|
ARP_OPERATION_REPLY = 2,
|
|
} arp_operation_t;
|
|
|
|
typedef struct __attribute__((__packed__)) {
|
|
uint16_t hardware_type;
|
|
uint16_t protocol_type;
|
|
uint8_t hardware_len;
|
|
uint8_t protocol_len;
|
|
uint16_t operation_type;
|
|
mac_address_t sender_hardware_address;
|
|
ip_address_t sender_protocol_address;
|
|
mac_address_t target_hardware_address;
|
|
ip_address_t target_protocol_address;
|
|
} arp_packet_t;
|
|
|
|
static_assert(offsetof(arp_packet_t, hardware_type) == 0);
|
|
static_assert(offsetof(arp_packet_t, protocol_type) == 2);
|
|
static_assert(offsetof(arp_packet_t, hardware_len) == 4);
|
|
static_assert(offsetof(arp_packet_t, protocol_len) == 5);
|
|
static_assert(offsetof(arp_packet_t, operation_type) == 6);
|
|
static_assert(offsetof(arp_packet_t, sender_hardware_address) == 8);
|
|
static_assert(offsetof(arp_packet_t, sender_protocol_address) == 14);
|
|
static_assert(offsetof(arp_packet_t, target_hardware_address) == 18);
|
|
static_assert(offsetof(arp_packet_t, target_protocol_address) == 24);
|
|
static_assert(sizeof(arp_packet_t) == 28);
|
|
|
|
typedef struct {
|
|
|
|
uint64_t time;
|
|
uint64_t cache_timeout;
|
|
uint64_t request_timeout;
|
|
|
|
arp_packet_t *output;
|
|
|
|
void *send_data;
|
|
void (*send)(void *send_data, mac_address_t dest_mac);
|
|
|
|
ip_address_t self_ip;
|
|
mac_address_t self_mac;
|
|
arp_translation_table_t table;
|
|
|
|
arp_pending_request_t *pending_request_free_list;
|
|
arp_pending_request_t *pending_request_used_list;
|
|
arp_pending_request_t *pending_request_used_tail;
|
|
arp_pending_request_t pending_request_pool[ARP_MAX_PENDING_REQUESTS];
|
|
} arp_state_t;
|
|
|
|
typedef enum {
|
|
ARP_PROCESS_RESULT_HWARENOTSUPP,
|
|
ARP_PROCESS_RESULT_PROTONOTSUPP,
|
|
ARP_PROCESS_RESULT_INVALID,
|
|
ARP_PROCESS_RESULT_OK,
|
|
} arp_process_result_t;
|
|
|
|
void arp_init(arp_state_t *state,
|
|
ip_address_t ip,
|
|
mac_address_t mac,
|
|
void *send_data,
|
|
void (*send)(void*, mac_address_t));
|
|
|
|
void arp_free(arp_state_t *state);
|
|
|
|
arp_process_result_t
|
|
arp_process_packet(arp_state_t *state,
|
|
const void *packet,
|
|
size_t len);
|
|
|
|
void arp_resolve_mac(arp_state_t *state,
|
|
ip_address_t ip,
|
|
void *userp,
|
|
void (*callback)(void*, arp_resolution_status_t, mac_address_t));
|
|
|
|
void arp_ms_passed(arp_state_t *state, size_t ms);
|
|
void arp_change_output_buffer(arp_state_t *state, void *ptr, size_t max); |