- Memory leak caused by packet drop fixed - MemoryPool warns about possible double free
83 lines
2.8 KiB
C
83 lines
2.8 KiB
C
#include "icmp_connblock.h"
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "../packet_parsers/packet_parsers.h"
|
|
#include "../../utils.h"
|
|
#include "../../dynmem.h"
|
|
#include "../../pckt_assembler.h"
|
|
#include "../../eth_interface.h"
|
|
#include "../packet_parsers/icmp_packet.h"
|
|
#include "ipv4_connblock.h"
|
|
|
|
static bool filtIcmp(const PcktSieveFilterCondition * filtCond, const PcktProps * contProps, const PcktProps * ownProps, EthInterface * intf) {
|
|
IPv4Props * ipProps = (IPv4Props *) contProps;
|
|
IcmpProps * icmpProps = (IcmpProps *) ownProps;
|
|
|
|
return ipProps->Protocol == ETH_ICMP_PACKET_CLASS;
|
|
}
|
|
|
|
static int icmp_recv_cb(const Pckt * pckt, PcktSieveLayerTag tag) {
|
|
IcmpProps * icmpProps = HEADER_FETCH_PROPS(IcmpProps, pckt->header);
|
|
EthInterface * intf = (EthInterface *) tag.p; // icmp_new_connblock() puts pointer to intf into tag field
|
|
|
|
switch (icmpProps->type) {
|
|
case ICMP_MT_ECHO_REQUEST: {
|
|
icmpProps->type = ICMP_MT_ECHO_REPLY; // replace request with reply
|
|
icmpProps->hdrInsFn = insert_icmp_header;
|
|
|
|
// swap source an destination IP addresses
|
|
IPv4Props * iPv4Props = HEADER_FETCH_PROPS(IPv4Props, pckt->header->prev);
|
|
ip4_addr tmpIp = iPv4Props->SourceIPAddr;
|
|
iPv4Props->SourceIPAddr = iPv4Props->DestIPAddr;
|
|
iPv4Props->DestIPAddr = tmpIp;
|
|
iPv4Props->hdrInsFn = insert_ipv4_header;
|
|
|
|
// swap Ethernet fields
|
|
EthernetAddress tmpEth;
|
|
EthernetProps * ethProps = HEADER_FETCH_PROPS(EthernetProps, pckt->header->prev->prev);
|
|
HWACPY(tmpEth, ethProps->sourceAddr);
|
|
HWACPY(ethProps->sourceAddr, ethProps->destAddr);
|
|
HWACPY(ethProps->destAddr, tmpEth);
|
|
ethProps->hdrInsFn = insert_ethernet_header;
|
|
|
|
// payload is the same...
|
|
|
|
// assemble packet
|
|
RawPckt raw;
|
|
pckt_assemble(&raw, pckt);
|
|
|
|
// release headers
|
|
//pckthdr_chain_free(pckt->header);
|
|
|
|
ethinf_transmit(intf, &raw);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ConnBlock icmp_new_connblock(EthInterface * intf) {
|
|
ConnBlock icmpConnB;
|
|
ConnBlock ipConnB = ipv4_new_connblock(intf, IPv4_IF_ADDR, NULL); // create new IPv4 connection block
|
|
|
|
PcktSieveFilterCondition filtCond;
|
|
packfiltcond_zero(&filtCond);
|
|
PcktSieveLayerTag tag;
|
|
tag.p = intf; // Ethernet-interface passed in 'tag.p'
|
|
icmpConnB.sieveLayer = packsieve_new_layer(ipConnB.sieveLayer, &filtCond, false, filtIcmp, icmp_recv_cb, tag, ETH_ICMP_PACKET_CLASS);
|
|
ASSERT_NULL(icmpConnB.sieveLayer);
|
|
|
|
icmpConnB.sieve = &intf->sieve;
|
|
icmpConnB.sieveLayer->connBReportFn = icmp_print_report;
|
|
|
|
return icmpConnB;
|
|
}
|
|
|
|
void icmp_print_report(const ConnBlock *connBlock) {
|
|
INFO("ICMP (ping)");
|
|
}
|