- utils: atoip(), lefttrim() - ARP: bunch of bugfixes - TCP, FTP: WIP - DHCP: mutex; query the FSM state
132 lines
3.7 KiB
C
132 lines
3.7 KiB
C
//
|
|
// Created by epagris on 2022.12.10..
|
|
//
|
|
|
|
#include <memory.h>
|
|
#include "arp_cache.h"
|
|
#include "dynmem.h"
|
|
#include "utils.h"
|
|
#include "eth_interface.h"
|
|
#include "prefab/conn_blocks/arp_connblock.h"
|
|
#include "prefab/packet_parsers/arp_packet.h"
|
|
#include "etherlib_options.h"
|
|
|
|
static int arpc_recv_cb(const Pckt * pckt, PcktSieveLayerTag tag) {
|
|
ArpProps * arpProps = HEADER_FETCH_PROPS(ArpProps, pckt->header);
|
|
EthInterface * intf = (EthInterface *) tag.p; // arp_new_connblock() puts pointer to intf into tag field
|
|
bool weAreCalled = (arpProps->OPER == ARPOP_REQ) && (arpProps->PTYPE == ETH_IPv4_PACKET_CLASS) &&
|
|
(arpProps->TPA == intf->ip) && (intf->ip != 0);
|
|
|
|
ArpCache * arpc = intf->arpc;
|
|
|
|
if (weAreCalled) {
|
|
arpc_respond(arpc, arpProps->SHA, arpProps->SPA);
|
|
//MSG("Megy a válasz!\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ArpCache *arpc_new(EthInterface * intf, uint16_t size) {
|
|
// allocate table
|
|
ArpCache * arcp = (ArpCache *) dynmem_alloc(sizeof(ArpCache) + size * sizeof(ArpEntry));
|
|
arcp->size = size;
|
|
arcp->fill = 0;
|
|
|
|
// create connblock
|
|
arcp->cb = arp_new_connblock(intf, arpc_recv_cb);
|
|
return arcp;
|
|
}
|
|
|
|
void arpc_free(ArpCache *aprc) {
|
|
dynmem_free(aprc);
|
|
}
|
|
|
|
void arpc_learn(ArpCache *arpc, const ArpEntry *newEntry) {
|
|
if (newEntry->eth[0] & 0x01) { // don't learn multicast addresses
|
|
return;
|
|
}
|
|
|
|
// TODO: nagyon dummy...
|
|
for (uint16_t i = 0; i < arpc->fill; i++) {
|
|
ArpEntry * entry = arpc->entries + i;
|
|
if (!memcmp(entry->eth, newEntry->eth, ETH_HW_ADDR_LEN) && (entry->ip == newEntry->ip)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// if not found...
|
|
arpc->entries[arpc->fill++] = *newEntry;
|
|
}
|
|
|
|
const ArpEntry *arpc_get(ArpCache *arpc, ip4_addr ip) {
|
|
// search in the cache
|
|
for (uint16_t i = 0; i < arpc->fill; i++) {
|
|
ArpEntry * entry = arpc->entries + i;
|
|
if (entry->ip == ip) {
|
|
return entry;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const ArpEntry *arpc_get_ask(ArpCache *arpc, ip4_addr ip) {
|
|
const ArpEntry * entry = arpc_get(arpc, ip);
|
|
if (entry != NULL) {
|
|
return entry;
|
|
}
|
|
|
|
// not found in the cache, probe the network
|
|
uint32_t attemptN = 0;
|
|
while (((entry = arpc_get(arpc, ip)) == NULL) && (attemptN < ETHLIB_ARP_RETRY_COUNT)) {
|
|
arpc_ask(arpc, ip);
|
|
ETHLIB_SLEEP_MS(20);
|
|
attemptN++;
|
|
}
|
|
|
|
return entry;
|
|
}
|
|
|
|
void arpc_dump(ArpCache *arpc) {
|
|
for (uint16_t i = 0; i < arpc->fill; i++) {
|
|
ArpEntry * entry = arpc->entries + i;
|
|
PRINT_IPv4(entry->ip);
|
|
MSG(" -> %02x:%02x:%02x:%02x:%02x:%02x\n", entry->eth[0], entry->eth[1], entry->eth[2], entry->eth[3], entry->eth[4], entry->eth[5]);
|
|
}
|
|
MSG("\n");
|
|
}
|
|
|
|
void arpc_ask(ArpCache *arpc, ip4_addr addr) {
|
|
ArpProps arpProps;
|
|
|
|
arpProps.HTYPE = 1;
|
|
arpProps.PTYPE = ETH_IPv4_PACKET_CLASS;
|
|
arpProps.HLEN = ETH_HW_ADDR_LEN;
|
|
arpProps.PLEN = sizeof(ip4_addr);
|
|
arpProps.OPER = ARPOP_REQ;
|
|
|
|
memcpy(arpProps.SHA, arpc->cb.sieve->intf->mac, ETH_HW_ADDR_LEN);
|
|
arpProps.SPA = arpc->cb.sieve->intf->ip;
|
|
memset(arpProps.THA, 0x00, ETH_HW_ADDR_LEN);
|
|
arpProps.TPA = addr;
|
|
|
|
arp_send(&arpc->cb, &arpProps);
|
|
}
|
|
|
|
void arpc_respond(ArpCache *arpc, const EthernetAddress hwAddr, ip4_addr ipAddr) {
|
|
ArpProps arpProps = { 0 };
|
|
|
|
arpProps.HTYPE = 1;
|
|
arpProps.PTYPE = ETH_IPv4_PACKET_CLASS;
|
|
arpProps.HLEN = ETH_HW_ADDR_LEN;
|
|
arpProps.PLEN = sizeof(ip4_addr);
|
|
arpProps.OPER = ARPOP_REP;
|
|
|
|
memcpy(arpProps.SHA, arpc->cb.sieve->intf->mac, ETH_HW_ADDR_LEN);
|
|
arpProps.SPA = arpc->cb.sieve->intf->ip;
|
|
memcpy(arpProps.THA, hwAddr, ETH_HW_ADDR_LEN);
|
|
arpProps.TPA = ipAddr;
|
|
|
|
arp_send(&arpc->cb, &arpProps);
|
|
} |